Open Bug 1364359 Opened 8 years ago Updated 9 hours ago

Allow the removal of non-empty arenas, including thread local arenas.

Categories

(Core :: Memory Allocator, enhancement, P3)

enhancement

Tracking

()

ASSIGNED

People

(Reporter: glandium, Assigned: pbone)

References

(Depends on 1 open bug, Blocks 4 open bugs)

Details

Attachments

(9 files, 2 obsolete files)

48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
The arenas created in the jemalloc_thread_local_arena function added in bug 1361258 are leaked on purpose. This bug is about not leaking them and properly terminating them (they might not be empty when jemalloc_thread_local_arena(false) is called).
No longer blocks: 1052579
Priority: -- → P3
Blocks: 1377999

Can someone educate me the status of this bug?

I used moz_create_arena in bug 1377999, and I'd like know whether this is a blocker of my patch.

If I can't manually call moz_dispose_arena at the moment, will it be disposed sometime later?

Thanks

(In reply to Sean Feng [:sefeng] from comment #1)

Can someone educate me the status of this bug?

We think bug 1596300 will help out here, it's currently be worked on but is more of proof-of-concept right now.

I used moz_create_arena in bug 1377999, and I'd like know whether this is a blocker of my patch.

It really depends on how many you expect to create and whether or not you can reuse them. Mike probably has a better idea of the overhead of leaving them around.

If I can't manually call moz_dispose_arena at the moment, will it be disposed sometime later?

My understanding is they'll stick around until process shutdown. If these are limited to content processes this might not be a huge issue once fission is enabled.

Flags: needinfo?(mh+mozilla)

What Eric said is accurate. At the moment, using moz_create_arena is not recommended except if the arena is meant to last until the end of the process. So for example, creating an arena for all DOM nodes in a process is fine, but creating an arena for all DOM nodes per page is not (with multiple pages per process).

Flags: needinfo?(mh+mozilla)
Blocks: 1649140
Severity: normal → S3

Note that currently we rely in quite some places on the arena not going away after having done gArenas.GetById outside the the collection's lock. We might be able to ensure that this pattern is used only on the main thread and add some API that allows us to run the effective dispose only ever on the main thread, too. Or in alternative we might want some additional mutex and/or reference counting for arenas.

Bug 1950041 prevented the deletion of all arenas, but this bug still blocks public (thread-local) arena deletion. One potential solution would be either to merge arenas into an orphaned threads arena when a thread terminates, or to delete the arena once its last object is freed.

Thread local arenas can now be destroyed, non-empty thread-local arenas will
be destroyed after their last object is freed, even if that's later from a
different thread. Thread local arenas will be destroyed implicitly when a
thread exits.

Assignee: nobody → pbone
Status: NEW → ASSIGNED
Depends on: 1980064
Attachment #9478214 - Attachment is obsolete: true

It's strange but this blocks Bug 1980064 because thread-local structures in the allocator that refer to arenas may still be alive after an arena is destroyed. So we need to refcount arenas, and allow the removal of non-empty arenas, before we can implement TLS. That has the side-effect of no-longer leaking thread local arenas. So let's do that!

Blocks: 1980064
Depends on: 1976184
No longer depends on: 1980064
Summary: Properly cleanup thread-local arenas → Allow the removal of non-empty arenas, including thread local arenas.

In the short term this will simplify logic that prevents an arena with a
purge request from being deleted before removing the purge request.

However the main motivation for this change is to keep an arena alive
until all thread local structures that refer to it have been cleaned up.

  • Two new classes, RefPtrRedBlackTree and RefPtrDoublyLinkedList, have
    been created that wrap their namesakes and manipulates refcounts
    during insertion and removal.
  • A RefPtrUtils.h file has been added that includes a safe refcounting
    mixin class.

  • Because huge allocations now hold a refptr to the arena, deleting an
    arena that has only huge allocations will no-longer crash.
    TestJemalloc.cpp has been updated.

The places that hold references to arenas are:

  • The ArenaCollection
  • The purge request list.
  • Huge allocations stored outside the arena structure but belonging to
    the arena.
  • Some automatic stack variables when there's a chance another
    reference to the arena could be dropped, eg DisposeArena.

Thread local arenas are still leaked, threads have a raw pointer to
their arena, they are kept alive by ArenaCollection.

The delete statement was removed in the previous patch. This patch
removes some of the logic for deleting arenas after purge. It keeps
just enough logic so that purge can exit early for a dying arena.

"remove" is more accurate since the arena might not be destroyed if
other things hold a reference.

Disposing a non-empty arena will now move it to a tree for disposed
arenas. This allows purging and jemalloc_stats to continue to process
it. Once it is empty it will be removed from this tree (dropping the
last reference).

Thread local arenas are now stored within a special class which removes
them from the arena collection when its destructor runs. Because arenas
aren't removed until they're empty this is safe and ensures that thread
local arenas won't be leaked.

Attachment #9533251 - Attachment description: WIP: Bug 1364359 - pt 1. Mozjemalloc arenas are now refcounted → WIP: Bug 1364359 - pt 2. Mozjemalloc arenas are now refcounted
Attachment #9533252 - Attachment description: WIP: Bug 1364359 - pt 2. Simplify code for deleting arenas after purge → WIP: Bug 1364359 - pt 3. Simplify code for deleting arenas after purge
Attachment #9533253 - Attachment description: WIP: Bug 1364359 - pt 3. Rename DisposeArena to RemoveArena → WIP: Bug 1364359 - pt 4. Rename DisposeArena to RemoveArena
Attachment #9533254 - Attachment description: WIP: Bug 1364359 - pt 4. Add locking annotation to mNumOperationsRemovedArenas → WIP: Bug 1364359 - pt 5. Add locking annotation to mNumOperationsRemovedArenas
Attachment #9533255 - Attachment description: WIP: Bug 1364359 - pt 5. Support deleting non-empty arenas → WIP: Bug 1364359 - pt 6. Support deleting non-empty arenas
Attachment #9533256 - Attachment description: WIP: Bug 1364359 - pt 6. Thread local arenas are no-longer leaked → WIP: Bug 1364359 - pt 7. Thread local arenas are no-longer leaked
Attachment #9533257 - Attachment description: WIP: Bug 1364359 - pt 7. Refactoring in arena_t::~arena_t() → WIP: Bug 1364359 - pt 8. Refactoring in arena_t::~arena_t()

This makes it safe for thread local storage code supplied by the
libraries/compiler, such as C++'s thread_local keyword to call malloc.

malloc_initialised is now an enum to represent which phases have
completed.

malloc_init_hard() is called the first time that malloc() is used it
performs the first phase.

malloc_init_tls() is called the first time jemalloc_local_arena() is
used, it performs the second phase.

This also refactors choose_arena adding a branch annotation to the most
likely branch.

Attachment #9533256 - Attachment description: WIP: Bug 1364359 - pt 7. Thread local arenas are no-longer leaked → WIP: Bug 1364359 - pt 8. Thread local arenas are no-longer leaked
Attachment #9533257 - Attachment description: WIP: Bug 1364359 - pt 8. Refactoring in arena_t::~arena_t() → WIP: Bug 1364359 - pt 9. Refactoring in arena_t::~arena_t()
Blocks: 2014607
No longer blocks: 2014607
Depends on: 2014607
Blocks: 2014607
No longer depends on: 2014607

The ArenaCollection iterator was always messy and caused at least one
bug in the past. A future patch will add weak references to arenas
which would make this much more complex. Replacing it with a simple
function that builds a vector may use more/different temporary storage,
but its conceptually much simpler.

Attachment #9533252 - Attachment description: WIP: Bug 1364359 - pt 3. Simplify code for deleting arenas after purge → WIP: Bug 1364359 - pt 4. Simplify code for deleting arenas after purge
Attachment #9533253 - Attachment description: WIP: Bug 1364359 - pt 4. Rename DisposeArena to RemoveArena → WIP: Bug 1364359 - pt 5. Rename DisposeArena to RemoveArena
Attachment #9533254 - Attachment description: WIP: Bug 1364359 - pt 5. Add locking annotation to mNumOperationsRemovedArenas → WIP: Bug 1364359 - pt 6. Add locking annotation to mNumOperationsRemovedArenas
Attachment #9533255 - Attachment description: WIP: Bug 1364359 - pt 6. Support deleting non-empty arenas → WIP: Bug 1364359 - pt 7. Support deleting non-empty arenas
Attachment #9540804 - Attachment description: WIP: Bug 1364359 - pt 7. Initialise the allocator in two phases → WIP: Bug 1364359 - pt 8. Initialise the allocator in two phases
Attachment #9533256 - Attachment description: WIP: Bug 1364359 - pt 8. Thread local arenas are no-longer leaked → WIP: Bug 1364359 - pt 9. Thread local arenas are no-longer leaked
Attachment #9533257 - Attachment description: WIP: Bug 1364359 - pt 9. Refactoring in arena_t::~arena_t() → WIP: Bug 1364359 - pt 10. Refactoring in arena_t::~arena_t()

Comment on attachment 9533551 [details]
WIP: Bug 1364359 - pt 1. Move the arena struct definition into a new header

Revision D276789 was moved to bug 2016627. Setting attachment 9533551 [details] to obsolete.

Attachment #9533551 - Attachment is obsolete: true
Attachment #9533251 - Attachment description: WIP: Bug 1364359 - pt 2. Mozjemalloc arenas are now refcounted → WIP: Bug 1364359 - pt 1. Mozjemalloc arenas are now refcounted
Attachment #9542631 - Attachment description: WIP: Bug 1364359 - pt 3. Clean up ArenaCollection iteration → WIP: Bug 1364359 - pt 2. Clean up ArenaCollection iteration
Attachment #9533252 - Attachment description: WIP: Bug 1364359 - pt 4. Simplify code for deleting arenas after purge → WIP: Bug 1364359 - pt 3. Simplify code for deleting arenas after purge
Attachment #9533253 - Attachment description: WIP: Bug 1364359 - pt 5. Rename DisposeArena to RemoveArena → WIP: Bug 1364359 - pt 4. Rename DisposeArena to RemoveArena
Attachment #9533254 - Attachment description: WIP: Bug 1364359 - pt 6. Add locking annotation to mNumOperationsRemovedArenas → WIP: Bug 1364359 - pt 5. Add locking annotation to mNumOperationsRemovedArenas
Attachment #9533255 - Attachment description: WIP: Bug 1364359 - pt 7. Support deleting non-empty arenas → WIP: Bug 1364359 - pt 6. Support deleting non-empty arenas
Attachment #9540804 - Attachment description: WIP: Bug 1364359 - pt 8. Initialise the allocator in two phases → WIP: Bug 1364359 - pt 7. Initialise the allocator in two phases
Attachment #9533256 - Attachment description: WIP: Bug 1364359 - pt 9. Thread local arenas are no-longer leaked → WIP: Bug 1364359 - pt 8. Thread local arenas are no-longer leaked
Attachment #9533257 - Attachment description: WIP: Bug 1364359 - pt 10. Refactoring in arena_t::~arena_t() → WIP: Bug 1364359 - pt 9. Refactoring in arena_t::~arena_t()
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: