Merge pull request #6 from microsoft/dev

Merge with last dev
This commit is contained in:
synacker 2020-04-24 12:24:06 +03:00 committed by GitHub
commit eb3e849a3a
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 250 additions and 180 deletions

View file

@ -68,6 +68,7 @@ if(MI_OVERRIDE MATCHES "ON")
# use zone's on macOS # use zone's on macOS
message(STATUS " Use malloc zone to override malloc (MI_OSX_ZONE=ON)") message(STATUS " Use malloc zone to override malloc (MI_OSX_ZONE=ON)")
list(APPEND mi_sources src/alloc-override-osx.c) list(APPEND mi_sources src/alloc-override-osx.c)
list(APPEND mi_defines MI_OSX_ZONE=1)
if(NOT MI_INTERPOSE MATCHES "ON") if(NOT MI_INTERPOSE MATCHES "ON")
message(STATUS " (enabling INTERPOSE as well since zone's require this)") message(STATUS " (enabling INTERPOSE as well since zone's require this)")
set(MI_INTERPOSE "ON") set(MI_INTERPOSE "ON")
@ -152,10 +153,12 @@ endif()
if(WIN32) if(WIN32)
list(APPEND mi_libraries psapi shell32 user32 bcrypt) list(APPEND mi_libraries psapi shell32 user32 bcrypt)
else() else()
list(APPEND mi_libraries pthread) if(NOT ${CMAKE_C_COMPILER} MATCHES "android")
find_library(LIBRT rt) list(APPEND mi_libraries pthread)
if(LIBRT) find_library(LIBRT rt)
list(APPEND mi_libraries ${LIBRT}) if(LIBRT)
list(APPEND mi_libraries ${LIBRT})
endif()
endif() endif()
endif() endif()

View file

@ -18,12 +18,15 @@ jobs:
Debug: Debug:
BuildType: debug BuildType: debug
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON
MSBuildConfiguration: Debug
Release: Release:
BuildType: release BuildType: release
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release
MSBuildConfiguration: Release
Secure: Secure:
BuildType: secure BuildType: secure
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON
MSBuildConfiguration: Release
steps: steps:
- task: CMake@1 - task: CMake@1
inputs: inputs:
@ -32,6 +35,7 @@ jobs:
- task: MSBuild@1 - task: MSBuild@1
inputs: inputs:
solution: $(BuildType)/libmimalloc.sln solution: $(BuildType)/libmimalloc.sln
configuration: '$(MSBuildConfiguration)'
- script: | - script: |
cd $(BuildType) cd $(BuildType)
ctest ctest

View file

@ -38,7 +38,7 @@ PROJECT_NAME = mi-malloc
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = 1.4 PROJECT_NUMBER = 1.6
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a

View file

@ -1009,28 +1009,31 @@ or via environment variables.
- `MIMALLOC_SHOW_STATS=1`: show statistics when the program terminates. - `MIMALLOC_SHOW_STATS=1`: show statistics when the program terminates.
- `MIMALLOC_VERBOSE=1`: show verbose messages. - `MIMALLOC_VERBOSE=1`: show verbose messages.
- `MIMALLOC_SHOW_ERRORS=1`: show error and warning messages. - `MIMALLOC_SHOW_ERRORS=1`: show error and warning messages.
- `MIMALLOC_PAGE_RESET=1`: reset (or purge) OS pages when not in use. This can reduce - `MIMALLOC_PAGE_RESET=0`: by default, mimalloc will reset (or purge) OS pages when not in use to signal to the OS
memory fragmentation in long running (server) programs. If performance is impacted, that the underlying physical memory can be reused. This can reduce memory fragmentation in long running (server)
`MIMALLOC_RESET_DELAY=`_msecs_ can be set higher (100ms by default) to make the page programs. By setting it to `0` no such page resets will be done which can improve performance for programs that are not long
reset occur less frequently. running. As an alternative, the `MIMALLOC_RESET_DELAY=`<msecs> can be set higher (100ms by default) to make the page
- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages when available; for some workloads this can significantly reset occur less frequently instead of turning it off completely.
- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages (2MiB) when available; for some workloads this can significantly
improve performance. Use `MIMALLOC_VERBOSE` to check if the large OS pages are enabled -- usually one needs improve performance. Use `MIMALLOC_VERBOSE` to check if the large OS pages are enabled -- usually one needs
to explicitly allow large OS pages (as on [Windows][windows-huge] and [Linux][linux-huge]). However, sometimes to explicitly allow large OS pages (as on [Windows][windows-huge] and [Linux][linux-huge]). However, sometimes
the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that
can have fragmented memory (for that reason, we generally recommend to use `MIMALLOC_RESERVE_HUGE_OS_PAGES` instead when possible). can have fragmented memory (for that reason, we generally recommend to use `MIMALLOC_RESERVE_HUGE_OS_PAGES` instead when possible).
- `MIMALLOC_EAGER_REGION_COMMIT=1`: on Windows, commit large (256MiB) regions eagerly. On Windows, these regions - `MIMALLOC_RESERVE_HUGE_OS_PAGES=N`: where N is the number of 1GiB _huge_ OS pages. This reserves the huge pages at
show in the working set even though usually just a small part is committed to physical memory. This is why it startup and sometimes this can give a large (latency) performance improvement on big workloads.
turned off by default on Windows as it looks not good in the task manager. However, in reality it is always better Usually it is better to not use
to turn it on as it improves performance and has no other drawbacks.
- `MIMALLOC_RESERVE_HUGE_OS_PAGES=N`: where N is the number of 1GiB huge OS pages. This reserves the huge pages at
startup and can give quite a performance improvement on long running workloads. Usually it is better to not use
`MIMALLOC_LARGE_OS_PAGES` in combination with this setting. Just like large OS pages, use with care as reserving `MIMALLOC_LARGE_OS_PAGES` in combination with this setting. Just like large OS pages, use with care as reserving
contiguous physical memory can take a long time when memory is fragmented. contiguous physical memory can take a long time when memory is fragmented (but reserving the huge pages is done at
startup only once).
Note that we usually need to explicitly enable huge OS pages (as on [Windows][windows-huge] and [Linux][linux-huge])). With huge OS pages, it may be beneficial to set the setting Note that we usually need to explicitly enable huge OS pages (as on [Windows][windows-huge] and [Linux][linux-huge])). With huge OS pages, it may be beneficial to set the setting
`MIMALLOC_EAGER_COMMIT_DELAY=N` (with usually `N` as 1) to delay the initial `N` segments `MIMALLOC_EAGER_COMMIT_DELAY=N` (`N` is 1 by default) to delay the initial `N` segments (of 4MiB)
of a thread to not allocate in the huge OS pages; this prevents threads that are short lived of a thread to not allocate in the huge OS pages; this prevents threads that are short lived
and allocate just a little to take up space in the huge OS page area (which cannot be reset). and allocate just a little to take up space in the huge OS page area (which cannot be reset).
Use caution when using `fork` in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write
for all pages in the original process including the huge OS pages. When any memory is now written in that area, the
OS will copy the entire 1GiB huge page (or 2MiB large page) which can cause the memory usage to grow in big increments.
[linux-huge]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5 [linux-huge]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5
[windows-huge]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017 [windows-huge]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017
@ -1074,14 +1077,18 @@ resolved to the _mimalloc_ library.
Note that certain security restrictions may apply when doing this from Note that certain security restrictions may apply when doing this from
the [shell](https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash). the [shell](https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash).
Note: unfortunately, at this time, dynamic overriding on macOS seems broken but it is actively worked on to fix this (Note: macOS support for dynamic overriding is recent, please report any issues.)
(see issue [`#50`](https://github.com/microsoft/mimalloc/issues/50)).
### Windows ### Windows
Overriding on Windows is robust but requires that you link your program explicitly with Overriding on Windows is robust and has the
particular advantage to be able to redirect all malloc/free calls that go through
the (dynamic) C runtime allocator, including those from other DLL's or libraries.
The overriding on Windows requires that you link your program explicitly with
the mimalloc DLL and use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch). the mimalloc DLL and use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch).
Moreover, you need to ensure the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) is available Also, the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) must be available
in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency). in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency).
The redirection DLL ensures that all calls to the C runtime malloc API get redirected to The redirection DLL ensures that all calls to the C runtime malloc API get redirected to
mimalloc (in `mimalloc-override.dll`). mimalloc (in `mimalloc-override.dll`).
@ -1090,14 +1097,15 @@ To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some
call to the mimalloc API in the `main` function, like `mi_version()` call to the mimalloc API in the `main` function, like `mi_version()`
(or use the `/INCLUDE:mi_version` switch on the linker). See the `mimalloc-override-test` project (or use the `/INCLUDE:mi_version` switch on the linker). See the `mimalloc-override-test` project
for an example on how to use this. For best performance on Windows with C++, it for an example on how to use this. For best performance on Windows with C++, it
is highly recommended to also override the `new`/`delete` operations (by including is also recommended to also override the `new`/`delete` operations (by including
[`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h) a single(!) source file in your project). [`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h) a single(!) source file in your project).
The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic
overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected. overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected.
(Note: in principle, it is possible to patch existing executables (Note: in principle, it is possible to even patch existing executables without any recompilation
that are linked with the dynamic C runtime (`ucrtbase.dll`) by just putting the `mimalloc-override.dll` into the import table (and putting `mimalloc-redirect.dll` in the same folder) if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the `mimalloc-override.dll`
into the import table (and put `mimalloc-redirect.dll` in the same folder)
Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388)). Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388)).

View file

@ -36,15 +36,15 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="23.706667" inkscape:zoom="23.706667"
inkscape:cx="34.419045" inkscape:cx="24.864771"
inkscape:cy="35.79485" inkscape:cy="35.79485"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="3840" inkscape:window-width="3840"
inkscape:window-height="2160" inkscape:window-height="2050"
inkscape:window-x="0" inkscape:window-x="-12"
inkscape:window-y="0" inkscape:window-y="-12"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:snap-object-midpoints="false" inkscape:snap-object-midpoints="false"
inkscape:snap-bbox="false" inkscape:snap-bbox="false"
@ -126,17 +126,15 @@
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
id="path6525" /> id="path6525" />
</g> </g>
<text <g
xml:space="preserve" aria-label="m"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3694315px;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3694315px;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578"
x="1.6752419" id="text848">
y="293.17081" <path
id="text848"><tspan d="m 2.3718985,293.17081 c 0.080862,0 0.1492836,-0.0249 0.211485,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.95313 c 0.037321,-0.0622 0.087082,-0.13062 0.1430634,-0.19282 0.049761,-0.0622 0.1368433,-0.1244 0.2488059,-0.19283 0.1119627,-0.0622 0.2301455,-0.0995 0.3545485,-0.0995 0.1119626,0 0.2177051,0.0498 0.3110074,0.14929 0.087082,0.0995 0.1368432,0.23014 0.1368432,0.39808 v 1.89093 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.89093 -0.0622 c 0.018661,-0.0311 0.043541,-0.0622 0.068422,-0.0995 0.024881,-0.0373 0.062201,-0.0746 0.1119626,-0.1244 0.049761,-0.0498 0.099522,-0.0933 0.1492836,-0.13063 0.049761,-0.0373 0.1181828,-0.0684 0.1928246,-0.0933 0.074642,-0.0249 0.1492835,-0.0373 0.2239253,-0.0373 0.1119626,0 0.2177052,0.0498 0.3110074,0.14929 0.087082,0.0995 0.1368432,0.23014 0.1368432,0.39808 v 1.89093 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.89093 c 0,-0.31722 -0.1057425,-0.58469 -0.3047872,-0.80861 -0.2052649,-0.22393 -0.4540708,-0.33589 -0.7401976,-0.33589 -0.2052649,0 -0.3918693,0.0435 -0.5535932,0.11818 -0.1617238,0.0746 -0.3047872,0.17416 -0.4291902,0.29857 -0.211485,-0.27369 -0.4789514,-0.41675 -0.8086192,-0.41675 -0.2861268,0 -0.5411529,0.0809 -0.7650782,0.23636 -0.024881,-0.0498 -0.062202,-0.0933 -0.1119627,-0.13062 -0.049761,-0.0373 -0.1057425,-0.056 -0.167944,-0.056 -0.087082,0 -0.1555037,0.0311 -0.211485,0.0871 -0.062202,0.0622 -0.087082,0.13062 -0.087082,0.21149 v 2.6871 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.1244029,0.0871 0.211485,0.0871 z"
y="293.17081" style="stroke-width:0.15923578"
x="1.6752419" id="path834" />
sodipodi:role="line" </g>
id="tspan872"
style="stroke-width:0.15923578">m</tspan></text>
<g <g
id="g28" id="g28"
transform="translate(-0.23995531,0.02790178)"> transform="translate(-0.23995531,0.02790178)">

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -107,11 +107,11 @@ $(document).ready(function(){initNavTree('environment.html','');});
<li><code>MIMALLOC_SHOW_STATS=1</code>: show statistics when the program terminates.</li> <li><code>MIMALLOC_SHOW_STATS=1</code>: show statistics when the program terminates.</li>
<li><code>MIMALLOC_VERBOSE=1</code>: show verbose messages.</li> <li><code>MIMALLOC_VERBOSE=1</code>: show verbose messages.</li>
<li><code>MIMALLOC_SHOW_ERRORS=1</code>: show error and warning messages.</li> <li><code>MIMALLOC_SHOW_ERRORS=1</code>: show error and warning messages.</li>
<li><code>MIMALLOC_PAGE_RESET=1</code>: reset (or purge) OS pages when not in use. This can reduce memory fragmentation in long running (server) programs. If performance is impacted, <code>MIMALLOC_RESET_DELAY=</code>_msecs_ can be set higher (100ms by default) to make the page reset occur less frequently.</li> <li><code>MIMALLOC_PAGE_RESET=0</code>: by default, mimalloc will reset (or purge) OS pages when not in use to signal to the OS that the underlying physical memory can be reused. This can reduce memory fragmentation in long running (server) programs. By setting it to <code>0</code> no such page resets will be done which can improve performance for programs that are not long running. As an alternative, the <code>MIMALLOC_RESET_DELAY=</code>&lt;msecs&gt; can be set higher (100ms by default) to make the page reset occur less frequently instead of turning it off completely.</li>
<li><code>MIMALLOC_LARGE_OS_PAGES=1</code>: use large OS pages when available; for some workloads this can significantly improve performance. Use <code>MIMALLOC_VERBOSE</code> to check if the large OS pages are enabled &ndash; usually one needs to explicitly allow large OS pages (as on <a href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017">Windows</a> and <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5">Linux</a>). However, sometimes the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that can have fragmented memory (for that reason, we generally recommend to use <code>MIMALLOC_RESERVE_HUGE_OS_PAGES</code> instead when possible).</li> <li><code>MIMALLOC_LARGE_OS_PAGES=1</code>: use large OS pages (2MiB) when available; for some workloads this can significantly improve performance. Use <code>MIMALLOC_VERBOSE</code> to check if the large OS pages are enabled &ndash; usually one needs to explicitly allow large OS pages (as on <a href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017">Windows</a> and <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5">Linux</a>). However, sometimes the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that can have fragmented memory (for that reason, we generally recommend to use <code>MIMALLOC_RESERVE_HUGE_OS_PAGES</code> instead when possible).</li>
<li><code>MIMALLOC_EAGER_REGION_COMMIT=1</code>: on Windows, commit large (256MiB) regions eagerly. On Windows, these regions show in the working set even though usually just a small part is committed to physical memory. This is why it turned off by default on Windows as it looks not good in the task manager. However, in reality it is always better to turn it on as it improves performance and has no other drawbacks.</li> <li><code>MIMALLOC_RESERVE_HUGE_OS_PAGES=N</code>: where N is the number of 1GiB <em>huge</em> OS pages. This reserves the huge pages at startup and sometimes this can give a large (latency) performance improvement on big workloads. Usually it is better to not use <code>MIMALLOC_LARGE_OS_PAGES</code> in combination with this setting. Just like large OS pages, use with care as reserving contiguous physical memory can take a long time when memory is fragmented (but reserving the huge pages is done at startup only once). Note that we usually need to explicitly enable huge OS pages (as on <a href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017">Windows</a> and <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5">Linux</a>)). With huge OS pages, it may be beneficial to set the setting <code>MIMALLOC_EAGER_COMMIT_DELAY=N</code> (<code>N</code> is 1 by default) to delay the initial <code>N</code> segments (of 4MiB) of a thread to not allocate in the huge OS pages; this prevents threads that are short lived and allocate just a little to take up space in the huge OS page area (which cannot be reset).</li>
<li><code>MIMALLOC_RESERVE_HUGE_OS_PAGES=N</code>: where N is the number of 1GiB huge OS pages. This reserves the huge pages at startup and can give quite a performance improvement on long running workloads. Usually it is better to not use <code>MIMALLOC_LARGE_OS_PAGES</code> in combination with this setting. Just like large OS pages, use with care as reserving contiguous physical memory can take a long time when memory is fragmented. Note that we usually need to explicitly enable huge OS pages (as on <a href="https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017">Windows</a> and <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5">Linux</a>)). With huge OS pages, it may be beneficial to set the setting <code>MIMALLOC_EAGER_COMMIT_DELAY=N</code> (with usually <code>N</code> as 1) to delay the initial <code>N</code> segments of a thread to not allocate in the huge OS pages; this prevents threads that are short lived and allocate just a little to take up space in the huge OS page area (which cannot be reset). </li>
</ul> </ul>
<p>Use caution when using <code>fork</code> in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write for all pages in the original process including the huge OS pages. When any memory is now written in that area, the OS will copy the entire 1GiB huge page (or 2MiB large page) which can cause the memory usage to grow in big increments. </p>
</div></div><!-- PageDoc --> </div></div><!-- PageDoc -->
</div><!-- contents --> </div><!-- contents -->
</div><!-- doc-content --> </div><!-- doc-content -->

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -146,7 +146,7 @@ Macros</h2></td></tr>
</table> </table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2> <a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<p>Typed allocation macros. </p> <p>Typed allocation macros. </p>
<h2 class="groupheader">Macro Definition Documentation</h2> <p>For example: </p><div class="fragment"><div class="line"><span class="keywordtype">int</span>* p = <a class="code" href="group__typed.html#ga0619a62c5fd886f1016030abe91f0557">mi_malloc_tp</a>(<span class="keywordtype">int</span>)</div></div><!-- fragment --> <h2 class="groupheader">Macro Definition Documentation</h2>
<a id="gae80c47c9d4cab10961fff1a8ac98fc07"></a> <a id="gae80c47c9d4cab10961fff1a8ac98fc07"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gae80c47c9d4cab10961fff1a8ac98fc07">&#9670;&nbsp;</a></span>mi_calloc_tp</h2> <h2 class="memtitle"><span class="permalink"><a href="#gae80c47c9d4cab10961fff1a8ac98fc07">&#9670;&nbsp;</a></span>mi_calloc_tp</h2>

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -127,7 +127,9 @@ $(document).ready(function(){initNavTree('index.html','');});
<li><a class="el" href="group__heap.html">Heap Allocation</a></li> <li><a class="el" href="group__heap.html">Heap Allocation</a></li>
<li><a class="el" href="group__typed.html">Typed Macros</a></li> <li><a class="el" href="group__typed.html">Typed Macros</a></li>
<li><a class="el" href="group__analysis.html">Heap Introspection</a></li> <li><a class="el" href="group__analysis.html">Heap Introspection</a></li>
<li><a class="el" href="group__options.html">Runtime Options</a> </li> <li><a class="el" href="group__options.html">Runtime Options</a></li>
<li><a class="el" href="group__posix.html">Posix</a></li>
<li><a class="el" href="group__cpp.html">C++ wrappers</a> </li>
</ul> </ul>
</div></div><!-- PageDoc --> </div></div><!-- PageDoc -->
</div><!-- contents --> </div><!-- contents -->

File diff suppressed because one or more lines are too long

View file

@ -36,15 +36,15 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="23.706667" inkscape:zoom="23.706667"
inkscape:cx="34.419045" inkscape:cx="24.864771"
inkscape:cy="35.79485" inkscape:cy="35.79485"
inkscape:document-units="mm" inkscape:document-units="mm"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="false" showgrid="false"
inkscape:window-width="3840" inkscape:window-width="3840"
inkscape:window-height="2160" inkscape:window-height="2050"
inkscape:window-x="0" inkscape:window-x="-12"
inkscape:window-y="0" inkscape:window-y="-12"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:snap-object-midpoints="false" inkscape:snap-object-midpoints="false"
inkscape:snap-bbox="false" inkscape:snap-bbox="false"
@ -126,17 +126,15 @@
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.28797817px;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.28599727"
id="path6525" /> id="path6525" />
</g> </g>
<text <g
xml:space="preserve" aria-label="m"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3694315px;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.3694315px;line-height:1.25;font-family:RoutedGothicEx;-inkscape-font-specification:'RoutedGothicEx, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.15923578"
x="1.6752419" id="text848">
y="293.17081" <path
id="text848"><tspan d="m 2.3718985,293.17081 c 0.080862,0 0.1492836,-0.0249 0.211485,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.95313 c 0.037321,-0.0622 0.087082,-0.13062 0.1430634,-0.19282 0.049761,-0.0622 0.1368433,-0.1244 0.2488059,-0.19283 0.1119627,-0.0622 0.2301455,-0.0995 0.3545485,-0.0995 0.1119626,0 0.2177051,0.0498 0.3110074,0.14929 0.087082,0.0995 0.1368432,0.23014 0.1368432,0.39808 v 1.89093 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.89093 -0.0622 c 0.018661,-0.0311 0.043541,-0.0622 0.068422,-0.0995 0.024881,-0.0373 0.062201,-0.0746 0.1119626,-0.1244 0.049761,-0.0498 0.099522,-0.0933 0.1492836,-0.13063 0.049761,-0.0373 0.1181828,-0.0684 0.1928246,-0.0933 0.074642,-0.0249 0.1492835,-0.0373 0.2239253,-0.0373 0.1119626,0 0.2177052,0.0498 0.3110074,0.14929 0.087082,0.0995 0.1368432,0.23014 0.1368432,0.39808 v 1.89093 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.124403,0.0871 0.211485,0.0871 0.080862,0 0.1492836,-0.0249 0.2114851,-0.0871 0.055981,-0.056 0.087082,-0.1244 0.087082,-0.21148 v -1.89093 c 0,-0.31722 -0.1057425,-0.58469 -0.3047872,-0.80861 -0.2052649,-0.22393 -0.4540708,-0.33589 -0.7401976,-0.33589 -0.2052649,0 -0.3918693,0.0435 -0.5535932,0.11818 -0.1617238,0.0746 -0.3047872,0.17416 -0.4291902,0.29857 -0.211485,-0.27369 -0.4789514,-0.41675 -0.8086192,-0.41675 -0.2861268,0 -0.5411529,0.0809 -0.7650782,0.23636 -0.024881,-0.0498 -0.062202,-0.0933 -0.1119627,-0.13062 -0.049761,-0.0373 -0.1057425,-0.056 -0.167944,-0.056 -0.087082,0 -0.1555037,0.0311 -0.211485,0.0871 -0.062202,0.0622 -0.087082,0.13062 -0.087082,0.21149 v 2.6871 c 0,0.0871 0.024881,0.1555 0.087082,0.21148 0.055981,0.0622 0.1244029,0.0871 0.211485,0.0871 z"
y="293.17081" style="stroke-width:0.15923578"
x="1.6752419" id="path834" />
sodipodi:role="line" </g>
id="tspan872"
style="stroke-width:0.15923578">m</tspan></text>
<g <g
id="g28" id="g28"
transform="translate(-0.23995531,0.02790178)"> transform="translate(-0.23995531,0.02790178)">

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -116,12 +116,13 @@ $(document).ready(function(){initNavTree('overrides.html','');});
<li><code>env DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram</code></li> <li><code>env DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram</code></li>
</ul> </ul>
<p>Note that certain security restrictions may apply when doing this from the <a href="https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash">shell</a>.</p> <p>Note that certain security restrictions may apply when doing this from the <a href="https://stackoverflow.com/questions/43941322/dyld-insert-libraries-ignored-when-calling-application-through-bash">shell</a>.</p>
<p>Note: unfortunately, at this time, dynamic overriding on macOS seems broken but it is actively worked on to fix this (see issue <a href="https://github.com/microsoft/mimalloc/issues/50"><code>#50</code></a>).</p> <p>(Note: macOS support for dynamic overriding is recent, please report any issues.)</p>
<h3>Windows</h3> <h3>Windows</h3>
<p>Overriding on Windows is robust but requires that you link your program explicitly with the mimalloc DLL and use the C-runtime library as a DLL (using the <code>/MD</code> or <code>/MDd</code> switch). Moreover, you need to ensure the <code>mimalloc-redirect.dll</code> (or <code>mimalloc-redirect32.dll</code>) is available in the same folder as the main <code>mimalloc-override.dll</code> at runtime (as it is a dependency). The redirection DLL ensures that all calls to the C runtime malloc API get redirected to mimalloc (in <code>mimalloc-override.dll</code>).</p> <p>Overriding on Windows is robust and has the particular advantage to be able to redirect all malloc/free calls that go through the (dynamic) C runtime allocator, including those from other DLL's or libraries.</p>
<p>To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some call to the mimalloc API in the <code>main</code> function, like <code>mi_version()</code> (or use the <code>/INCLUDE:mi_version</code> switch on the linker). See the <code>mimalloc-override-test</code> project for an example on how to use this. For best performance on Windows with C++, it is highly recommended to also override the <code>new</code>/<code>delete</code> operations (by including <a href="https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h"><code>mimalloc-new-delete.h</code></a> a single(!) source file in your project).</p> <p>The overriding on Windows requires that you link your program explicitly with the mimalloc DLL and use the C-runtime library as a DLL (using the <code>/MD</code> or <code>/MDd</code> switch). Also, the <code>mimalloc-redirect.dll</code> (or <code>mimalloc-redirect32.dll</code>) must be available in the same folder as the main <code>mimalloc-override.dll</code> at runtime (as it is a dependency). The redirection DLL ensures that all calls to the C runtime malloc API get redirected to mimalloc (in <code>mimalloc-override.dll</code>).</p>
<p>To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some call to the mimalloc API in the <code>main</code> function, like <code>mi_version()</code> (or use the <code>/INCLUDE:mi_version</code> switch on the linker). See the <code>mimalloc-override-test</code> project for an example on how to use this. For best performance on Windows with C++, it is also recommended to also override the <code>new</code>/<code>delete</code> operations (by including <a href="https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h"><code>mimalloc-new-delete.h</code></a> a single(!) source file in your project).</p>
<p>The environment variable <code>MIMALLOC_DISABLE_REDIRECT=1</code> can be used to disable dynamic overriding at run-time. Use <code>MIMALLOC_VERBOSE=1</code> to check if mimalloc was successfully redirected.</p> <p>The environment variable <code>MIMALLOC_DISABLE_REDIRECT=1</code> can be used to disable dynamic overriding at run-time. Use <code>MIMALLOC_VERBOSE=1</code> to check if mimalloc was successfully redirected.</p>
<p>(Note: in principle, it is possible to patch existing executables that are linked with the dynamic C runtime (<code>ucrtbase.dll</code>) by just putting the <code>mimalloc-override.dll</code> into the import table (and putting <code>mimalloc-redirect.dll</code> in the same folder) Such patching can be done for example with <a href="https://ntcore.com/?page_id=388">CFF Explorer</a>).</p> <p>(Note: in principle, it is possible to even patch existing executables without any recompilation if they are linked with the dynamic C runtime (<code>ucrtbase.dll</code>) &ndash; just put the <code>mimalloc-override.dll</code> into the import table (and put <code>mimalloc-redirect.dll</code> in the same folder) Such patching can be done for example with <a href="https://ntcore.com/?page_id=388">CFF Explorer</a>).</p>
<h2>Static override</h2> <h2>Static override</h2>
<p>On Unix systems, you can also statically link with <em>mimalloc</em> to override the standard malloc interface. The recommended way is to link the final program with the <em>mimalloc</em> single object file (<code>mimalloc-override.o</code>). We use an object file instead of a library file as linkers give preference to that over archives to resolve symbols. To ensure that the standard malloc interface resolves to the <em>mimalloc</em> library, link it as the first object file. For example:</p> <p>On Unix systems, you can also statically link with <em>mimalloc</em> to override the standard malloc interface. The recommended way is to link the final program with the <em>mimalloc</em> single object file (<code>mimalloc-override.o</code>). We use an object file instead of a library file as linkers give preference to that over archives to resolve symbols. To ensure that the standard malloc interface resolves to the <em>mimalloc</em> library, link it as the first object file. For example:</p>
<div class="fragment"><div class="line">gcc -o myprogram mimalloc-<span class="keyword">override</span>.o myfile1.c ...</div></div><!-- fragment --><h2>List of Overrides:</h2> <div class="fragment"><div class="line">gcc -o myprogram mimalloc-<span class="keyword">override</span>.o myfile1.c ...</div></div><!-- fragment --><h2>List of Overrides:</h2>

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -37,7 +37,7 @@
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td> <td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;"> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc <div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span> &#160;<span id="projectnumber">1.6</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -8,7 +8,7 @@ terms of the MIT license. A copy of the license can be found in the file
#ifndef MIMALLOC_H #ifndef MIMALLOC_H
#define MIMALLOC_H #define MIMALLOC_H
#define MI_MALLOC_VERSION 161 // major + 2 digits minor #define MI_MALLOC_VERSION 163 // major + 2 digits minor
// ------------------------------------------------------ // ------------------------------------------------------
// Compiler specific attributes // Compiler specific attributes
@ -28,11 +28,11 @@ terms of the MIT license. A copy of the license can be found in the file
#define mi_decl_nodiscard [[nodiscard]] #define mi_decl_nodiscard [[nodiscard]]
#elif (__GNUC__ >= 4) || defined(__clang__) // includes clang, icc, and clang-cl #elif (__GNUC__ >= 4) || defined(__clang__) // includes clang, icc, and clang-cl
#define mi_decl_nodiscard __attribute__((warn_unused_result)) #define mi_decl_nodiscard __attribute__((warn_unused_result))
#elif (_MSC_VER >= 1700) #elif (_MSC_VER >= 1700)
#define mi_decl_nodiscard _Check_return_ #define mi_decl_nodiscard _Check_return_
#else #else
#define mi_decl_nodiscard #define mi_decl_nodiscard
#endif #endif
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#if !defined(MI_SHARED_LIB) #if !defined(MI_SHARED_LIB)

View file

@ -11,7 +11,7 @@ mimalloc (pronounced "me-malloc")
is a general purpose allocator with excellent [performance](#performance) characteristics. is a general purpose allocator with excellent [performance](#performance) characteristics.
Initially developed by Daan Leijen for the run-time systems of the Initially developed by Daan Leijen for the run-time systems of the
[Koka](https://github.com/koka-lang/koka) and [Lean](https://github.com/leanprover/lean) languages. [Koka](https://github.com/koka-lang/koka) and [Lean](https://github.com/leanprover/lean) languages.
Latest release:`v1.6.1` (2020-02-17). Latest release:`v1.6.2` (2020-04-20).
It is a drop-in replacement for `malloc` and can be used in other programs It is a drop-in replacement for `malloc` and can be used in other programs
without code changes, for example, on dynamically linked ELF-based systems (Linux, BSD, etc.) you can use it as: without code changes, for example, on dynamically linked ELF-based systems (Linux, BSD, etc.) you can use it as:
@ -59,6 +59,9 @@ Enjoy!
### Releases ### Releases
* 2020-04-20, `v1.6.2`: stable release 1.6: fix compilation on Android, MingW, Raspberry, and Conda,
stability fix for Windows 7, fix multiple mimalloc instances in one executable, fix `strnlen` overload,
fix aligned debug padding.
* 2020-02-17, `v1.6.1`: stable release 1.6: minor updates (build with clang-cl, fix alignment issue for small objects). * 2020-02-17, `v1.6.1`: stable release 1.6: minor updates (build with clang-cl, fix alignment issue for small objects).
* 2020-02-09, `v1.6.0`: stable release 1.6: fixed potential memory leak, improved overriding * 2020-02-09, `v1.6.0`: stable release 1.6: fixed potential memory leak, improved overriding
and thread local support on FreeBSD, NetBSD, DragonFly, and macOSX. New byte-precise and thread local support on FreeBSD, NetBSD, DragonFly, and macOSX. New byte-precise
@ -77,6 +80,11 @@ free list encoding](https://github.com/microsoft/mimalloc/blob/783e3377f79ee82af
* 2019-09-01, `v1.0.8`: pre-release 8: more robust windows dynamic overriding, initial huge page support. * 2019-09-01, `v1.0.8`: pre-release 8: more robust windows dynamic overriding, initial huge page support.
* 2019-08-10, `v1.0.6`: pre-release 6: various performance improvements. * 2019-08-10, `v1.0.6`: pre-release 6: various performance improvements.
Special thanks to:
* Jason Gibson (@jasongibson) for exhaustive testing on large workloads and server environments and finding complex bugs in (early versions of) `mimalloc`.
* Manuel Pöter (@mpoeter) and Sam Gross (@colesbury) for finding an ABA concurrency issue in abandoned segment reclamation.
# Building # Building
## Windows ## Windows
@ -210,31 +218,42 @@ or via environment variables.
- `MIMALLOC_SHOW_STATS=1`: show statistics when the program terminates. - `MIMALLOC_SHOW_STATS=1`: show statistics when the program terminates.
- `MIMALLOC_VERBOSE=1`: show verbose messages. - `MIMALLOC_VERBOSE=1`: show verbose messages.
- `MIMALLOC_SHOW_ERRORS=1`: show error and warning messages. - `MIMALLOC_SHOW_ERRORS=1`: show error and warning messages.
- `MIMALLOC_PAGE_RESET=1`: reset (or purge) OS pages when not in use. This can reduce - `MIMALLOC_PAGE_RESET=0`: by default, mimalloc will reset (or purge) OS pages that are not in use, to signal to the OS
memory fragmentation in long running (server) programs. If performance is impacted, that the underlying physical memory can be reused. This can reduce memory fragmentation in long running (server)
`MIMALLOC_RESET_DELAY=`<msecs> can be set higher (100ms by default) to make the page programs. By setting it to `0` this will no longer be done which can improve performance for batch-like programs.
reset occur less frequently. As an alternative, the `MIMALLOC_RESET_DELAY=`<msecs> can be set higher (100ms by default) to make the page
- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages when available; for some workloads this can significantly reset occur less frequently instead of turning it off completely.
- `MIMALLOC_USE_NUMA_NODES=N`: pretend there are at most `N` NUMA nodes. If not set, the actual NUMA nodes are detected
at runtime. Setting `N` to 1 may avoid problems in some virtual environments. Also, setting it to a lower number than
the actual NUMA nodes is fine and will only cause threads to potentially allocate more memory across actual NUMA
nodes (but this can happen in any case as NUMA local allocation is always a best effort but not guaranteed).
- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages (2MiB) when available; for some workloads this can significantly
improve performance. Use `MIMALLOC_VERBOSE` to check if the large OS pages are enabled -- usually one needs improve performance. Use `MIMALLOC_VERBOSE` to check if the large OS pages are enabled -- usually one needs
to explicitly allow large OS pages (as on [Windows][windows-huge] and [Linux][linux-huge]). However, sometimes to explicitly allow large OS pages (as on [Windows][windows-huge] and [Linux][linux-huge]). However, sometimes
the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that
can have fragmented memory (for that reason, we generally recommend to use `MIMALLOC_RESERVE_HUGE_OS_PAGES` instead when possible). can have fragmented memory (for that reason, we generally recommend to use `MIMALLOC_RESERVE_HUGE_OS_PAGES` instead whenever possible).
<!-- <!--
- `MIMALLOC_EAGER_REGION_COMMIT=1`: on Windows, commit large (256MiB) regions eagerly. On Windows, these regions - `MIMALLOC_EAGER_REGION_COMMIT=1`: on Windows, commit large (256MiB) regions eagerly. On Windows, these regions
show in the working set even though usually just a small part is committed to physical memory. This is why it show in the working set even though usually just a small part is committed to physical memory. This is why it
turned off by default on Windows as it looks not good in the task manager. However, turning it on has no turned off by default on Windows as it looks not good in the task manager. However, turning it on has no
real drawbacks and may improve performance by a little. real drawbacks and may improve performance by a little.
--> -->
- `MIMALLOC_RESERVE_HUGE_OS_PAGES=N`: where N is the number of 1GiB huge OS pages. This reserves the huge pages at - `MIMALLOC_RESERVE_HUGE_OS_PAGES=N`: where N is the number of 1GiB _huge_ OS pages. This reserves the huge pages at
startup and can give quite a (latency) performance improvement on long running workloads. Usually it is better to not use startup and sometimes this can give a large (latency) performance improvement on big workloads.
Usually it is better to not use
`MIMALLOC_LARGE_OS_PAGES` in combination with this setting. Just like large OS pages, use with care as reserving `MIMALLOC_LARGE_OS_PAGES` in combination with this setting. Just like large OS pages, use with care as reserving
contiguous physical memory can take a long time when memory is fragmented (but reserving the huge pages is done at contiguous physical memory can take a long time when memory is fragmented (but reserving the huge pages is done at
startup only once). startup only once).
Note that we usually need to explicitly enable huge OS pages (as on [Windows][windows-huge] and [Linux][linux-huge])). With huge OS pages, it may be beneficial to set the setting Note that we usually need to explicitly enable huge OS pages (as on [Windows][windows-huge] and [Linux][linux-huge])).
`MIMALLOC_EAGER_COMMIT_DELAY=N` (with usually `N` as 1) to delay the initial `N` segments With huge OS pages, it may be beneficial to set the setting
`MIMALLOC_EAGER_COMMIT_DELAY=N` (`N` is 1 by default) to delay the initial `N` segments (of 4MiB)
of a thread to not allocate in the huge OS pages; this prevents threads that are short lived of a thread to not allocate in the huge OS pages; this prevents threads that are short lived
and allocate just a little to take up space in the huge OS page area (which cannot be reset). and allocate just a little to take up space in the huge OS page area (which cannot be reset).
Use caution when using `fork` in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write
for all pages in the original process including the huge OS pages. When any memory is now written in that area, the
OS will copy the entire 1GiB huge page (or 2MiB large page) which can cause the memory usage to grow in big increments.
[linux-huge]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5 [linux-huge]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/sect-oracle_9i_and_10g_tuning_guide-large_memory_optimization_big_pages_and_huge_pages-configuring_huge_pages_in_red_hat_enterprise_linux_4_or_5
[windows-huge]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017 [windows-huge]: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/enable-the-lock-pages-in-memory-option-windows?view=sql-server-2017
@ -282,9 +301,13 @@ the [shell](https://stackoverflow.com/questions/43941322/dyld-insert-libraries-i
### Override on Windows ### Override on Windows
<span id="override_on_windows">Overriding on Windows</span> is robust but requires that you link your program explicitly with <span id="override_on_windows">Overriding on Windows</span> is robust and has the
particular advantage to be able to redirect all malloc/free calls that go through
the (dynamic) C runtime allocator, including those from other DLL's or libraries.
The overriding on Windows requires that you link your program explicitly with
the mimalloc DLL and use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch). the mimalloc DLL and use the C-runtime library as a DLL (using the `/MD` or `/MDd` switch).
Moreover, you need to ensure the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) is available Also, the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) must be available
in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency). in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency).
The redirection DLL ensures that all calls to the C runtime malloc API get redirected to The redirection DLL ensures that all calls to the C runtime malloc API get redirected to
mimalloc (in `mimalloc-override.dll`). mimalloc (in `mimalloc-override.dll`).
@ -299,8 +322,9 @@ is also recommended to also override the `new`/`delete` operations (by including
The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic The environment variable `MIMALLOC_DISABLE_REDIRECT=1` can be used to disable dynamic
overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected. overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected.
(Note: in principle, it is possible to patch existing executables (Note: in principle, it is possible to even patch existing executables without any recompilation
that are linked with the dynamic C runtime (`ucrtbase.dll`) by just putting the `mimalloc-override.dll` into the import table (and putting `mimalloc-redirect.dll` in the same folder) if they are linked with the dynamic C runtime (`ucrtbase.dll`) -- just put the `mimalloc-override.dll`
into the import table (and put `mimalloc-redirect.dll` in the same folder)
Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388)). Such patching can be done for example with [CFF Explorer](https://ntcore.com/?page_id=388)).

View file

@ -41,8 +41,11 @@ extern malloc_zone_t* malloc_default_purgeable_zone(void) __attribute__((weak_im
------------------------------------------------------ */ ------------------------------------------------------ */
static size_t zone_size(malloc_zone_t* zone, const void* p) { static size_t zone_size(malloc_zone_t* zone, const void* p) {
UNUSED(zone); UNUSED(p); UNUSED(zone);
return 0; // as we cannot guarantee that `p` comes from us, just return 0 if (!mi_is_in_heap_region(p))
return 0; // not our pointer, bail out
return mi_usable_size(p);
} }
static void* zone_malloc(malloc_zone_t* zone, size_t size) { static void* zone_malloc(malloc_zone_t* zone, size_t size) {

View file

@ -163,18 +163,30 @@ extern "C" {
// Posix & Unix functions definitions // Posix & Unix functions definitions
// ------------------------------------------------------ // ------------------------------------------------------
void* reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize);
size_t malloc_size(void* p) MI_FORWARD1(mi_usable_size,p);
size_t malloc_usable_size(void *p) MI_FORWARD1(mi_usable_size,p);
void cfree(void* p) MI_FORWARD0(mi_free, p); void cfree(void* p) MI_FORWARD0(mi_free, p);
void* reallocf(void* p, size_t newsize) MI_FORWARD2(mi_reallocf,p,newsize);
size_t malloc_size(const void* p) MI_FORWARD1(mi_usable_size,p);
#if !defined(__ANDROID__)
size_t malloc_usable_size(void *p) MI_FORWARD1(mi_usable_size,p);
#else
size_t malloc_usable_size(const void *p) MI_FORWARD1(mi_usable_size,p);
#endif
// no forwarding here due to aliasing/name mangling issues // no forwarding here due to aliasing/name mangling issues
void* valloc(size_t size) { return mi_valloc(size); } void* valloc(size_t size) { return mi_valloc(size); }
void* pvalloc(size_t size) { return mi_pvalloc(size); } void* pvalloc(size_t size) { return mi_pvalloc(size); }
void* reallocarray(void* p, size_t count, size_t size) { return mi_reallocarray(p, count, size); } void* reallocarray(void* p, size_t count, size_t size) { return mi_reallocarray(p, count, size); }
void* memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); } void* memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); }
void* aligned_alloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); } int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p, alignment, size); }
int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p, alignment, size); } void* _aligned_malloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); }
// on some glibc `aligned_alloc` is declared `static inline` so we cannot override it (e.g. Conda). This happens
// when _GLIBCXX_HAVE_ALIGNED_ALLOC is not defined. However, in those cases it will use `memalign`, `posix_memalign`,
// or `_aligned_malloc` and we can avoid overriding it ourselves.
#if _GLIBCXX_HAVE_ALIGNED_ALLOC
void* aligned_alloc(size_t alignment, size_t size) { return mi_aligned_alloc(alignment, size); }
#endif
#if defined(__GLIBC__) && defined(__linux__) #if defined(__GLIBC__) && defined(__linux__)
// forward __libc interface (needed for glibc-based Linux distributions) // forward __libc interface (needed for glibc-based Linux distributions)
@ -184,10 +196,10 @@ int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_me
void __libc_free(void* p) MI_FORWARD0(mi_free,p); void __libc_free(void* p) MI_FORWARD0(mi_free,p);
void __libc_cfree(void* p) MI_FORWARD0(mi_free,p); void __libc_cfree(void* p) MI_FORWARD0(mi_free,p);
void* __libc_valloc(size_t size) { return mi_valloc(size); } void* __libc_valloc(size_t size) { return mi_valloc(size); }
void* __libc_pvalloc(size_t size) { return mi_pvalloc(size); } void* __libc_pvalloc(size_t size) { return mi_pvalloc(size); }
void* __libc_memalign(size_t alignment, size_t size) { return mi_memalign(alignment,size); } void* __libc_memalign(size_t alignment, size_t size) { return mi_memalign(alignment,size); }
int __posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p,alignment,size); } int __posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_memalign(p,alignment,size); }
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -649,12 +649,13 @@ mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept {
// `strndup` using mi_malloc // `strndup` using mi_malloc
mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept { mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept {
if (s == NULL) return NULL; if (s == NULL) return NULL;
size_t m = strlen(s); const char* end = (const char*)memchr(s, 0, n); // find end of string in the first `n` characters (returns NULL if not found)
if (n > m) n = m; const size_t m = (end != NULL ? (size_t)(end - s) : n); // `m` is the minimum of `n` or the end-of-string
char* t = (char*)mi_heap_malloc(heap, n+1); mi_assert_internal(m <= n);
char* t = (char*)mi_heap_malloc(heap, m+1);
if (t == NULL) return NULL; if (t == NULL) return NULL;
memcpy(t, s, n); memcpy(t, s, m);
t[n] = 0; t[m] = 0;
return t; return t;
} }

View file

@ -36,6 +36,7 @@ of 256MiB in practice.
// os.c // os.c
void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld); void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_os_tld_t* tld);
void _mi_os_free_ex(void* p, size_t size, bool was_committed, mi_stats_t* stats);
void _mi_os_free(void* p, size_t size, mi_stats_t* stats); void _mi_os_free(void* p, size_t size, mi_stats_t* stats);
void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_secs, size_t* pages_reserved, size_t* psize); void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_secs, size_t* pages_reserved, size_t* psize);
@ -213,13 +214,13 @@ void* _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_zero, siz
Arena free Arena free
----------------------------------------------------------- */ ----------------------------------------------------------- */
void _mi_arena_free(void* p, size_t size, size_t memid, mi_stats_t* stats) { void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_stats_t* stats) {
mi_assert_internal(size > 0 && stats != NULL); mi_assert_internal(size > 0 && stats != NULL);
if (p==NULL) return; if (p==NULL) return;
if (size==0) return; if (size==0) return;
if (memid == MI_MEMID_OS) { if (memid == MI_MEMID_OS) {
// was a direct OS allocation, pass through // was a direct OS allocation, pass through
_mi_os_free(p, size, stats); _mi_os_free_ex(p, size, all_committed, stats);
} }
else { else {
// allocated in an arena // allocated in an arena

View file

@ -247,10 +247,12 @@ static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment
void* p = VirtualAlloc(hint, size, flags, PAGE_READWRITE); void* p = VirtualAlloc(hint, size, flags, PAGE_READWRITE);
if (p != NULL) return p; if (p != NULL) return p;
DWORD err = GetLastError(); DWORD err = GetLastError();
if (err != ERROR_INVALID_ADDRESS) { // if linked with multiple instances, we may have tried to allocate at an already allocated area if (err != ERROR_INVALID_ADDRESS && // If linked with multiple instances, we may have tried to allocate at an already allocated area (#210)
err != ERROR_INVALID_PARAMETER) { // Windows7 instability (#230)
return NULL; return NULL;
} }
} // fall through
}
#endif #endif
#if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS) #if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS)
// on modern Windows try use VirtualAlloc2 for aligned allocation // on modern Windows try use VirtualAlloc2 for aligned allocation
@ -263,6 +265,7 @@ static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment
return (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, &param, 1); return (*pVirtualAlloc2)(GetCurrentProcess(), addr, size, flags, PAGE_READWRITE, &param, 1);
} }
#endif #endif
// last resort
return VirtualAlloc(addr, size, flags, PAGE_READWRITE); return VirtualAlloc(addr, size, flags, PAGE_READWRITE);
} }

