Closed Bug 1375331 Opened 3 years ago Closed 3 years ago

nsPresArena::Allocate calls free() a lot


(Core :: Layout, defect, P3)




Tracking Status
firefox-esr52 --- wontfix
firefox54 --- wontfix
firefox55 --- wontfix
firefox56 --- fixed


(Reporter: mats, Assigned: mats)


(Blocks 1 open bug)


(Keywords: perf, regression, Whiteboard: [qf])


(1 file)

I'm looking at a perf log where I see lot's of calls to free() on this path:

I'm pretty sure it comes from removing an entry from the FreeList::mEntries:

nsTArray::RemoveElementAt calls ShiftData which calls ShrinkCapacity:
*currently* only if it becomes empty, but I don't think we should count on that.
Anyway, I don't see a reason to free the array buffer even if it becomes empty
because it will surely be non-empty very soon again.


(bug 497495 is where we started using nsTArray for this, AFAICT)
Shows up in Speedometer.
calls: the number of calls to nsPresArena::Allocate where we end up
       taking an object off a free list (i.e. the number of times
       we hit the changed code)
large: same as calls, but where "list->mEntries.Capacity() > 500" is true
       (which corresponds to a malloc size of 4096 bytes or more)
arenas: the number of alive arenas at the end of the test time
free: the number of times free() called from here
overhead: the number of allocated bytes in free list arrays that
          aren't used
histogram: occurences of transitions to empty per malloc size

before: calls=22015 arenas=24 free=2701 overhead=9600 bytes
after:  large=0 arenas=19 free=0 overhead=14784 bytes
histogram[16]: 503
histogram[32]: 427
histogram[64]: 341
histogram[128]: 122
histogram[256]: 397
histogram[512]: 153
histogram[1024]: 24
histogram[2048]: 81
before: calls=20891 arenas=8 free=1598 overhead=9896 bytes
after:  large=4199 arenas=8 free=3 overhead=13424 bytes
histogram[16]: 319
histogram[32]: 574
histogram[64]: 178
histogram[128]: 86
histogram[256]: 205
histogram[512]: 99
histogram[1024]: 155
histogram[2048]: 9
histogram[4096]: 3
before: calls=21958 arenas=6 free=842 overhead=16504 bytes
after:  large=12434 arenas=5 free=7 overhead=28248 bytes
histogram[16]: 153
histogram[32]: 108
histogram[64]: 29
histogram[128]: 164
histogram[256]: 48
histogram[512]: 263
histogram[1024]: 1
histogram[2048]: 17
histogram[4096]: 2
histogram[8192]: 2
histogram[16384]: 1
histogram[32768]: 2
before: calls=5724 arenas=11 free=1084 overhead=8064 bytes
after:  large=77 arenas=11 free=0 overhead=9280 bytes
histogram[16]: 257
histogram[32]: 235
histogram[64]: 181
histogram[128]: 141
histogram[256]: 273
histogram[512]: 4

The test is: load the URL using a fresh profile and wait 1 minute
15 seconds, then measure the overhead over all arenas.
(Using "firefox -layoutdebug" (at 800x1000) to minimize UI overhead)


Conclusion: the overhead increases but the numbers are fairly small.
In exchange, we almost eradicate the number of malloc/free calls
associated with these arrays.

Note 1: we should save at least the same amount of malloc calls as
the "free" numbers above

Note 2: the difference in number of arenas before/after is likely due
to ads and other dynamic effects, so all numbers are ball park figures
FTR, resizing the window tilts the histogram even more towards
lower sizes.
(I'm removing the "LIFO behavior for best cache utilization" because
I think it's obsolete - it's about the linked list implementation
we had before bug 497495.)
Attachment #8880974 - Flags: review?(dbaron)
Attachment #8880974 - Flags: review?(dbaron) → review+
Pushed by
Retain the array buffer for PresArena free lists if it's 2048 bytes or less to avoid malloc/free churn.  r=dbaron
Closed: 3 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla56
You need to log in before you can comment on or make changes to this bug.