| author | |
| committer | |
| log | a03711b1e3921b2e088e4ee05277497e6143355c |
| tree | ef92dad92dd48c40ce58f583dea9347ed9e707f6 |
| parent | 0fe0d69c63888d92a959ff20ad032348b5a2bd53 |
The old logic here meant that if you had a parent node with a large
number of small child nodes being added to it, the parent node would
grow in small steps instead of exponentially. If there was insufficient
space for the parent node to grow, it would jump over its siblings,
leaving a vacant space. If the siblings were also hitting this case, the
nodes would end up "leapfrogging" over one another constantly, never
re-using the vacant region before them (due to the node allocation logic
in `MappedFile` currently being quite simplistic). In these conditions,
because the nodes were adding wasted space every time they wanted to
grow just *slightly*, the file size could get truly ridiculous---at
worst, binaries which should be on the order of a few hundred megabytes
could potentially reach the order of 100 *gigabytes*.
The `MappedFile.growth_factor` constant solves exactly this class of
problem by using exponential growth to bound the number of wasted bytes
in the file, so the fix is simply to actually use it when expanding a
parent node to make space for a new child.1 files changed, 1 insertions(+), 1 deletions(-)
src/link/MappedFile.zig+1-1| ... | @@ -572,7 +572,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct { | ... | @@ -572,7 +572,7 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct { |
| 572 | .none => { | 572 | .none => { |
| 573 | _, const parent_size = opts.parent.location(mf).resolve(mf); | 573 | _, const parent_size = opts.parent.location(mf).resolve(mf); |
| 574 | if (new_end > parent_size) | 574 | if (new_end > parent_size) |
| 575 | try opts.parent.resize(mf, gpa, new_end); | 575 | try opts.parent.resize(mf, gpa, new_end +| new_end / growth_factor); |
| 576 | }, | 576 | }, |
| 577 | else => |next_ni| { | 577 | else => |next_ni| { |
| 578 | const next_offset, _ = next_ni.location(mf).resolve(mf); | 578 | const next_offset, _ = next_ni.location(mf).resolve(mf); |