View file

@ -49,7 +49,7 @@ bool _mi_os_reset(void* p, size_t size, mi_stats_t* stats);
bool _mi_os_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats); bool _mi_os_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats);
// arena.c // arena.c
void _mi_arena_free(void* p, size_t size, size_t memid, mi_stats_t* stats); void _mi_arena_free(void* p, size_t size, size_t memid, bool all_committed, mi_stats_t* stats);
void* _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld); void* _mi_arena_alloc(size_t size, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld);
void* _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld); void* _mi_arena_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* memid, mi_os_tld_t* tld);
@ -187,7 +187,7 @@ static bool mi_region_try_alloc_os(size_t blocks, bool commit, bool allow_large,
const uintptr_t idx = mi_atomic_increment(&regions_count); const uintptr_t idx = mi_atomic_increment(&regions_count);
if (idx >= MI_REGION_MAX) { if (idx >= MI_REGION_MAX) {
mi_atomic_decrement(&regions_count); mi_atomic_decrement(&regions_count);
_mi_arena_free(start, MI_REGION_SIZE, arena_memid, tld->stats); _mi_arena_free(start, MI_REGION_SIZE, arena_memid, region_commit, tld->stats);
_mi_warning_message("maximum regions used: %zu GiB (perhaps recompile with a larger setting for MI_HEAP_REGION_MAX_SIZE)", _mi_divide_up(MI_HEAP_REGION_MAX_SIZE, GiB)); _mi_warning_message("maximum regions used: %zu GiB (perhaps recompile with a larger setting for MI_HEAP_REGION_MAX_SIZE)", _mi_divide_up(MI_HEAP_REGION_MAX_SIZE, GiB));
return false; return false;
} }
@ -391,7 +391,7 @@ void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_re
mem_region_t* region; mem_region_t* region;
if (mi_memid_is_arena(id,&region,&bit_idx,&arena_memid)) { if (mi_memid_is_arena(id,&region,&bit_idx,&arena_memid)) {
// was a direct arena allocation, pass through // was a direct arena allocation, pass through
_mi_arena_free(p, size, arena_memid, tld->stats); _mi_arena_free(p, size, arena_memid, full_commit, tld->stats);
} }
else { else {
// allocated in a region // allocated in a region
@ -454,12 +454,13 @@ void _mi_mem_collect(mi_os_tld_t* tld) {
// on success, free the whole region // on success, free the whole region
uint8_t* start = mi_atomic_read_ptr(uint8_t,&regions[i].start); uint8_t* start = mi_atomic_read_ptr(uint8_t,&regions[i].start);
size_t arena_memid = mi_atomic_read_relaxed(&regions[i].arena_memid); size_t arena_memid = mi_atomic_read_relaxed(&regions[i].arena_memid);
uintptr_t commit = mi_atomic_read_relaxed(&regions[i].commit);
memset(&regions[i], 0, sizeof(mem_region_t)); memset(&regions[i], 0, sizeof(mem_region_t));
// and release the whole region // and release the whole region
mi_atomic_write(&region->info, 0); mi_atomic_write(&region->info, 0);
if (start != NULL) { // && !_mi_os_is_huge_reserved(start)) { if (start != NULL) { // && !_mi_os_is_huge_reserved(start)) {
_mi_abandoned_await_readers(); // ensure no pending reads _mi_abandoned_await_readers(); // ensure no pending reads
_mi_arena_free(start, MI_REGION_SIZE, arena_memid, tld->stats); _mi_arena_free(start, MI_REGION_SIZE, arena_memid, (~commit == 0), tld->stats);
} }
} }
} }

