This is an archive of the discontinued LLVM Phabricator instance.

sanitizer_common: optimize memory drain
ClosedPublic

Authored by dvyukov on Jul 11 2021, 6:17 AM.

Details

Summary

Currently we allocate MemoryMapper per size class.
MemoryMapper mmap's and munmap's internal buffer.
This results in 50 mmap/munmap calls under the global
allocator mutex. Reuse MemoryMapper and the buffer
for all size classes. This radically reduces number of
mmap/munmap calls. Smaller size classes tend to have
more objects allocated, so it's highly likely that
the buffer allocated for the first size class will
be enough for all subsequent size classes.

Diff Detail

Event Timeline

dvyukov requested review of this revision.Jul 11 2021, 6:17 AM
dvyukov created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptJul 11 2021, 6:17 AM
Herald added a subscriber: Restricted Project. · View Herald Transcript
melver accepted this revision.Jul 12 2021, 8:45 AM
melver added inline comments.
compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
46

I think this can just be 'MemoryMapper', and the typedef later would just shadow the template class.

Because there's still that 'MemoryMapperT' template argument elsewhere[1], and on a whole it looks like 'MemoryMapperT' would indicate a template arg, whereas here it no longer is.

50

explicit?

490

[1]

This revision is now accepted and ready to land.Jul 12 2021, 8:45 AM
dvyukov added inline comments.Jul 12 2021, 10:06 AM
compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
490

I fail to decipher this comment.

dvyukov updated this revision to Diff 357975.Jul 12 2021, 10:07 AM
  • renamed MemoryMapperT to MemoryMapper
  • added explicit to MemoryMapper ctor
dvyukov marked 2 inline comments as done.Jul 12 2021, 10:07 AM
melver added inline comments.Jul 12 2021, 10:09 AM
compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
490

See other comment:

[...]
Because there's still that 'MemoryMapperT' template argument elsewhere[1]
[...]

(... cross referencing code in comments is complicated.)

melver accepted this revision.Jul 12 2021, 10:13 AM
This revision was landed with ongoing or failed builds.Jul 12 2021, 10:21 AM
This revision was automatically updated to reflect the committed changes.
nikic added a subscriber: nikic.Jul 12 2021, 11:35 AM
nikic added inline comments.
compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
114

It looks like this kind of shadowing is not accepted by GCC:

error: declaration of ‘typedef class sanitizer::MemoryMapper<sanitizer::SizeClassAllocator64<Params> > __sanitizer::SizeClassAllocator64<Params>::MemoryMapper’ changes meaning of ‘MemoryMapper’ [-fpermissive]

I've reverted the change for now.

dvyukov reopened this revision.Jul 13 2021, 12:07 AM
This revision is now accepted and ready to land.Jul 13 2021, 12:07 AM
dvyukov updated this revision to Diff 358180.Jul 13 2021, 12:23 AM

resubmit after revert with gcc warning fixed

PTAL

I've re-uploaded with the gcc warning fixed, you can look at the new diff with:
https://reviews.llvm.org/D105778?vs=357981&id=358180#toc

melver accepted this revision.Jul 13 2021, 12:51 AM
This revision was landed with ongoing or failed builds.Jul 13 2021, 1:02 AM
This revision was automatically updated to reflect the committed changes.
vitalybuka added a subscriber: hctim.EditedJul 13 2021, 11:13 AM

Breaks Windows https://lab.llvm.org/buildbot/#/builders/127/builds/13818/steps/8/logs/stdio

# command output:
   Creating library C:\b\slave\sanitizer-windows\build\stage1\projects\compiler-rt\test\asan\X86_64WindowsConfig\TestCases\Windows\Output\sanitizer_purge.cpp.lib and object C:\b\slave\sanitizer-windows\build\stage1\projects\compiler-rt\test\asan\X86_64WindowsConfig\TestCases\Windows\Output\sanitizer_purge.cpp.exp
