forked from lix-project/lix
optimize removeAttrs builtin
use a sorted array of symbols to be removed instead of a set. this saves a lot of memory allocations and slightly speeds up removal.
This commit is contained in:
parent
6401e443a4
commit
c9fc975259
|
@ -121,6 +121,8 @@ class BindingsBuilder
|
||||||
Bindings * bindings;
|
Bindings * bindings;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// needed by std::back_inserter
|
||||||
|
using value_type = Attr;
|
||||||
|
|
||||||
EvalState & state;
|
EvalState & state;
|
||||||
|
|
||||||
|
@ -134,6 +136,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(const Attr & attr)
|
void insert(const Attr & attr)
|
||||||
|
{
|
||||||
|
push_back(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const Attr & attr)
|
||||||
{
|
{
|
||||||
bindings->push_back(attr);
|
bindings->push_back(attr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "value-to-xml.hh"
|
#include "value-to-xml.hh"
|
||||||
#include "primops.hh"
|
#include "primops.hh"
|
||||||
|
|
||||||
|
#include <boost/container/small_vector.hpp>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -2270,21 +2272,25 @@ static void prim_removeAttrs(EvalState & state, const Pos & pos, Value * * args,
|
||||||
state.forceAttrs(*args[0], pos);
|
state.forceAttrs(*args[0], pos);
|
||||||
state.forceList(*args[1], pos);
|
state.forceList(*args[1], pos);
|
||||||
|
|
||||||
/* Get the attribute names to be removed. */
|
/* Get the attribute names to be removed.
|
||||||
std::set<Symbol> names;
|
We keep them as Attrs instead of Symbols so std::set_difference
|
||||||
|
can be used to remove them from attrs[0]. */
|
||||||
|
boost::container::small_vector<Attr, 64> names;
|
||||||
|
names.reserve(args[1]->listSize());
|
||||||
for (auto elem : args[1]->listItems()) {
|
for (auto elem : args[1]->listItems()) {
|
||||||
state.forceStringNoCtx(*elem, pos);
|
state.forceStringNoCtx(*elem, pos);
|
||||||
names.insert(state.symbols.create(elem->string.s));
|
names.emplace_back(state.symbols.create(elem->string.s), nullptr);
|
||||||
}
|
}
|
||||||
|
std::sort(names.begin(), names.end());
|
||||||
|
|
||||||
/* Copy all attributes not in that set. Note that we don't need
|
/* Copy all attributes not in that set. Note that we don't need
|
||||||
to sort v.attrs because it's a subset of an already sorted
|
to sort v.attrs because it's a subset of an already sorted
|
||||||
vector. */
|
vector. */
|
||||||
auto attrs = state.buildBindings(args[0]->attrs->size());
|
auto attrs = state.buildBindings(args[0]->attrs->size());
|
||||||
for (auto & i : *args[0]->attrs) {
|
std::set_difference(
|
||||||
if (!names.count(i.name))
|
args[0]->attrs->begin(), args[0]->attrs->end(),
|
||||||
attrs.insert(i);
|
names.begin(), names.end(),
|
||||||
}
|
std::back_inserter(attrs));
|
||||||
v.mkAttrs(attrs.alreadySorted());
|
v.mkAttrs(attrs.alreadySorted());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue