forked from lix-project/lix
shrink Attr by 8 bytes on 64bit machines
with position and symbol tables in place we can now shrink Attr by a full pointer with some simple field reordering. since Attr is a very hot struct this has substantial impact on memory use, decreasing GC allocations and heap size by 10-15% each. we also get a ~15% performance improvement due to reduced GC loading. pure parsing has taken a hit over the branch base because positions are now slightly more expensive to create, but overall we get a noticeable improvement. before (on memory-friendliness): Benchmark 1: nix search --no-eval-cache --offline ../nixpkgs hello Time (mean ± σ): 6.960 s ± 0.028 s [User: 5.832 s, System: 0.897 s] Range (min … max): 6.886 s … 7.005 s 20 runs Benchmark 2: nix eval -f ../nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix Time (mean ± σ): 328.1 ms ± 1.7 ms [User: 295.8 ms, System: 32.2 ms] Range (min … max): 324.9 ms … 331.2 ms 20 runs Benchmark 3: nix eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' Time (mean ± σ): 2.688 s ± 0.029 s [User: 2.365 s, System: 0.238 s] Range (min … max): 2.642 s … 2.742 s 20 runs after: Benchmark 1: nix search --no-eval-cache --offline ../nixpkgs hello Time (mean ± σ): 6.902 s ± 0.039 s [User: 5.844 s, System: 0.783 s] Range (min … max): 6.820 s … 6.956 s 20 runs Benchmark 2: nix eval -f ../nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix Time (mean ± σ): 330.7 ms ± 2.2 ms [User: 300.6 ms, System: 30.0 ms] Range (min … max): 327.5 ms … 334.5 ms 20 runs Benchmark 3: nix eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' Time (mean ± σ): 2.330 s ± 0.027 s [User: 2.040 s, System: 0.234 s] Range (min … max): 2.272 s … 2.383 s 20 runs
This commit is contained in:
parent
8775be3393
commit
8168a4cf4a
|
@ -15,11 +15,15 @@ struct Value;
|
||||||
/* Map one attribute name to its value. */
|
/* Map one attribute name to its value. */
|
||||||
struct Attr
|
struct Attr
|
||||||
{
|
{
|
||||||
|
/* the placement of `name` and `pos` in this struct is important.
|
||||||
|
both of them are uint32 wrappers, they are next to each other
|
||||||
|
to make sure that Attr has no padding on 64 bit machines. that
|
||||||
|
way we keep Attr size at two words with no wasted space. */
|
||||||
SymbolIdx name;
|
SymbolIdx name;
|
||||||
Value * value;
|
|
||||||
PosIdx pos;
|
PosIdx pos;
|
||||||
|
Value * value;
|
||||||
Attr(SymbolIdx name, Value * value, PosIdx pos = noPos)
|
Attr(SymbolIdx name, Value * value, PosIdx pos = noPos)
|
||||||
: name(name), value(value), pos(pos) { };
|
: name(name), pos(pos), value(value) { };
|
||||||
Attr() { };
|
Attr() { };
|
||||||
bool operator < (const Attr & a) const
|
bool operator < (const Attr & a) const
|
||||||
{
|
{
|
||||||
|
@ -27,6 +31,11 @@ struct Attr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(Attr) == 2 * sizeof(uint32_t) + sizeof(Value *),
|
||||||
|
"performance of the evaluator is highly sensitive to the size of Attr. "
|
||||||
|
"avoid introducing any padding into Attr if at all possible, and do not "
|
||||||
|
"introduce new fields that need not be present for almost every instance.");
|
||||||
|
|
||||||
/* Bindings contains all the attributes of an attribute set. It is defined
|
/* Bindings contains all the attributes of an attribute set. It is defined
|
||||||
by its size and its capacity, the capacity being the number of Attr
|
by its size and its capacity, the capacity being the number of Attr
|
||||||
elements allocated after this structure, while the size corresponds to
|
elements allocated after this structure, while the size corresponds to
|
||||||
|
|
Loading…
Reference in a new issue