mirror of
https://github.com/NixOS/nix.git
synced 2025-11-14 14:32:42 +01:00
Add builtins.unique [WIP]
This cuts ~4.5s from "nix-env -qaP -f `<nixpkgs>` --out-path" and reduces memory allocations from 7.49 to 7.16 GiB. Note that builtins.unique requires a less-than comparator function, which is a change from the 'unique' function in Nixpkgs which uses an equality function.
This commit is contained in:
parent
bb6e6923f2
commit
a3d874175c
1 changed files with 59 additions and 1 deletions
|
|
@ -341,6 +341,8 @@ struct CompareValues
|
||||||
return strcmp(v1->string.s, v2->string.s) < 0;
|
return strcmp(v1->string.s, v2->string.s) < 0;
|
||||||
case tPath:
|
case tPath:
|
||||||
return strcmp(v1->path, v2->path) < 0;
|
return strcmp(v1->path, v2->path) < 0;
|
||||||
|
case tAttrs:
|
||||||
|
return v1 < v2; // FIXME
|
||||||
default:
|
default:
|
||||||
throw EvalError(format("cannot compare %1% with %2%") % showType(*v1) % showType(*v2));
|
throw EvalError(format("cannot compare %1% with %2%") % showType(*v1) % showType(*v2));
|
||||||
}
|
}
|
||||||
|
|
@ -1576,7 +1578,6 @@ static void prim_sort(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
v.listElems()[n] = args[1]->listElems()[n];
|
v.listElems()[n] = args[1]->listElems()[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto comparator = [&](Value * a, Value * b) {
|
auto comparator = [&](Value * a, Value * b) {
|
||||||
/* Optimization: if the comparator is lessThan, bypass
|
/* Optimization: if the comparator is lessThan, bypass
|
||||||
callFunction. */
|
callFunction. */
|
||||||
|
|
@ -1596,6 +1597,62 @@ static void prim_sort(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void prim_unique(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
|
{
|
||||||
|
state.forceFunction(*args[0], pos);
|
||||||
|
state.forceList(*args[1], pos);
|
||||||
|
|
||||||
|
auto len = args[1]->listSize();
|
||||||
|
|
||||||
|
Value * vs[len];
|
||||||
|
for (size_t n = 0; n < len; ++n) {
|
||||||
|
auto v2 = args[1]->listElems()[n];
|
||||||
|
state.forceValue(*v2);
|
||||||
|
vs[n] = v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto comparator = [&](Value * a, Value * b) {
|
||||||
|
/* Optimization: if the comparator is lessThan, bypass
|
||||||
|
callFunction. */
|
||||||
|
if (args[0]->type == tPrimOp && args[0]->primOp->fun == prim_lessThan)
|
||||||
|
return CompareValues()(a, b);
|
||||||
|
|
||||||
|
Value vTmp1, vTmp2;
|
||||||
|
state.callFunction(*args[0], *a, vTmp1, pos);
|
||||||
|
state.callFunction(vTmp1, *b, vTmp2, pos);
|
||||||
|
return state.forceBool(vTmp2, pos);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::sort(vs, vs + len, comparator);
|
||||||
|
|
||||||
|
auto outLen = std::min((size_t) 1, len);
|
||||||
|
for (size_t n = 1; n < len; n++) {
|
||||||
|
if (comparator(vs[outLen - 1], vs[n])) {
|
||||||
|
vs[outLen++] = vs[n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(vs, vs + outLen);
|
||||||
|
|
||||||
|
state.mkList(v, outLen);
|
||||||
|
|
||||||
|
size_t outPos = 0;
|
||||||
|
for (size_t n = 0; n < len; n++) {
|
||||||
|
auto v2 = args[1]->listElems()[n];
|
||||||
|
auto i = std::lower_bound(vs, vs + outLen, v2);
|
||||||
|
if (*i == v2) {
|
||||||
|
// Remove v2 from the set by setting its least significant
|
||||||
|
// bit. (This doesn't change the sort order.)
|
||||||
|
*i = (Value *) (((ptrdiff_t) v2) | 1);
|
||||||
|
assert(outPos < outLen);
|
||||||
|
v.listElems()[outPos++] = v2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(outPos == outLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void prim_partition(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_partition(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceFunction(*args[0], pos);
|
state.forceFunction(*args[0], pos);
|
||||||
|
|
@ -2240,6 +2297,7 @@ void EvalState::createBaseEnv()
|
||||||
addPrimOp("__all", 2, prim_all);
|
addPrimOp("__all", 2, prim_all);
|
||||||
addPrimOp("__genList", 2, prim_genList);
|
addPrimOp("__genList", 2, prim_genList);
|
||||||
addPrimOp("__sort", 2, prim_sort);
|
addPrimOp("__sort", 2, prim_sort);
|
||||||
|
addPrimOp("__unique", 2, prim_unique);
|
||||||
addPrimOp("__partition", 2, prim_partition);
|
addPrimOp("__partition", 2, prim_partition);
|
||||||
addPrimOp("__concatMap", 2, prim_concatMap);
|
addPrimOp("__concatMap", 2, prim_concatMap);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue