Repository navigation
BitSet blocks with the dependencies' non-override mimalloc; one mimalloc per process - #7240
Conversation
…loc per process MR::Allocator (BitSet::Blocks) is mi_stl_allocator, linked from the dependencies' mimalloc built without the malloc override: thirdparty/cpm on Ubuntu, the ports-unix overlay on vcpkg Linux/macOS (local-dynamic TLS on Linux, release-only), vcpkg's mimalloc[override] DLL on Windows. macOS Homebrew builds use std::allocator (MR_STD_ALLOCATOR), as Emscripten does. With MR_MIMALLOC_OVERRIDE=ON, executables forward malloc and new to the same mimalloc through MRMimallocOverride (Linux: definitions; macOS: dyld interposes and a malloc zone), or use the redirect of the same DLL on Windows. CMake CI builds with MR_MIMALLOC_OVERRIDE=ON for now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Windows the global target made the mimalloc that mr_enable_mimalloc prepends the same item as MRMesh's interface one, which CMake then placed after MRMesh, so mimalloc-redirect initialized after ucrtbase and malloc was not redirected (MimallocRedirectActive). Targets in other directories resolve MRMesh's interface mimalloc without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…malloc imported from the copied thirdparty libs - Code built against installed MeshLib does not see config_cmake.h (MR_USE_CMAKE_CONFIGURE_FILE is MeshLib's own), so the macOS Homebrew C++ examples compiled mi_stl_allocator and did not link (_mi_free). MRMesh now exports MR_STD_ALLOCATOR=1, the same value as config_cmake.h. - The .deb has no CMake config of mimalloc next to its copied thirdparty lib and include dirs, so MRMeshConfig imports libmimalloc from there (or next to MRMesh in vcpkg installs) as #7228 did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…talls) Linux vcpkg installs put vcpkg's lib dir at the prefix, not next to MRMesh (lib/MeshLib). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vcpkg 2026.10.16 ships mimalloc 3.5.3, so the ports-unix overlay is gone (as in master): the non-override build comes from vcpkg.json's Windows-only override feature, release-only from MeshLib's Linux/macOS triplets, and the Linux triplets add MI_LOCAL_DYNAMIC_TLS for mimalloc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -DMESHLIB_BUILD_GENERATED_C_BINDINGS=OFF | ||
| -DMRVIEWER_NO_GTK=ON | ||
| -DMRVIEWER_WITH_BUNDLED_CURL=ON | ||
| -DMR_MIMALLOC_OVERRIDE=ON |
There was a problem hiding this comment.
why override here? does it only takes effect on MeshViewer and TestApp?
There was a problem hiding this comment.
Yes, it only changed MeshLib's own executables (MRTest, MeshViewer), to test the override path in CI. It is gone now: MR_MIMALLOC_OVERRIDE is removed, and MRTest and MeshViewer always override malloc again, as on master, so every CI job tests it.
| target_link_libraries(${PROJECT_NAME} PRIVATE libzip::zip) | ||
|
|
||
| # MR::Allocator, see MRAllocator.h | ||
| IF(MR_STD_ALLOCATOR) |
There was a problem hiding this comment.
is it just client property that we always disable on our side? (mb in this case it is better to use common naming MR_NO_MIMALLOC like we do for other optional thirdparties?)
There was a problem hiding this comment.
It is not a client property: it is ON by default in Emscripten builds (malloc is already mimalloc there) and in macOS Homebrew builds (Homebrew's mimalloc overrides malloc, and its mimalloc.h of any version comes first in the include path). Renamed to the option MRMESH_NO_MIMALLOC with those defaults, like MRIOEXTRAS_NO_* and MRVIEWER_NO_*.
| find_package(mimalloc 3.5 CONFIG REQUIRED) | ||
| endif() | ||
|
|
||
| if(MR_MIMALLOC_OVERRIDE AND NOT WIN32) |
There was a problem hiding this comment.
seems a bit strange to have too different flags: MR_MIMALLOC_OVERRIDE and MR_STD_ALLOCATOR
There was a problem hiding this comment.
Agreed, MR_MIMALLOC_OVERRIDE is removed: an overriding executable now forwards malloc to the libraries' own mimalloc, so overriding is always safe and mr_enable_mimalloc needs no option. MRMESH_NO_MIMALLOC is the only flag left.
…ALLOCATOR Overriding malloc in an executable is always safe now (it forwards to the libraries' own mimalloc), so mr_enable_mimalloc works without an option, MRMimallocOverride is always built on macOS and Linux, and MRTest and MeshViewer override malloc again as on master (CMake and MimallocRedirect.props); CI needs no -DMR_MIMALLOC_OVERRIDE=ON. MR_STD_ALLOCATOR becomes the option MRMESH_NO_MIMALLOC, named like the other optional dependencies, ON by default in Emscripten and macOS Homebrew builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BitSetstores its blocks with mimalloc explicitly, and executables that override malloc (mr_enable_mimalloc, also MeshViewer and MRTest, as on master) forward it to the same mimalloc, so every process has exactly one mimalloc heap. The mimalloc comes from the dependencies, built without the malloc override, so MeshLib libraries can be loaded late into any process (Python, .NET, Java).An alternative to #7236, which fetches and builds its own
MRMimallocinstead.Allocator
BitSet::Blocksisstd::vector<block_type, Allocator<block_type>>. The newMRAllocator.hdefinesMR::Allocator<T>asmi_stl_allocator<T>.std::allocator<T>with the new optionMRMESH_NO_MIMALLOC, named like the other optional dependencies (MRIOEXTRAS_NO_*,MRVIEWER_NO_*). It defaults to ON in Emscripten builds, where malloc is mimalloc already withMR_EMSCRIPTEN_MIMALLOC, and in macOS Homebrew builds, because Homebrew's mimalloc overrides malloc. It is a public compile definition of MRMesh, so code built against installed MeshLib sees it too, and an entry inconfig_cmake.h.mimallocPUBLIC throughmr_find_mimalloc().MRAllocator.hauto-linksmimalloc(-debug).dll.lib, so consumers that link onlyMRMeshby name resolve the inlinemi_free.Dependencies
thirdparty/cpm/stage1)MI_OVERRIDE=OFF, local-dynamic TLS, release-builtoverridefeature (it is Windows-only invcpkg.json), release-only like everything in MeshLib's Linux/macOS triplets, local-dynamic TLS from the Linux tripletsmimalloc[override], as before (theoverridefeature is now Windows-only invcpkg.json)mr_enable_mimallocexecutables, as on masterThe libraries never load an override mimalloc, which would crash a plain Python loading it late. Release-only builds matter because the same mimalloc can be the allocator of the whole process (below).
Executables
mr_enable_mimallocmakes malloc use the libraries' mimalloc; it needs no option, as overriding is always safe now:MRMimallocOverridelibrary (source/MRMimallocOverride/MRMimallocOverride.cpp), first in the link order. It defines the Linux list of mimalloc 3.5.3'ssrc/alloc-override.c(malloc& co, glibc's__libc_*) and everyoperator new/deleteas calls tomi_*.MRMimallocOverride(MRMimallocOverrideMacOS.cpp), a port of mimalloc's macOS override (alloc-override.cwithMI_OSX_INTERPOSEplussrc/prim/osx/alloc-override-zone.c) to the public API. It uses dyld__interposetuples and a mimalloc malloc zone. Two things differ from mimalloc's single-image override:realpathis left out:mi_realpathcalls it, which recursed.MRMESH_NO_MIMALLOC(macOS Homebrew): the dependencies' mimalloc, Homebrew's override one, as on master (the libraries usestd::allocator).mimalloc.dll, unchanged.MRMimallocOverrideis built on macOS and Linux unlessMRMESH_NO_MIMALLOC. MeshViewer and MRTest callmr_enable_mimallocagain (MSBuild:MimallocRedirect.props), as on master, so every CI job tests the override.Packages and bindings
MRMeshConfig.cmakedefines themimalloctarget for code built against installed MeshLib: vcpkg's package on Windows; elsewhere the dependencies'libmimalloccopied with MeshLib (the thirdparty lib dir in the .deb, vcpkg's lib dir in vcpkg installs), with the copied thirdparty include dir.bits()andfromBlocksare hidden from the bindings (MR_BIND_IGNORE), because mrbind drops custom allocators (see this C bindings error).generate.mkreadsMRMESH_NO_MIMALLOCfrom MRMesh'sconfig_cmake.h, so the bindings agree with MRMesh onBitSet::Blocks.BitSet::Blocks, andDynamicArrayaccepts astd::vectorwith any allocator.Tests
MRMimallocRedirectTests.cpp:MimallocRedirectActive:mallocandnewreturn mimalloc memory. On Windows the redirect is active, and on macOS the default malloc zone is mimalloc's.MimallocBitSet:BitSetblocks come from mimalloc, also those allocated inside MRMesh.MimallocSharedLibrary(Linux, macOS): exactly onelibmimalloc*is loaded, pluslibMRMimallocOverride(unlessMRMESH_NO_MIMALLOC), andmimalloc.hmatches the library's version.The file is skipped where malloc is not mimalloc (Emscripten without
MR_EMSCRIPTEN_MIMALLOC,MRMESH_NO_MIMALLOCoutside macOS Homebrew).Performance
Boolean timing of an overriding executable built with this PR matches master (the dependencies' override mimalloc replacing malloc) on 8 Linux, 3 Windows and 2 macOS CI jobs, interleaved on the same machine (two samples of the Linux and Windows jobs). Measured with #7236's
MRMimalloc, the same mimalloc 3.5.3 built the same way, local-dynamic TLS costs nothing measurable.🤖 Generated with Claude Code