View file

@ -204,9 +204,9 @@ static void mi_segment_protect(mi_segment_t* segment, bool protect, mi_os_tld_t*
mi_segment_protect_range((uint8_t*)segment + segment->segment_info_size - os_page_size, os_page_size, protect); mi_segment_protect_range((uint8_t*)segment + segment->segment_info_size - os_page_size, os_page_size, protect);
if (MI_SECURE <= 1 || segment->capacity == 1) { if (MI_SECURE <= 1 || segment->capacity == 1) {
// and protect the last (or only) page too // and protect the last (or only) page too
mi_assert_internal(segment->page_kind >= MI_PAGE_LARGE); mi_assert_internal(MI_SECURE <= 1 || segment->page_kind >= MI_PAGE_LARGE);
uint8_t* start = (uint8_t*)segment + segment->segment_size - os_page_size; uint8_t* start = (uint8_t*)segment + segment->segment_size - os_page_size;
if (protect && !mi_option_is_enabled(mi_option_eager_page_commit)) { if (protect && !segment->mem_is_committed) {
// ensure secure page is committed // ensure secure page is committed
_mi_mem_commit(start, os_page_size, NULL, tld); _mi_mem_commit(start, os_page_size, NULL, tld);
} }
@ -236,12 +236,12 @@ static void mi_page_reset(mi_segment_t* segment, mi_page_t* page, size_t size, m
void* start = mi_segment_raw_page_start(segment, page, &psize); void* start = mi_segment_raw_page_start(segment, page, &psize);
page->is_reset = true; page->is_reset = true;
mi_assert_internal(size <= psize); mi_assert_internal(size <= psize);
size_t reset_size = (size == 0 || size > psize ? psize : size); size_t reset_size = ((size == 0 || size > psize) ? psize : size);
if (size == 0 && segment->page_kind >= MI_PAGE_LARGE && !mi_option_is_enabled(mi_option_eager_page_commit)) { if (size == 0 && segment->page_kind >= MI_PAGE_LARGE && !mi_option_is_enabled(mi_option_eager_page_commit)) {
mi_assert_internal(page->xblock_size > 0); mi_assert_internal(page->xblock_size > 0);
reset_size = page->capacity * mi_page_block_size(page); reset_size = page->capacity * mi_page_block_size(page);
} }
_mi_mem_reset(start, reset_size, tld->os); if (reset_size > 0) _mi_mem_reset(start, reset_size, tld->os);
} }
static void mi_page_unreset(mi_segment_t* segment, mi_page_t* page, size_t size, mi_segments_tld_t* tld) static void mi_page_unreset(mi_segment_t* segment, mi_page_t* page, size_t size, mi_segments_tld_t* tld)
@ -258,7 +258,7 @@ static void mi_page_unreset(mi_segment_t* segment, mi_page_t* page, size_t size,
unreset_size = page->capacity * mi_page_block_size(page); unreset_size = page->capacity * mi_page_block_size(page);
} }
bool is_zero = false; bool is_zero = false;
_mi_mem_unreset(start, unreset_size, &is_zero, tld->os); if (unreset_size > 0) _mi_mem_unreset(start, unreset_size, &is_zero, tld->os);
if (is_zero) page->is_zero_init = true; if (is_zero) page->is_zero_init = true;
} }
@ -627,8 +627,13 @@ static mi_segment_t* mi_segment_init(mi_segment_t* segment, size_t required, mi_
if (!commit) { if (!commit) {
// ensure the initial info is committed // ensure the initial info is committed
bool commit_zero = false; bool commit_zero = false;
_mi_mem_commit(segment, pre_size, &commit_zero, tld->os); bool ok = _mi_mem_commit(segment, pre_size, &commit_zero, tld->os);
if (commit_zero) is_zero = true; if (commit_zero) is_zero = true;
if (!ok) {
// commit failed; we cannot touch the memory: free the segment directly and return `NULL`
_mi_mem_free(segment, MI_SEGMENT_SIZE, memid, false, false, os_tld);
return NULL;
}
} }
segment->memid = memid; segment->memid = memid;
segment->mem_is_fixed = mem_large; segment->mem_is_fixed = mem_large;
@ -714,28 +719,30 @@ static bool mi_segment_has_free(const mi_segment_t* segment) {
return (segment->used < segment->capacity); return (segment->used < segment->capacity);
} }
static void mi_segment_page_claim(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) { static bool mi_segment_page_claim(mi_segment_t* segment, mi_page_t* page, mi_segments_tld_t* tld) {
mi_assert_internal(_mi_page_segment(page) == segment); mi_assert_internal(_mi_page_segment(page) == segment);
mi_assert_internal(!page->segment_in_use); mi_assert_internal(!page->segment_in_use);
// set in-use before doing unreset to prevent delayed reset
mi_pages_reset_remove(page, tld); mi_pages_reset_remove(page, tld);
page->segment_in_use = true; // check commit
segment->used++;
if (!page->is_committed) { if (!page->is_committed) {
mi_assert_internal(!segment->mem_is_fixed); mi_assert_internal(!segment->mem_is_fixed);
mi_assert_internal(!page->is_reset); mi_assert_internal(!page->is_reset);
page->is_committed = true; if (segment->page_kind < MI_PAGE_LARGE || mi_option_is_enabled(mi_option_eager_page_commit)) {
if (segment->page_kind < MI_PAGE_LARGE
|| !mi_option_is_enabled(mi_option_eager_page_commit)) {
size_t psize; size_t psize;
uint8_t* start = mi_segment_raw_page_start(segment, page, &psize); uint8_t* start = mi_segment_raw_page_start(segment, page, &psize);
bool is_zero = false; bool is_zero = false;
const size_t gsize = (MI_SECURE >= 2 ? _mi_os_page_size() : 0); const size_t gsize = (MI_SECURE >= 2 ? _mi_os_page_size() : 0);
_mi_mem_commit(start, psize + gsize, &is_zero, tld->os); bool ok = _mi_mem_commit(start, psize + gsize, &is_zero, tld->os);
if (!ok) return false; // failed to commit!
if (gsize > 0) { mi_segment_protect_range(start + psize, gsize, true); } if (gsize > 0) { mi_segment_protect_range(start + psize, gsize, true); }
if (is_zero) { page->is_zero_init = true; } if (is_zero) { page->is_zero_init = true; }
} }
page->is_committed = true;
} }
// set in-use before doing unreset to prevent delayed reset
page->segment_in_use = true;
segment->used++;
// check reset
if (page->is_reset) { if (page->is_reset) {
mi_page_unreset(segment, page, 0, tld); // todo: only unreset the part that was reset? mi_page_unreset(segment, page, 0, tld); // todo: only unreset the part that was reset?
} }
@ -746,6 +753,7 @@ static void mi_segment_page_claim(mi_segment_t* segment, mi_page_t* page, mi_seg
mi_assert_internal(!mi_segment_has_free(segment)); mi_assert_internal(!mi_segment_has_free(segment));
mi_segment_remove_from_free_queue(segment, tld); mi_segment_remove_from_free_queue(segment, tld);
} }
return true;
} }
@ -1212,8 +1220,8 @@ static mi_page_t* mi_segment_find_free(mi_segment_t* segment, mi_segments_tld_t*
for (size_t i = 0; i < segment->capacity; i++) { // TODO: use a bitmap instead of search? for (size_t i = 0; i < segment->capacity; i++) { // TODO: use a bitmap instead of search?
mi_page_t* page = &segment->pages[i]; mi_page_t* page = &segment->pages[i];
if (!page->segment_in_use) { if (!page->segment_in_use) {
mi_segment_page_claim(segment, page, tld); bool ok = mi_segment_page_claim(segment, page, tld);
return page; if (ok) return page;
} }
} }
mi_assert(false); mi_assert(false);

View file

@ -24,5 +24,8 @@ terms of the MIT license. A copy of the license can be found in the file
#include "alloc.c" #include "alloc.c"
#include "alloc-aligned.c" #include "alloc-aligned.c"
#include "alloc-posix.c" #include "alloc-posix.c"
#if MI_OSX_ZONE
#include "alloc-override-osx.c"
#endif
#include "init.c" #include "init.c"
#include "options.c" #include "options.c"