$ ":" "RUN: at line 7"
$ "C:\b\slave\sanitizer-windows\build\stage1\projects\compiler-rt\test\asan\X86_64WindowsConfig\TestCases\Windows\Output\sanitizer_purge.cpp.tmp"
# command stderr:
AddressSanitizer: CHECK failed: sanitizer_win.cpp:139 "((VirtualQuery(addr, &mbi, sizeof(mbi)))) != (0)" (0x0, 0x0) (tid=8988)
    #0 0x7ff7650e4f6d in __asan::CheckUnwind C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\asan\asan_rtl.cpp:67
    #1 0x7ff7650d0273 in __sanitizer::CheckFailed(char const *, int, char const *, unsigned __int64, unsigned __int64) C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\sanitizer_common\sanitizer_termination.cpp:86
    #2 0x7ff7650d2e69 in __sanitizer::UnmapOrDie(void *, unsigned __int64) C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\sanitizer_common\sanitizer_win.cpp:139
    #3 0x7ff7650d2b6a in __sanitizer::ReleaseMemoryPagesToOS(unsigned __int64, unsigned __int64) C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\sanitizer_common\sanitizer_win.cpp:342
    #4 0x7ff765100f12 in __sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> >::FreePagesRangeTracker<__sanitizer::MemoryMapper<__sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> > > >::CloseOpenedRange C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\sanitizer_common\sanitizer_allocator_primary64.h:523
    #5 0x7ff765100f12 in __sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> >::FreePagesRangeTracker<__sanitizer::MemoryMapper<__sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> > > >::NextPage C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\sanitizer_common\sanitizer_allocator_primary64.h:508
    #6 0x7ff765100f12 in __sanitizer::SizeClassAllocator64<struct __asan::AP64<struct __sanitizer::LocalAddressSpaceView>>::ReleaseFreeMemoryToOS<class __sanitizer::MemoryMapper<class __sanitizer::SizeClassAllocator64<struct __asan::AP64<struct __sanitizer::LocalAddressSpaceView>>>>(unsigned int *, unsigned __int64, unsigned __int64, unsigned __int64, class __sanitizer::MemoryMapper<class __sanitizer::SizeClassAllocator64<struct __asan::AP64<struct __sanitizer::LocalAddressSpaceView>>> *, unsigned __int64) C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\sanitizer_common\sanitizer_allocator_primary64.h:610
    #7 0x7ff7651031c8 in __sanitizer::SizeClassAllocator64<struct __asan::AP64<struct __sanitizer::LocalAddressSpaceView>>::ForceReleaseToOS(void) C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\sanitizer_common\sanitizer_allocator_primary64.h:181
    #8 0x7ff7651071ae in __sanitizer::CombinedAllocator<__sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> >,__sanitizer::LargeMmapAllocatorPtrArrayDynamic>::ForceReleaseToOS C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\sanitizer_common\sanitizer_allocator_combined.h:86
    #9 0x7ff7651071ae in __asan::Allocator::Purge C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\asan\asan_allocator.cpp:836
    #10 0x7ff7651071ae in __sanitizer_purge_allocator C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\lib\asan\asan_allocator.cpp:1242
    #11 0x7ff7650c129e in main C:\b\slave\sanitizer-windows\llvm-project\compiler-rt\test\asan\TestCases\Windows\sanitizer_purge.cpp:23
    #12 0x7ff76510a247 in invoke_main d:\A01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #13 0x7ff76510a247 in __scrt_common_main_seh d:\A01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #14 0x7ffb5c4213f1  (C:\windows\system32\KERNEL32.DLL+0x1800013f1)
    #15 0x7ffb5c9154f3  (C:\windows\SYSTEM32\ntdll.dll+0x1800154f3)

FYI @hctim

vitalybuka reopened this revision.Jul 13 2021, 12:59 PM
This revision is now accepted and ready to land.Jul 13 2021, 12:59 PM

another rebase

vitalybuka added inline comments.Jul 13 2021, 4:04 PM
compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
82

Maybe problem is that class_id everywhere else is the first arg.

This revision was landed with ongoing or failed builds.Jul 13 2021, 4:29 PM
This revision was automatically updated to reflect the committed changes.

Maybe problem is that class_id everywhere else is the first arg.

Thanks for fixing this.
I very much confused how all linux tests passes with the swapped args... and there is a number of tests for this...