Merge pull request #1 from microsoft/master

Update to last master
This commit is contained in:
synacker 2020-03-26 08:49:29 -07:00 committed by GitHub
commit 7b9fc77923
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
121 changed files with 14666 additions and 3753 deletions

View file

@ -1,24 +1,28 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
project(libmimalloc C CXX) project(libmimalloc C CXX)
include("cmake/mimalloc-config-version.cmake")
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
option(MI_OVERRIDE "Override the standard malloc interface" ON) option(MI_OVERRIDE "Override the standard malloc interface" ON)
option(MI_INTERPOSE "Use interpose to override standard malloc on macOS" ON) option(MI_DEBUG_FULL "Use full internal heap invariant checking in DEBUG mode" OFF)
option(MI_SEE_ASM "Generate assembly files" OFF) option(MI_SECURE "Use full security mitigations (like guard pages, allocation randomization, double-free mitigation, and free-list corruption detection)" OFF)
option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode" OFF)
option(MI_USE_CXX "Use the C++ compiler to compile the library" OFF) option(MI_USE_CXX "Use the C++ compiler to compile the library" OFF)
option(MI_SECURE "Use security mitigations (like guard pages and randomization)" OFF) option(MI_SEE_ASM "Generate assembly files" OFF)
option(MI_INTERPOSE "Use interpose to override standard malloc on macOS" ON)
option(MI_OSX_ZONE "Use malloc zone to override standard malloc on macOS" OFF) # enables interpose as well
option(MI_LOCAL_DYNAMIC_TLS "Use slightly slower, dlopen-compatible TLS mechanism (Unix)" OFF) option(MI_LOCAL_DYNAMIC_TLS "Use slightly slower, dlopen-compatible TLS mechanism (Unix)" OFF)
option(MI_BUILD_TESTS "Build test executables" ON) option(MI_BUILD_TESTS "Build test executables" ON)
option(MI_CHECK_FULL "Use full internal invariant checking in DEBUG mode (deprecated, use MI_DEBUG_FULL instead)" OFF)
set(mi_install_dir "lib/mimalloc-${mi_version}") include("cmake/mimalloc-config-version.cmake")
set(mi_sources set(mi_sources
src/stats.c src/stats.c
src/random.c
src/os.c src/os.c
src/memory.c src/arena.c
src/region.c
src/segment.c src/segment.c
src/page.c src/page.c
src/alloc.c src/alloc.c
@ -28,47 +32,56 @@ set(mi_sources
src/options.c src/options.c
src/init.c) src/init.c)
# Set default build type # -----------------------------------------------------------------------------
# Converience: set default build type depending on the build directory
# -----------------------------------------------------------------------------
if (NOT CMAKE_BUILD_TYPE) if (NOT CMAKE_BUILD_TYPE)
if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$") if ("${CMAKE_BINARY_DIR}" MATCHES ".*(D|d)ebug$" OR MI_DEBUG_FULL MATCHES "ON")
message(STATUS "No build type selected, default to *** Debug ***") message(STATUS "No build type selected, default to: Debug")
set(CMAKE_BUILD_TYPE "Debug") set(CMAKE_BUILD_TYPE "Debug")
else() else()
message(STATUS "No build type selected, default to *** Release ***") message(STATUS "No build type selected, default to: Release")
set(CMAKE_BUILD_TYPE "Release") set(CMAKE_BUILD_TYPE "Release")
endif() endif()
else()
message(STATUS "Build type specified as *** ${CMAKE_BUILD_TYPE} ***")
endif() endif()
if("${CMAKE_BINARY_DIR}" MATCHES ".*(S|s)ecure$") if("${CMAKE_BINARY_DIR}" MATCHES ".*(S|s)ecure$")
message(STATUS "Default to secure build")
set(MI_SECURE "ON") set(MI_SECURE "ON")
endif() endif()
if(CMAKE_C_COMPILER_ID MATCHES "MSVC") # -----------------------------------------------------------------------------
# Process options
# -----------------------------------------------------------------------------
if(CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel")
set(MI_USE_CXX "ON") set(MI_USE_CXX "ON")
endif() endif()
# Options
if(MI_OVERRIDE MATCHES "ON") if(MI_OVERRIDE MATCHES "ON")
message(STATUS "Override standard malloc (MI_OVERRIDE=ON)") message(STATUS "Override standard malloc (MI_OVERRIDE=ON)")
if(APPLE) if(APPLE)
if(MI_OSX_ZONE MATCHES "ON")
# use zone's on macOS
message(STATUS " Use malloc zone to override malloc (MI_OSX_ZONE=ON)")
list(APPEND mi_sources src/alloc-override-osx.c)
if(NOT MI_INTERPOSE MATCHES "ON")
message(STATUS " (enabling INTERPOSE as well since zone's require this)")
set(MI_INTERPOSE "ON")
endif()
endif()
if(MI_INTERPOSE MATCHES "ON") if(MI_INTERPOSE MATCHES "ON")
# use interpose on macOS # use interpose on macOS
message(STATUS " Use interpose to override malloc (MI_INTERPOSE=ON)") message(STATUS " Use interpose to override malloc (MI_INTERPOSE=ON)")
list(APPEND mi_defines MI_INTERPOSE) list(APPEND mi_defines MI_INTERPOSE)
else()
# use zone's on macOS
message(STATUS " Use zone's to override malloc (MI_INTERPOSE=OFF)")
list(APPEND mi_sources src/alloc-override-osx.c)
endif() endif()
endif() endif()
endif() endif()
if(MI_SECURE MATCHES "ON") if(MI_SECURE MATCHES "ON")
message(STATUS "Set secure build (MI_SECURE=ON)") message(STATUS "Set full secure build (MI_SECURE=ON)")
list(APPEND mi_defines MI_SECURE=2) list(APPEND mi_defines MI_SECURE=4)
endif() endif()
if(MI_SEE_ASM MATCHES "ON") if(MI_SEE_ASM MATCHES "ON")
@ -77,47 +90,50 @@ if(MI_SEE_ASM MATCHES "ON")
endif() endif()
if(MI_CHECK_FULL MATCHES "ON") if(MI_CHECK_FULL MATCHES "ON")
message(STATUS "Set debug level to full invariant checking (MI_CHECK_FULL=ON)") message(STATUS "The MI_CHECK_FULL option is deprecated, use MI_DEBUG_FULL instead")
set(MI_DEBUG_FULL "ON")
endif()
if(MI_DEBUG_FULL MATCHES "ON")
message(STATUS "Set debug level to full internal invariant checking (MI_DEBUG_FULL=ON)")
list(APPEND mi_defines MI_DEBUG=3) # full invariant checking list(APPEND mi_defines MI_DEBUG=3) # full invariant checking
endif() endif()
if(MI_USE_CXX MATCHES "ON") if(MI_USE_CXX MATCHES "ON")
message(STATUS "Use the C++ compiler to compile (MI_USE_CXX=ON)") message(STATUS "Use the C++ compiler to compile (MI_USE_CXX=ON)")
set_source_files_properties(${mi_sources} PROPERTIES LANGUAGE CXX ) set_source_files_properties(${mi_sources} PROPERTIES LANGUAGE CXX )
set_source_files_properties(src/static.c test/test-api.c PROPERTIES LANGUAGE CXX ) set_source_files_properties(src/static.c test/test-api.c test/test-stress PROPERTIES LANGUAGE CXX )
if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang|Clang")
list(APPEND mi_cflags -Wno-deprecated)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
list(APPEND mi_cflags -Kc++)
endif()
endif() endif()
# Compiler flags # Compiler flags
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU") if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU")
list(APPEND mi_cflags -Wall -Wextra -Wno-unknown-pragmas) list(APPEND mi_cflags -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden)
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
list(APPEND mi_cflags -Wno-invalid-memory-model)
endif()
endif()
if(CMAKE_C_COMPILER_ID MATCHES "Intel")
list(APPEND mi_cflags -Wall -fvisibility=hidden)
endif()
if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU|Intel")
if(MI_LOCAL_DYNAMIC_TLS MATCHES "ON") if(MI_LOCAL_DYNAMIC_TLS MATCHES "ON")
list(APPEND mi_cflags -ftls-model=local-dynamic) list(APPEND mi_cflags -ftls-model=local-dynamic)
else() else()
list(APPEND mi_cflags -ftls-model=initial-exec) list(APPEND mi_cflags -ftls-model=initial-exec)
endif() endif()
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
list(APPEND mi_cflags -Wno-invalid-memory-model)
list(APPEND mi_cflags -fvisibility=hidden)
list(APPEND mi_cflags -fbranch-target-load-optimize)
endif() endif()
endif()
if(NOT(CMAKE_BUILD_TYPE MATCHES "Release|release|RelWithDebInfo|relwithdebinfo"))
string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type)
set(mi_basename "mimalloc-${build_type}")
else()
if(MI_SECURE MATCHES "ON")
set(mi_basename "mimalloc-secure")
else()
set(mi_basename "mimalloc")
endif()
endif()
message(STATUS "Output library name : ${mi_basename}")
message(STATUS "Installation directory: ${mi_install_dir}")
# extra needed libraries # extra needed libraries
if(WIN32) if(WIN32)
list(APPEND mi_libraries psapi shell32 user32) list(APPEND mi_libraries psapi shell32 user32 bcrypt)
else() else()
list(APPEND mi_libraries pthread) list(APPEND mi_libraries pthread)
find_library(LIBRT rt) find_library(LIBRT rt)
@ -127,9 +143,28 @@ else()
endif() endif()
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Main targets # Install and output names
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
set(mi_install_dir "${CMAKE_INSTALL_PREFIX}/lib/mimalloc-${mi_version}")
if(MI_SECURE MATCHES "ON")
set(mi_basename "mimalloc-secure")
else()
set(mi_basename "mimalloc")
endif()
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LC)
if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel)$"))
set(mi_basename "${mi_basename}-${CMAKE_BUILD_TYPE_LC}") #append build type (e.g. -debug) if not a release version
endif()
message(STATUS "")
message(STATUS "Library base name: ${mi_basename}")
message(STATUS "Build type : ${CMAKE_BUILD_TYPE_LC}")
message(STATUS "Install directory: ${mi_install_dir}")
message(STATUS "")
# -----------------------------------------------------------------------------
# Main targets
# -----------------------------------------------------------------------------
# shared library # shared library
add_library(mimalloc SHARED ${mi_sources}) add_library(mimalloc SHARED ${mi_sources})
@ -218,7 +253,7 @@ if (MI_BUILD_TESTS MATCHES "ON")
target_compile_definitions(mimalloc-test-stress PRIVATE ${mi_defines}) target_compile_definitions(mimalloc-test-stress PRIVATE ${mi_defines})
target_compile_options(mimalloc-test-stress PRIVATE ${mi_cflags}) target_compile_options(mimalloc-test-stress PRIVATE ${mi_cflags})
target_include_directories(mimalloc-test-stress PRIVATE include) target_include_directories(mimalloc-test-stress PRIVATE include)
target_link_libraries(mimalloc-test-stress PRIVATE mimalloc-static ${mi_libraries}) target_link_libraries(mimalloc-test-stress PRIVATE mimalloc ${mi_libraries})
enable_testing() enable_testing()
add_test(test_api, mimalloc-test-api) add_test(test_api, mimalloc-test-api)
@ -231,7 +266,7 @@ endif()
if (MI_OVERRIDE MATCHES "ON") if (MI_OVERRIDE MATCHES "ON")
target_compile_definitions(mimalloc PRIVATE MI_MALLOC_OVERRIDE) target_compile_definitions(mimalloc PRIVATE MI_MALLOC_OVERRIDE)
if(NOT WIN32) if(NOT WIN32)
# It is only possible to override malloc on Windows when building as a DLL. (src/alloc-override.c) # It is only possible to override malloc on Windows when building as a DLL.
target_compile_definitions(mimalloc-static PRIVATE MI_MALLOC_OVERRIDE) target_compile_definitions(mimalloc-static PRIVATE MI_MALLOC_OVERRIDE)
target_compile_definitions(mimalloc-obj PRIVATE MI_MALLOC_OVERRIDE) target_compile_definitions(mimalloc-obj PRIVATE MI_MALLOC_OVERRIDE)
endif() endif()

View file

@ -13,16 +13,31 @@ jobs:
pool: pool:
vmImage: vmImage:
windows-2019 windows-2019
strategy:
matrix:
Debug:
BuildType: debug
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON
Release:
BuildType: release
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release
Secure:
BuildType: secure
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON
steps: steps:
- task: CMake@1 - task: CMake@1
inputs: inputs:
workingDirectory: 'build' workingDirectory: $(BuildType)
cmakeArgs: .. cmakeArgs: .. $(cmakeExtraArgs)
- task: MSBuild@1 - task: MSBuild@1
inputs: inputs:
solution: build/libmimalloc.sln solution: $(BuildType)/libmimalloc.sln
- upload: $(Build.SourcesDirectory)/build - script: |
artifact: windows cd $(BuildType)
ctest
displayName: CTest
- upload: $(Build.SourcesDirectory)/$(BuildType)
artifact: mimalloc-windows-$(BuildType)
- job: - job:
displayName: Linux displayName: Linux
@ -35,48 +50,78 @@ jobs:
CC: gcc CC: gcc
CXX: g++ CXX: g++
BuildType: debug BuildType: debug
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_CHECK_FULL=ON cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON
Release: Release:
CC: gcc CC: gcc
CXX: g++ CXX: g++
BuildType: release BuildType: release
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release
Secure:
CC: gcc
CXX: g++
BuildType: secure
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON
Debug++:
CC: gcc
CXX: g++
BuildType: debug-cxx
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON -DMI_USE_CXX=ON
Debug Clang: Debug Clang:
CC: clang CC: clang
CXX: clang++ CXX: clang++
BuildType: debug-clang BuildType: debug-clang
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_CHECK_FULL=ON cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON
Release Clang: Release Clang:
CC: clang CC: clang
CXX: clang++ CXX: clang++
BuildType: release-clang BuildType: release-clang
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release
Secure Clang:
CC: clang
CXX: clang++
BuildType: secure-clang
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON
Debug++ Clang:
CC: clang
CXX: clang++
BuildType: debug-clang-cxx
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON -DMI_USE_CXX=ON
steps: steps:
- task: CMake@1 - task: CMake@1
inputs: inputs:
workingDirectory: $(BuildType) workingDirectory: $(BuildType)
cmakeArgs: .. $(cmakeExtraArgs) cmakeArgs: .. $(cmakeExtraArgs)
- script: make -j$(nproc) -C $(BuildType) - script: make -j$(nproc) -C $(BuildType)
displayName: Make displayName: Make
- script: make test -C $(BuildType) - script: make test -C $(BuildType)
displayName: Ctest displayName: CTest
- upload: $(Build.SourcesDirectory)/$(BuildType) - upload: $(Build.SourcesDirectory)/$(BuildType)
artifact: ubuntu-$(BuildType) artifact: mimalloc-ubuntu-$(BuildType)
- job: - job:
displayName: macOS displayName: macOS
pool: pool:
vmImage: vmImage:
macOS-10.14 macOS-10.14
strategy:
matrix:
Debug:
BuildType: debug
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Debug -DMI_DEBUG_FULL=ON
Release:
BuildType: release
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release
Secure:
BuildType: secure
cmakeExtraArgs: -DCMAKE_BUILD_TYPE=Release -DMI_SECURE=ON
steps: steps:
- task: CMake@1 - task: CMake@1
inputs: inputs:
workingDirectory: 'build' workingDirectory: $(BuildType)
cmakeArgs: .. cmakeArgs: .. $(cmakeExtraArgs)
- script: make -j$(sysctl -n hw.ncpu) -C build - script: make -j$(sysctl -n hw.ncpu) -C $(BuildType)
- upload: $(Build.SourcesDirectory)/build displayName: Make
artifact: macos - script: make test -C $(BuildType)
displayName: CTest
- upload: $(Build.SourcesDirectory)/$(BuildType)
artifact: mimalloc-macos-$(BuildType)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,5 +1,5 @@
set(mi_version_major 1) set(mi_version_major 1)
set(mi_version_minor 1) set(mi_version_minor 6)
set(mi_version ${mi_version_major}.${mi_version_minor}) set(mi_version ${mi_version_major}.${mi_version_minor})
set(PACKAGE_VERSION ${mi_version}) set(PACKAGE_VERSION ${mi_version})

View file

@ -0,0 +1,886 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 2.4.2 -->
<svg height='167.731pt' version='1.1' viewBox='52.938 54.996 381.624 167.731' width='381.624pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<clipPath id='clip1'>
<path d='M82.148 206.586H434.164V81.34H82.148Z'/>
</clipPath>
<use id='g3-40' transform='scale(1.143)' xlink:href='#g0-40'/>
<use id='g3-41' transform='scale(1.143)' xlink:href='#g0-41'/>
<use id='g3-78' transform='scale(1.143)' xlink:href='#g0-78'/>
<use id='g3-97' transform='scale(1.143)' xlink:href='#g0-97'/>
<use id='g3-98' transform='scale(1.143)' xlink:href='#g0-98'/>
<use id='g3-99' transform='scale(1.143)' xlink:href='#g0-99'/>
<use id='g3-100' transform='scale(1.143)' xlink:href='#g0-100'/>
<use id='g3-101' transform='scale(1.143)' xlink:href='#g0-101'/>
<use id='g3-102' transform='scale(1.143)' xlink:href='#g0-102'/>
<use id='g3-105' transform='scale(1.143)' xlink:href='#g0-105'/>
<use id='g3-108' transform='scale(1.143)' xlink:href='#g0-108'/>
<use id='g3-109' transform='scale(1.143)' xlink:href='#g0-109'/>
<use id='g3-110' transform='scale(1.143)' xlink:href='#g0-110'/>
<use id='g3-111' transform='scale(1.143)' xlink:href='#g0-111'/>
<use id='g3-112' transform='scale(1.143)' xlink:href='#g0-112'/>
<use id='g3-114' transform='scale(1.143)' xlink:href='#g0-114'/>
<use id='g3-115' transform='scale(1.143)' xlink:href='#g0-115'/>
<use id='g3-116' transform='scale(1.143)' xlink:href='#g0-116'/>
<use id='g3-119' transform='scale(1.143)' xlink:href='#g0-119'/>
<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g1-82'/>
<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g1-97'/>
<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g1-101'/>
<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g1-105'/>
<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g1-108'/>
<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g1-109'/>
<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g1-116'/>
<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g1-118'/>
<use id='g2-46' transform='scale(0.714)' xlink:href='#g0-46'/>
<use id='g2-48' transform='scale(0.714)' xlink:href='#g0-48'/>
<use id='g2-49' transform='scale(0.714)' xlink:href='#g0-49'/>
<use id='g2-50' transform='scale(0.714)' xlink:href='#g0-50'/>
<use id='g2-51' transform='scale(0.714)' xlink:href='#g0-51'/>
<use id='g2-52' transform='scale(0.714)' xlink:href='#g0-52'/>
<use id='g2-53' transform='scale(0.714)' xlink:href='#g0-53'/>
<use id='g2-54' transform='scale(0.714)' xlink:href='#g0-54'/>
<use id='g2-55' transform='scale(0.714)' xlink:href='#g0-55'/>
<use id='g2-56' transform='scale(0.714)' xlink:href='#g0-56'/>
<use id='g2-57' transform='scale(0.714)' xlink:href='#g0-57'/>
<use id='g2-120' transform='scale(0.714)' xlink:href='#g0-120'/>
<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g4-1'/>
<path d='M2.127 -5.23C2.008 -5.23 1.995 -5.23 1.911 -5.154C1.032 -4.387 0.586 -3.145 0.586 -1.743C0.586 -0.425 0.983 0.844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 0.063C1.276 -0.481 1.193 -1.053 1.193 -1.743C1.193 -4.156 2.322 -5.112 2.462 -5.23H2.127Z' id='g0-40'/>
<path d='M0.746 1.743C0.865 1.743 0.879 1.743 0.962 1.667C1.841 0.9 2.287 -0.342 2.287 -1.743C2.287 -3.062 1.89 -4.331 0.969 -5.14C0.879 -5.23 0.865 -5.23 0.746 -5.23H0.411C0.432 -5.216 1.109 -4.638 1.43 -3.55C1.597 -3.006 1.681 -2.434 1.681 -1.743C1.681 0.669 0.551 1.625 0.411 1.743H0.746Z' id='g0-41'/>
<path d='M1.339 -0.628H0.711V0H1.339V-0.628Z' id='g0-46'/>
<path d='M3.403 -2.267C3.403 -2.601 3.403 -3.417 3.075 -3.989C2.72 -4.617 2.183 -4.721 1.848 -4.721C1.534 -4.721 0.99 -4.624 0.642 -4.024C0.307 -3.466 0.293 -2.706 0.293 -2.267C0.293 -1.75 0.321 -1.116 0.614 -0.586C0.921 -0.021 1.437 0.146 1.848 0.146C2.545 0.146 2.929 -0.258 3.138 -0.697C3.382 -1.193 3.403 -1.834 3.403 -2.267ZM1.848 -0.314C1.555 -0.314 1.22 -0.481 1.046 -0.983C0.907 -1.409 0.9 -1.848 0.9 -2.357C0.9 -2.999 0.9 -4.261 1.848 -4.261S2.797 -2.999 2.797 -2.357C2.797 -1.897 2.797 -1.374 2.629 -0.928C2.434 -0.425 2.078 -0.314 1.848 -0.314Z' id='g0-48'/>
<path d='M2.239 -4.721H2.085C1.632 -4.303 1.06 -4.275 0.642 -4.261V-3.822C0.914 -3.829 1.262 -3.843 1.611 -3.982V-0.439H0.683V0H3.166V-0.439H2.239V-4.721Z' id='g0-49'/>
<path d='M1.974 -0.537C1.89 -0.537 1.806 -0.53 1.723 -0.53H0.928L2.008 -1.485C2.134 -1.597 2.476 -1.855 2.608 -1.967C2.915 -2.246 3.327 -2.608 3.327 -3.215C3.327 -4.003 2.741 -4.721 1.743 -4.721C1.004 -4.721 0.544 -4.324 0.307 -3.612L0.635 -3.201C0.795 -3.787 1.039 -4.24 1.646 -4.24C2.232 -4.24 2.678 -3.829 2.678 -3.201C2.678 -2.622 2.336 -2.294 1.918 -1.897C1.778 -1.757 1.402 -1.444 1.255 -1.304C1.053 -1.123 0.572 -0.656 0.37 -0.481V0H3.327V-0.537H1.974Z' id='g0-50'/>
<path d='M0.697 -3.578C0.983 -4.135 1.485 -4.289 1.82 -4.289C2.232 -4.289 2.538 -4.052 2.538 -3.654C2.538 -3.285 2.287 -2.831 1.757 -2.741C1.723 -2.734 1.695 -2.734 1.234 -2.699V-2.239H1.778C2.441 -2.239 2.685 -1.716 2.685 -1.276C2.685 -0.732 2.35 -0.314 1.806 -0.314C1.311 -0.314 0.746 -0.551 0.398 -0.997L0.307 -0.544C0.711 -0.091 1.276 0.146 1.82 0.146C2.734 0.146 3.389 -0.537 3.389 -1.269C3.389 -1.841 2.929 -2.301 2.378 -2.462C2.908 -2.734 3.18 -3.201 3.18 -3.654C3.18 -4.247 2.573 -4.721 1.827 -4.721C1.213 -4.721 0.704 -4.4 0.411 -3.982L0.697 -3.578Z' id='g0-51'/>
<path d='M2.762 -1.165H3.487V-1.625H2.762V-4.575H2.071L0.209 -1.625V-1.165H2.162V0H2.762V-1.165ZM0.802 -1.625C1.011 -1.953 2.211 -3.815 2.211 -4.233V-1.625H0.802Z' id='g0-52'/>
<path d='M1.144 -4.094H3.075V-4.575H0.586V-1.967H1.095C1.262 -2.343 1.59 -2.511 1.904 -2.511C2.19 -2.511 2.622 -2.315 2.622 -1.43C2.622 -0.516 2.043 -0.314 1.688 -0.314C1.227 -0.314 0.781 -0.558 0.544 -0.955L0.279 -0.537C0.621 -0.112 1.137 0.146 1.688 0.146C2.608 0.146 3.327 -0.565 3.327 -1.416C3.327 -2.28 2.685 -2.971 1.918 -2.971C1.618 -2.971 1.353 -2.866 1.144 -2.692V-4.094Z' id='g0-53'/>
<path d='M3.062 -4.582C2.685 -4.721 2.42 -4.721 2.287 -4.721C1.227 -4.721 0.307 -3.724 0.307 -2.253C0.307 -0.363 1.158 0.146 1.862 0.146C2.427 0.146 2.72 -0.119 2.936 -0.342C3.382 -0.816 3.389 -1.311 3.389 -1.555C3.389 -2.469 2.894 -3.229 2.218 -3.229C1.534 -3.229 1.165 -2.873 0.962 -2.671C1.053 -3.626 1.541 -4.289 2.294 -4.289C2.434 -4.289 2.713 -4.275 3.062 -4.142V-4.582ZM0.969 -1.534C0.969 -1.576 0.969 -1.681 0.976 -1.716C0.976 -2.19 1.276 -2.769 1.897 -2.769C2.748 -2.769 2.748 -1.792 2.748 -1.555C2.748 -1.29 2.748 -0.997 2.559 -0.704C2.392 -0.453 2.183 -0.314 1.862 -0.314C1.123 -0.314 1.004 -1.227 0.969 -1.534Z' id='g0-54'/>
<path d='M1.723 -4.038C1.806 -4.038 1.89 -4.045 1.974 -4.045H2.852C1.792 -3.006 1.116 -1.548 1.116 0.07H1.771C1.771 -1.967 2.762 -3.431 3.389 -4.087V-4.575H0.307V-4.038H1.723Z' id='g0-55'/>
<path d='M2.385 -2.469C2.845 -2.615 3.285 -2.985 3.285 -3.501C3.285 -4.135 2.678 -4.721 1.848 -4.721S0.411 -4.135 0.411 -3.501C0.411 -2.978 0.865 -2.608 1.311 -2.469C0.697 -2.28 0.307 -1.806 0.307 -1.269C0.307 -0.523 0.969 0.146 1.848 0.146S3.389 -0.523 3.389 -1.269C3.389 -1.806 2.992 -2.28 2.385 -2.469ZM1.848 -2.699C1.353 -2.699 0.948 -2.985 0.948 -3.494C0.948 -3.94 1.262 -4.289 1.848 -4.289C2.427 -4.289 2.748 -3.94 2.748 -3.494C2.748 -2.999 2.357 -2.699 1.848 -2.699ZM1.848 -0.314C1.367 -0.314 0.941 -0.621 0.941 -1.276C0.941 -1.904 1.346 -2.239 1.848 -2.239S2.755 -1.897 2.755 -1.276C2.755 -0.621 2.322 -0.314 1.848 -0.314Z' id='g0-56'/>
<path d='M0.537 -0.174C0.879 0.077 1.193 0.146 1.52 0.146C2.497 0.146 3.389 -0.837 3.389 -2.336C3.389 -4.24 2.545 -4.721 1.876 -4.721C1.255 -4.721 0.969 -4.428 0.767 -4.226C0.321 -3.773 0.307 -3.292 0.307 -3.02C0.307 -2.12 0.795 -1.346 1.478 -1.346C2.267 -1.346 2.699 -1.869 2.734 -1.911C2.636 -0.802 2.092 -0.314 1.52 -0.314C1.158 -0.314 0.934 -0.446 0.774 -0.579L0.537 -0.174ZM2.713 -3.027C2.72 -2.985 2.72 -2.915 2.72 -2.873C2.72 -2.357 2.406 -1.806 1.799 -1.806C1.534 -1.806 1.325 -1.883 1.144 -2.169C0.962 -2.441 0.948 -2.706 0.948 -3.02C0.948 -3.292 0.948 -3.605 1.165 -3.912C1.311 -4.122 1.52 -4.289 1.869 -4.289C2.545 -4.289 2.692 -3.473 2.713 -3.027Z' id='g0-57'/>
<path d='M1.646 -4.84H0.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-0.551H3.933L1.646 -4.84Z' id='g0-78'/>
<path d='M2.971 -2.008C2.971 -2.72 2.427 -3.201 1.736 -3.201C1.297 -3.201 0.962 -3.11 0.572 -2.901L0.614 -2.392C0.844 -2.545 1.186 -2.755 1.736 -2.755C2.043 -2.755 2.364 -2.525 2.364 -2.001V-1.723C1.332 -1.688 0.314 -1.471 0.314 -0.823C0.314 -0.474 0.551 0.07 1.165 0.07C1.465 0.07 2.015 0.007 2.385 -0.265V0H2.971V-2.008ZM2.364 -0.99C2.364 -0.851 2.364 -0.669 2.12 -0.523C1.897 -0.398 1.625 -0.391 1.548 -0.391C1.165 -0.391 0.872 -0.565 0.872 -0.83C0.872 -1.276 2.05 -1.318 2.364 -1.332V-0.99Z' id='g0-97'/>
<path d='M1.179 -4.84H0.593V0H1.2V-0.328C1.353 -0.195 1.688 0.07 2.197 0.07C2.957 0.07 3.571 -0.642 3.571 -1.555C3.571 -2.399 3.089 -3.166 2.392 -3.166C1.953 -3.166 1.527 -3.027 1.179 -2.769V-4.84ZM1.2 -2.197C1.2 -2.308 1.2 -2.392 1.444 -2.552C1.548 -2.615 1.736 -2.706 1.974 -2.706C2.441 -2.706 2.964 -2.392 2.964 -1.555C2.964 -0.704 2.385 -0.391 1.897 -0.391C1.639 -0.391 1.395 -0.509 1.2 -0.823V-2.197Z' id='g0-98'/>
<path d='M3.034 -0.76C2.685 -0.537 2.308 -0.411 1.876 -0.411C1.234 -0.411 0.858 -0.928 0.858 -1.555C0.858 -2.092 1.137 -2.72 1.897 -2.72C2.371 -2.72 2.594 -2.622 2.95 -2.399L3.041 -2.901C2.622 -3.11 2.441 -3.201 1.897 -3.201C0.851 -3.201 0.251 -2.357 0.251 -1.548C0.251 -0.697 0.921 0.07 1.869 0.07C2.357 0.07 2.776 -0.077 3.075 -0.251L3.034 -0.76Z' id='g0-99'/>
<path d='M3.229 -4.84H2.643V-2.797C2.197 -3.124 1.743 -3.166 1.541 -3.166C0.809 -3.166 0.251 -2.434 0.251 -1.548S0.802 0.07 1.52 0.07C1.953 0.07 2.357 -0.126 2.622 -0.363V0H3.229V-4.84ZM2.622 -0.865C2.448 -0.579 2.183 -0.391 1.848 -0.391C1.36 -0.391 0.858 -0.732 0.858 -1.541C0.858 -2.413 1.451 -2.706 1.925 -2.706C2.204 -2.706 2.441 -2.587 2.622 -2.35V-0.865Z' id='g0-100'/>
<path d='M2.999 -0.76C2.608 -0.481 2.169 -0.391 1.869 -0.391C1.262 -0.391 0.802 -0.886 0.781 -1.527H3.068C3.068 -1.848 3.034 -2.315 2.762 -2.713C2.511 -3.068 2.092 -3.201 1.75 -3.201C0.9 -3.201 0.244 -2.455 0.244 -1.569C0.244 -0.676 0.941 0.07 1.862 0.07C2.267 0.07 2.685 -0.049 3.041 -0.265L2.999 -0.76ZM0.83 -1.946C0.99 -2.504 1.402 -2.741 1.75 -2.741C2.057 -2.741 2.511 -2.594 2.643 -1.946H0.83Z' id='g0-101'/>
<path d='M1.325 -2.657H2.12V-3.096H1.304V-3.898C1.304 -4.38 1.743 -4.449 1.974 -4.449C2.12 -4.449 2.308 -4.428 2.566 -4.331V-4.84C2.385 -4.882 2.169 -4.91 1.981 -4.91C1.262 -4.91 0.739 -4.394 0.739 -3.703V-3.096H0.202V-2.657H0.739V0H1.325V-2.657Z' id='g0-102'/>
<path d='M1.227 -4.784H0.523V-4.08H1.227V-4.784ZM1.172 -3.096H0.586V0H1.172V-3.096Z' id='g0-105'/>
<path d='M1.172 -4.84H0.586V0H1.172V-4.84Z' id='g0-108'/>
<path d='M5.3 -2.064C5.3 -2.608 5.14 -3.166 4.282 -3.166C3.696 -3.166 3.333 -2.824 3.166 -2.601C3.096 -2.79 2.922 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-1.695C3.243 -2.155 3.438 -2.706 3.975 -2.706C4.693 -2.706 4.693 -2.218 4.693 -2.015V0H5.3V-2.064Z' id='g0-109'/>
<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-110'/>
<path d='M3.487 -1.527C3.487 -2.448 2.755 -3.201 1.848 -3.201S0.209 -2.441 0.209 -1.527C0.209 -0.642 0.948 0.07 1.848 0.07C2.755 0.07 3.487 -0.642 3.487 -1.527ZM1.848 -0.411C1.297 -0.411 0.816 -0.816 0.816 -1.604S1.332 -2.741 1.848 -2.741C2.371 -2.741 2.88 -2.378 2.88 -1.604C2.88 -0.809 2.385 -0.411 1.848 -0.411Z' id='g0-111'/>
<path d='M1.2 -0.328C1.569 0.007 1.967 0.07 2.204 0.07C2.943 0.07 3.571 -0.635 3.571 -1.555C3.571 -2.392 3.11 -3.166 2.42 -3.166C2.106 -3.166 1.583 -3.075 1.179 -2.762V-3.096H0.593V1.353H1.2V-0.328ZM1.2 -2.315C1.36 -2.511 1.632 -2.685 1.967 -2.685C2.525 -2.685 2.964 -2.169 2.964 -1.555C2.964 -0.865 2.441 -0.391 1.897 -0.391C1.792 -0.391 1.618 -0.404 1.437 -0.551C1.227 -0.711 1.2 -0.816 1.2 -0.948V-2.315Z' id='g0-112'/>
<path d='M1.179 -1.485C1.179 -2.239 1.806 -2.643 2.42 -2.65V-3.166C1.834 -3.159 1.409 -2.873 1.13 -2.504V-3.145H0.593V0H1.179V-1.485Z' id='g0-114'/>
<path d='M2.545 -2.985C2.071 -3.18 1.723 -3.201 1.471 -3.201C1.297 -3.201 0.244 -3.201 0.244 -2.273C0.244 -1.946 0.425 -1.764 0.516 -1.681C0.76 -1.437 1.053 -1.381 1.423 -1.311C1.75 -1.248 2.127 -1.179 2.127 -0.844C2.127 -0.404 1.548 -0.404 1.451 -0.404C1.004 -0.404 0.586 -0.565 0.307 -0.76L0.209 -0.237C0.446 -0.119 0.872 0.07 1.451 0.07C1.764 0.07 2.071 0.021 2.329 -0.167C2.587 -0.363 2.671 -0.669 2.671 -0.907C2.671 -1.032 2.657 -1.304 2.364 -1.569C2.106 -1.799 1.855 -1.848 1.52 -1.911C1.109 -1.988 0.788 -2.05 0.788 -2.357C0.788 -2.755 1.297 -2.755 1.402 -2.755C1.799 -2.755 2.106 -2.671 2.455 -2.49L2.545 -2.985Z' id='g0-115'/>
<path d='M1.311 -2.657H2.343V-3.096H1.311V-3.982H0.774V-3.096H0.139V-2.657H0.753V-0.893C0.753 -0.425 0.872 0.07 1.374 0.07S2.26 -0.091 2.469 -0.188L2.35 -0.635C2.12 -0.467 1.876 -0.411 1.681 -0.411C1.388 -0.411 1.311 -0.697 1.311 -1.018V-2.657Z' id='g0-116'/>
<path d='M4.951 -3.096H4.407C4.345 -2.901 3.954 -1.723 3.738 -0.997C3.682 -0.795 3.612 -0.572 3.592 -0.411H3.585C3.543 -0.697 3.299 -1.451 3.285 -1.499L2.769 -3.096H2.239C2.036 -2.497 1.513 -0.934 1.458 -0.425H1.451C1.395 -0.921 0.879 -2.462 0.767 -2.797C0.711 -2.964 0.711 -2.978 0.676 -3.096H0.105L1.123 0H1.709C1.716 -0.028 1.904 -0.579 2.148 -1.353C2.253 -1.695 2.462 -2.364 2.497 -2.671L2.504 -2.678C2.518 -2.532 2.559 -2.378 2.608 -2.204S2.706 -1.841 2.755 -1.681L3.292 0H3.933L4.951 -3.096Z' id='g0-119'/>
<path d='M1.932 -1.597L3.285 -3.096H2.671L1.681 -1.953L0.669 -3.096H0.042L1.437 -1.597L0 0H0.621L1.681 -1.311L2.783 0H3.41L1.932 -1.597Z' id='g0-120'/>
</defs>
<g id='page1'>
<path d='M140.82 215.441V206.586M199.488 215.441V206.586M258.156 215.441V206.586M316.824 215.441V206.586M375.496 215.441V206.586M140.82 72.48V81.34M199.488 72.48V81.34M258.156 72.48V81.34M316.824 72.48V81.34M375.496 72.48V81.34' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
<path d='M111.484 210.836V206.586M170.152 210.836V206.586M228.824 210.836V206.586M287.492 210.836V206.586M346.16 210.836V206.586M404.828 210.836V206.586M111.484 77.086V81.34M170.152 77.086V81.34M228.824 77.086V81.34M287.492 77.086V81.34M346.16 77.086V81.34M404.828 77.086V81.34' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
<path d='M82.148 206.586H86.402M82.148 175.273H86.402M82.148 143.961H86.402M82.148 112.648H86.402M82.148 81.34H86.402M434.164 206.586H429.91M434.164 175.273H429.91M434.164 143.961H429.91M434.164 112.648H429.91M434.164 81.34H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
<path d='M82.148 206.586V81.34H434.164V206.586H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<g transform='matrix(1 0 0 1 -11.54 34.954)'>
<use x='114.487' xlink:href='#g3-99' y='186.027'/>
<use x='118.25' xlink:href='#g3-102' y='186.027'/>
<use x='120.838' xlink:href='#g3-114' y='186.027'/>
<use x='123.73' xlink:href='#g3-97' y='186.027'/>
<use x='127.798' xlink:href='#g3-99' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 45.565 34.954)'>
<use x='114.487' xlink:href='#g3-108' y='186.027'/>
<use x='116.507' xlink:href='#g3-101' y='186.027'/>
<use x='120.271' xlink:href='#g3-97' y='186.027'/>
<use x='124.339' xlink:href='#g3-110' y='186.027'/>
<use x='128.711' xlink:href='#g3-78' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 106.188 34.954)'>
<use x='114.487' xlink:href='#g3-114' y='186.027'/>
<use x='117.379' xlink:href='#g3-101' y='186.027'/>
<use x='121.142' xlink:href='#g3-100' y='186.027'/>
<use x='125.515' xlink:href='#g3-105' y='186.027'/>
<use x='127.535' xlink:href='#g3-115' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 159.716 34.954)'>
<use x='114.487' xlink:href='#g3-108' y='186.027'/>
<use x='116.507' xlink:href='#g3-97' y='186.027'/>
<use x='120.34' xlink:href='#g3-114' y='186.027'/>
<use x='123.232' xlink:href='#g3-115' y='186.027'/>
<use x='126.478' xlink:href='#g3-111' y='186.027'/>
<use x='130.712' xlink:href='#g3-110' y='186.027'/>
<use x='135.085' xlink:href='#g3-78' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 215.596 34.954)'>
<use x='114.487' xlink:href='#g3-109' y='186.027'/>
<use x='121.211' xlink:href='#g3-115' y='186.027'/>
<use x='124.458' xlink:href='#g3-116' y='186.027'/>
<use x='127.516' xlink:href='#g3-114' y='186.027'/>
<use x='130.408' xlink:href='#g3-101' y='186.027'/>
<use x='134.171' xlink:href='#g3-115' y='186.027'/>
<use x='137.418' xlink:href='#g3-115' y='186.027'/>
<use x='140.664' xlink:href='#g3-78' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 277.158 34.954)'>
<use x='114.487' xlink:href='#g3-114' y='186.027'/>
<use x='117.379' xlink:href='#g3-112' y='186.027'/>
<use x='121.751' xlink:href='#g3-116' y='186.027'/>
<use x='124.809' xlink:href='#g3-101' y='186.027'/>
<use x='128.573' xlink:href='#g3-115' y='186.027'/>
<use x='131.819' xlink:href='#g3-116' y='186.027'/>
<use x='134.877' xlink:href='#g3-78' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 -40.942 22.192)'>
<use x='114.487' xlink:href='#g2-48' y='186.027'/>
<use x='117.133' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -9.12)'>
<use x='114.487' xlink:href='#g2-48' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-53' y='186.027'/>
<use x='121.25' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -40.431)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -71.743)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-53' y='186.027'/>
<use x='121.25' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -103.054)'>
<use x='114.487' xlink:href='#g2-50' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-120' y='186.027'/>
</g>
<path clip-path='url(#clip1)' d='M82.148 143.961H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M88.945 206.586H92.18V143.961H88.945ZM147.613 206.586H150.852V143.961H147.613ZM206.281 206.586H209.52V143.961H206.281ZM264.949 206.586H268.188V143.961H264.949ZM323.621 206.586H326.859V143.961H323.621ZM382.289 206.586H385.527V143.961H382.289Z' fill='#993333'/>
<path clip-path='url(#clip1)' d='M88.945 206.586H92.18V143.961H88.945ZM147.613 206.586H150.852V143.961H147.613ZM206.281 206.586H209.52V143.961H206.281ZM264.949 206.586H268.188V143.961H264.949ZM323.621 206.586H326.859V143.961H323.621ZM382.289 206.586H385.527V143.961H382.289Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M90.563 143.961V143.898' fill='#993333'/>
<path clip-path='url(#clip1)' d='M90.563 143.961V143.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M88.57 143.898H92.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M90.563 143.961V144.023' fill='#993333'/>
<path clip-path='url(#clip1)' d='M90.563 143.961V144.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M92.555 144.024H88.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M149.231 143.961V143.523' fill='#993333'/>
<path clip-path='url(#clip1)' d='M149.231 143.961V143.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M147.238 143.524H151.226' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M149.231 143.961V144.398' fill='#993333'/>
<path clip-path='url(#clip1)' d='M149.231 143.961V144.398' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M151.223 144.398H147.238' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M207.902 143.961V142.207' fill='#993333'/>
<path clip-path='url(#clip1)' d='M207.902 143.961V142.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M205.91 142.207H209.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M207.902 143.961V145.715' fill='#993333'/>
<path clip-path='url(#clip1)' d='M207.902 143.961V145.715' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M209.891 145.715H205.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M266.57 143.961V143.336' fill='#993333'/>
<path clip-path='url(#clip1)' d='M266.57 143.961V143.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M264.578 143.336H268.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M266.57 143.961V144.586' fill='#993333'/>
<path clip-path='url(#clip1)' d='M266.57 143.961V144.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M268.563 144.586H264.578' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M325.238 143.961V143.586' fill='#993333'/>
<path clip-path='url(#clip1)' d='M325.238 143.961V143.586' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M323.246 143.586H327.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M325.238 143.961V144.336' fill='#993333'/>
<path clip-path='url(#clip1)' d='M325.238 143.961V144.336' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M327.231 144.336H323.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M383.906 143.961V143.523' fill='#993333'/>
<path clip-path='url(#clip1)' d='M383.906 143.961V143.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M381.914 143.524H385.902' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M383.906 143.961V144.398' fill='#993333'/>
<path clip-path='url(#clip1)' d='M383.906 143.961V144.398' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M385.898 144.398H381.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M94.176 206.586H97.41V142.519H94.176ZM152.844 206.586H156.082V140.203H152.844ZM211.512 206.586H214.75V148.344H211.512ZM270.18 206.586H273.418V121.418H270.18ZM328.852 206.586H332.09V135.07H328.852ZM387.52 206.586H390.758V81.34H387.52Z' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M94.176 206.586H97.41V142.519H94.176ZM152.844 206.586H156.082V140.203H152.844ZM211.512 206.586H214.75V148.344H211.512ZM270.18 206.586H273.418V121.418H270.18ZM328.852 206.586H332.09V135.07H328.852ZM387.52 206.586H390.758V81.34H387.52Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M95.793 142.519V142.519' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M93.801 142.52H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M95.793 142.519V142.519' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M93.801 142.52H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M154.461 140.203V139.203' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M154.461 140.203V139.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M152.469 139.203H156.457' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M154.461 140.203V141.207' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M154.461 140.203V141.207' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M156.453 141.207H152.468' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M213.133 148.344V148.031' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M213.133 148.344V148.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M211.141 148.032H215.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M213.133 148.344V148.656' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M213.133 148.344V148.656' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M215.121 148.656H211.136' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M271.801 121.418V121.23' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M271.801 121.418V121.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M269.809 121.23H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M271.801 121.418V121.605' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M271.801 121.418V121.605' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M273.793 121.606H269.808' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M330.469 135.07V134.254' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M330.469 135.07V134.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M328.477 134.254H332.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M330.469 135.07V135.883' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M330.469 135.07V135.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M332.461 135.883H328.476' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M389.137 81.34V81.34' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M387.145 81.34H391.133' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M389.137 81.34V81.34' fill='#8080bf'/>
<path clip-path='url(#clip1)' d='M387.145 81.34H391.133' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M99.406 206.586H102.641V140.266H99.406ZM158.074 206.586H161.313V142.898H158.074ZM216.742 206.586H219.981V134.754H216.742ZM275.41 206.586H278.649V99.25H275.41ZM334.082 206.586H337.32V81.34H334.082ZM392.75 206.586H395.988V81.34H392.75Z' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M99.406 206.586H102.641V140.266H99.406ZM158.074 206.586H161.313V142.898H158.074ZM216.742 206.586H219.981V134.754H216.742ZM275.41 206.586H278.649V99.25H275.41ZM334.082 206.586H337.32V81.34H334.082ZM392.75 206.586H395.988V81.34H392.75Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M101.024 140.266V140.203' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M101.024 140.266V140.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M99.031 140.203H103.016' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M101.024 140.266V140.328' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M101.024 140.266V140.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M103.016 140.328H99.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M159.691 142.898V142.269' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M159.691 142.898V142.269' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M157.699 142.269H161.687' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M159.691 142.898V143.523' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M159.691 142.898V143.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M161.684 143.524H157.699' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M218.363 134.754V134.066' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M218.363 134.754V134.066' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M216.371 134.067H220.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M218.363 134.754V135.445' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M218.363 134.754V135.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M220.352 135.445H216.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M277.031 99.25V91.168' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M277.031 99.25V91.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M275.039 91.172H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M277.031 99.25V107.328' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M277.031 99.25V107.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M279.024 107.328H275.039' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M335.699 81.34V81.34' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M333.707 81.34H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M335.699 81.34V81.34' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M333.707 81.34H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M394.367 81.34V81.34' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M392.375 81.34H396.363' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M394.367 81.34V81.34' fill='#ffb733'/>
<path clip-path='url(#clip1)' d='M392.375 81.34H396.363' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M104.637 206.586H107.871V124.859H104.637ZM163.305 206.586H166.543V141.207H163.305ZM221.973 206.586H225.211V118.035H221.973ZM280.641 206.586H283.879V121.043H280.641ZM339.313 206.586H342.551V133.066H339.313ZM397.981 206.586H401.219V89.039H397.981Z' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M104.637 206.586H107.871V124.859H104.637ZM163.305 206.586H166.543V141.207H163.305ZM221.973 206.586H225.211V118.035H221.973ZM280.641 206.586H283.879V121.043H280.641ZM339.313 206.586H342.551V133.066H339.313ZM397.981 206.586H401.219V89.039H397.981Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M106.254 124.859V124.797' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M106.254 124.859V124.797' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M104.261 124.796H108.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M106.254 124.859V124.922' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M106.254 124.859V124.922' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M108.246 124.922H104.261' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M164.922 141.207V140.894' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M164.922 141.207V140.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M162.929 140.895H166.917' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M164.922 141.207V141.519' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M164.922 141.207V141.519' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M166.914 141.52H162.929' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M223.594 118.035V117.973' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M223.594 118.035V117.973' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M221.601 117.973H225.585' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M223.594 118.035V118.098' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M223.594 118.035V118.098' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M225.582 118.098H221.597' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M282.262 121.043V120.539' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M282.262 121.043V120.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M280.269 120.539H284.253' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M282.262 121.043V121.543' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M282.262 121.043V121.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M284.254 121.543H280.269' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M340.93 133.066V132.812' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M340.93 133.066V132.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M338.937 132.812H342.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M340.93 133.066V133.316' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M340.93 133.066V133.316' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M342.922 133.316H338.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M399.598 89.039V88.539' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M399.598 89.039V88.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M397.605 88.539H401.593' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M399.598 89.039V89.543' fill='#bf80bf'/>
<path clip-path='url(#clip1)' d='M399.598 89.039V89.543' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M401.59 89.543H397.605' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M109.867 206.586H113.102V142.332H109.867ZM168.535 206.586H171.774V143.086H168.535ZM227.203 206.586H230.442V132.125H227.203ZM285.871 206.586H289.109V139.641H285.871ZM344.543 206.586H347.781V81.34H344.543ZM403.211 206.586H406.449V100.187H403.211Z' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M109.867 206.586H113.102V142.332H109.867ZM168.535 206.586H171.774V143.086H168.535ZM227.203 206.586H230.442V132.125H227.203ZM285.871 206.586H289.109V139.641H285.871ZM344.543 206.586H347.781V81.34H344.543ZM403.211 206.586H406.449V100.187H403.211Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M111.484 142.332V142.269' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M111.484 142.332V142.269' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M109.492 142.269H113.477' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M111.484 142.332V142.394' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M111.484 142.332V142.394' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M113.477 142.395H109.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M170.152 143.086V142.644' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M170.152 143.086V142.644' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M168.16 142.644H172.145' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M170.152 143.086V143.523' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M170.152 143.086V143.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M172.145 143.524H168.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M228.824 132.125V131.312' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M228.824 132.125V131.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M226.832 131.312H230.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M228.824 132.125V132.941' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M228.824 132.125V132.941' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M230.813 132.941H226.828' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M287.492 139.641V138.387' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M287.492 139.641V138.387' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M285.5 138.387H289.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M287.492 139.641V140.894' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M287.492 139.641V140.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M289.485 140.895H285.5' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M346.16 81.34V81.34' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M344.168 81.34H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M346.16 81.34V81.34' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M344.168 81.34H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M404.828 100.187V99.562' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M404.828 100.187V99.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M402.836 99.562H406.824' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M404.828 100.187V100.812' fill='#dfbf9f'/>
<path clip-path='url(#clip1)' d='M404.828 100.187V100.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M406.821 100.813H402.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M115.098 206.586H118.332V135.57H115.098ZM173.766 206.586H177.004V136.07H173.766ZM232.434 206.586H235.672V114.965H232.434ZM291.102 206.586H294.34V113.84H291.102ZM349.774 206.586H353.012V81.34H349.774ZM408.442 206.586H411.68V81.34H408.442Z' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M115.098 206.586H118.332V135.57H115.098ZM173.766 206.586H177.004V136.07H173.766ZM232.434 206.586H235.672V114.965H232.434ZM291.102 206.586H294.34V113.84H291.102ZM349.774 206.586H353.012V81.34H349.774ZM408.442 206.586H411.68V81.34H408.442Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M116.715 135.57V135.508' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M116.715 135.57V135.508' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M114.722 135.508H118.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M116.715 135.57V135.633' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M116.715 135.57V135.633' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M118.707 135.633H114.722' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M175.383 136.07V135.258' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M175.383 136.07V135.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M173.39 135.258H177.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M175.383 136.07V136.883' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M175.383 136.07V136.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M177.375 136.883H173.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M234.055 114.965V114.09' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M234.055 114.965V114.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M232.062 114.09H236.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M234.055 114.965V115.844' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M234.055 114.965V115.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M236.043 115.843H232.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M292.723 113.84V113.215' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M292.723 113.84V113.215' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M290.73 113.215H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M292.723 113.84V114.465' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M292.723 113.84V114.465' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M294.715 114.465H290.73' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M351.391 81.34V81.34' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M349.398 81.34H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M351.391 81.34V81.34' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M349.398 81.34H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M410.059 81.34V81.34' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M408.066 81.34H412.054' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M410.059 81.34V81.34' fill='#80bf80'/>
<path clip-path='url(#clip1)' d='M408.066 81.34H412.054' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M120.328 206.586H123.563V135.633H120.328ZM178.996 206.586H182.234V81.34H178.996ZM237.664 206.586H240.902V138.387H237.664ZM296.332 206.586H299.57V81.34H296.332ZM355.004 206.586H358.238V81.34H355.004ZM413.672 206.586H416.91V81.34H413.672Z' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M120.328 206.586H123.563V135.633H120.328ZM178.996 206.586H182.234V81.34H178.996ZM237.664 206.586H240.902V138.387H237.664ZM296.332 206.586H299.57V81.34H296.332ZM355.004 206.586H358.238V81.34H355.004ZM413.672 206.586H416.91V81.34H413.672Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M121.945 135.633V135.57' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M121.945 135.633V135.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M119.953 135.571H123.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M121.945 135.633V135.695' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M121.945 135.633V135.695' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M123.938 135.695H119.953' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M180.613 81.34V81.34' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M178.621 81.34H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M180.613 81.34V81.34' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M178.621 81.34H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M239.285 138.387V136.195' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M239.285 138.387V136.195' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M237.293 136.195H241.278' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M239.285 138.387V140.578' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M239.285 138.387V140.578' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M241.274 140.578H237.289' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M297.953 81.34V81.34' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M295.961 81.34H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M297.953 81.34V81.34' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M295.961 81.34H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M356.621 81.34V81.34' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M354.629 81.34H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M356.621 81.34V81.34' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M354.629 81.34H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M415.289 81.34V81.34' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M413.297 81.34H417.285' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M415.289 81.34V81.34' fill='#bfbf80'/>
<path clip-path='url(#clip1)' d='M413.297 81.34H417.285' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M125.559 206.586H128.793V139.266H125.559ZM184.227 206.586H187.465V135.695H184.227ZM242.895 206.586H246.133V137.824H242.895ZM301.563 206.586H304.801V97.433H301.563ZM360.234 206.586H363.469V81.34H360.234ZM418.902 206.586H422.141V81.34H418.902Z' fill='#339999'/>
<path clip-path='url(#clip1)' d='M125.559 206.586H128.793V139.266H125.559ZM184.227 206.586H187.465V135.695H184.227ZM242.895 206.586H246.133V137.824H242.895ZM301.563 206.586H304.801V97.433H301.563ZM360.234 206.586H363.469V81.34H360.234ZM418.902 206.586H422.141V81.34H418.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M127.176 139.266V139.203' fill='#339999'/>
<path clip-path='url(#clip1)' d='M127.176 139.266V139.203' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M125.183 139.203H129.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M127.176 139.266V139.328' fill='#339999'/>
<path clip-path='url(#clip1)' d='M127.176 139.266V139.328' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M129.168 139.328H125.183' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M185.844 135.695V135.258' fill='#339999'/>
<path clip-path='url(#clip1)' d='M185.844 135.695V135.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M183.851 135.258H187.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M185.844 135.695V136.133' fill='#339999'/>
<path clip-path='url(#clip1)' d='M185.844 135.695V136.133' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M187.836 136.133H183.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M244.516 137.824V137.012' fill='#339999'/>
<path clip-path='url(#clip1)' d='M244.516 137.824V137.012' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M242.523 137.012H246.508' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M244.516 137.824V138.637' fill='#339999'/>
<path clip-path='url(#clip1)' d='M244.516 137.824V138.637' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M246.504 138.637H242.519' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M303.184 97.433V95.617' fill='#339999'/>
<path clip-path='url(#clip1)' d='M303.184 97.433V95.617' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M301.191 95.617H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M303.184 97.433V99.25' fill='#339999'/>
<path clip-path='url(#clip1)' d='M303.184 97.433V99.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M305.176 99.25H301.191' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M361.852 81.34V81.34' fill='#339999'/>
<path clip-path='url(#clip1)' d='M359.859 81.34H363.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M361.852 81.34V81.34' fill='#339999'/>
<path clip-path='url(#clip1)' d='M359.859 81.34H363.844' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M420.52 81.34V81.34' fill='#339999'/>
<path clip-path='url(#clip1)' d='M418.527 81.34H422.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M420.52 81.34V81.34' fill='#339999'/>
<path clip-path='url(#clip1)' d='M418.527 81.34H422.515' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M130.789 206.586H134.024V136.508H130.789ZM189.457 206.586H192.695V143.023H189.457ZM248.125 206.586H251.363V139.391H248.125ZM306.793 206.586H310.031V134.191H306.793ZM365.465 206.586H368.699V81.34H365.465ZM424.133 206.586H427.371V85.348H424.133Z' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M130.789 206.586H134.024V136.508H130.789ZM189.457 206.586H192.695V143.023H189.457ZM248.125 206.586H251.363V139.391H248.125ZM306.793 206.586H310.031V134.191H306.793ZM365.465 206.586H368.699V81.34H365.465ZM424.133 206.586H427.371V85.348H424.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M132.406 136.508V136.445' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M132.406 136.508V136.445' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M130.414 136.445H134.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M132.406 136.508V136.57' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M132.406 136.508V136.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M134.399 136.571H130.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M191.074 143.023V142.582' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M191.074 143.023V142.582' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M189.082 142.582H193.067' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M191.074 143.023V143.461' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M191.074 143.023V143.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M193.067 143.461H189.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M249.746 139.391V136.383' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M249.746 139.391V136.383' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M247.754 136.383H251.739' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M249.746 139.391V142.394' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M249.746 139.391V142.394' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M251.735 142.395H247.75' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M308.414 134.191V131.875' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M308.414 134.191V131.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M306.422 131.875H310.406' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M308.414 134.191V136.508' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M308.414 134.191V136.508' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M310.407 136.508H306.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M367.082 81.34V81.34' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M365.09 81.34H369.075' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M367.082 81.34V81.34' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M365.09 81.34H369.075' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M425.75 85.348V72.633' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M425.75 85.348V72.633' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M423.758 72.633H427.746' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M425.75 85.348V98.058' fill='#bf8080'/>
<path clip-path='url(#clip1)' d='M425.75 85.348V98.058' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip1)' d='M427.743 98.059H423.758' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<g transform='matrix(0 -1 1 0 -93.83 252.423)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-48' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -35.161 252.423)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-48' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 23.508 252.423)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-48' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 82.177 252.423)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-48' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 140.846 252.423)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-48' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 199.515 252.423)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-48' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -88.6 250.983)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-50' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -29.93 248.666)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-54' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 28.739 256.807)'>
<use x='114.487' xlink:href='#g2-48' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-57' y='186.027'/>
<use x='121.25' xlink:href='#g2-51' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 87.408 229.879)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-51' y='186.027'/>
<use x='121.25' xlink:href='#g2-54' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 146.077 243.531)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-52' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 204.746 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-53' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-56' y='186.027'/>
<use x='126.877' xlink:href='#g2-50' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -83.369 248.729)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-54' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -24.7 251.359)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-50' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 33.969 243.218)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-53' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 92.638 207.711)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-55' y='186.027'/>
<use x='121.25' xlink:href='#g2-49' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 151.307 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-50' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-51' y='186.027'/>
<use x='126.877' xlink:href='#g2-54' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 209.976 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-50' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-57' y='186.027'/>
<use x='126.877' xlink:href='#g2-49' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -78.139 233.323)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-51' y='186.027'/>
<use x='121.25' xlink:href='#g2-49' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -19.47 249.668)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-52' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 39.199 226.497)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-52' y='186.027'/>
<use x='121.25' xlink:href='#g2-49' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 97.868 229.503)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-51' y='186.027'/>
<use x='121.25' xlink:href='#g2-55' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 156.537 241.527)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-55' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 215.206 197.503)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-56' y='186.027'/>
<use x='121.25' xlink:href='#g2-56' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -72.908 250.795)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-51' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -14.239 251.547)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-49' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 44.43 240.588)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-57' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 103.099 248.102)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-55' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 161.768 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-50' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-49' y='186.027'/>
<use x='126.877' xlink:href='#g2-54' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 220.437 208.65)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-55' y='186.027'/>
<use x='121.25' xlink:href='#g2-48' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -67.678 244.032)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-51' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -9.009 244.533)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-51' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 49.66 223.429)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-52' y='186.027'/>
<use x='121.25' xlink:href='#g2-54' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 108.329 222.302)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-52' y='186.027'/>
<use x='121.25' xlink:href='#g2-56' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 166.998 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-56' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-52' y='186.027'/>
<use x='126.877' xlink:href='#g2-50' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 225.667 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-57' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-57' y='186.027'/>
<use x='126.877' xlink:href='#g2-51' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -62.447 244.095)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-51' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -3.778 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-51' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-54' y='186.027'/>
<use x='126.877' xlink:href='#g2-51' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 54.891 246.85)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-57' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 113.56 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-50' y='186.027'/>
<use x='122.76' xlink:href='#g2-51' y='186.027'/>
<use x='125.406' xlink:href='#g2-46' y='186.027'/>
<use x='126.877' xlink:href='#g2-57' y='186.027'/>
<use x='129.523' xlink:href='#g2-57' y='186.027'/>
<use x='132.169' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 172.229 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-49' y='186.027'/>
<use x='122.76' xlink:href='#g2-56' y='186.027'/>
<use x='125.406' xlink:href='#g2-46' y='186.027'/>
<use x='126.877' xlink:href='#g2-53' y='186.027'/>
<use x='129.523' xlink:href='#g2-52' y='186.027'/>
<use x='132.169' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 230.898 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-51' y='186.027'/>
<use x='122.76' xlink:href='#g2-52' y='186.027'/>
<use x='125.406' xlink:href='#g2-46' y='186.027'/>
<use x='126.877' xlink:href='#g2-52' y='186.027'/>
<use x='129.523' xlink:href='#g2-53' y='186.027'/>
<use x='132.169' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -57.217 247.727)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-56' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 1.452 244.157)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-51' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 60.121 246.286)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-48' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 118.79 205.895)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-55' y='186.027'/>
<use x='121.25' xlink:href='#g2-52' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 177.459 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-52' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-51' y='186.027'/>
<use x='126.877' xlink:href='#g2-51' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 236.128 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-50' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-49' y='186.027'/>
<use x='126.877' xlink:href='#g2-50' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -51.986 244.971)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-50' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 6.683 251.484)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-50' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 65.352 247.852)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-48' y='186.027'/>
<use x='121.25' xlink:href='#g2-55' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 124.021 242.654)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-49' y='186.027'/>
<use x='121.25' xlink:href='#g2-54' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 182.69 189.8)'>
<use x='109.598' xlink:href='#g4-1' y='186.027'/>
<use x='113.103' xlink:href='#g4-1' y='186.027'/>
<use x='116.608' xlink:href='#g4-1' y='186.027'/>
<use x='120.114' xlink:href='#g2-50' y='186.027'/>
<use x='122.76' xlink:href='#g2-46' y='186.027'/>
<use x='124.23' xlink:href='#g2-50' y='186.027'/>
<use x='126.877' xlink:href='#g2-55' y='186.027'/>
<use x='129.523' xlink:href='#g2-120' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 241.359 193.808)'>
<use x='114.487' xlink:href='#g2-49' y='186.027'/>
<use x='117.133' xlink:href='#g2-46' y='186.027'/>
<use x='118.603' xlink:href='#g2-57' y='186.027'/>
<use x='121.25' xlink:href='#g2-52' y='186.027'/>
</g>
<g transform='matrix(0 -1 1 0 -126.667 313.708)'>
<use x='114.487' xlink:href='#g1-82' y='186.027'/>
<use x='120.457' xlink:href='#g1-101' y='186.027'/>
<use x='124.553' xlink:href='#g1-108' y='186.027'/>
<use x='126.753' xlink:href='#g1-97' y='186.027'/>
<use x='131.181' xlink:href='#g1-116' y='186.027'/>
<use x='134.509' xlink:href='#g1-105' y='186.027'/>
<use x='136.709' xlink:href='#g1-118' y='186.027'/>
<use x='140.957' xlink:href='#g1-101' y='186.027'/>
<use x='148.124' xlink:href='#g1-116' y='186.027'/>
<use x='151.452' xlink:href='#g1-105' y='186.027'/>
<use x='153.652' xlink:href='#g1-109' y='186.027'/>
<use x='160.972' xlink:href='#g1-101' y='186.027'/>
<use x='168.139' xlink:href='#g3-40' y='186.027'/>
<use x='171.432' xlink:href='#g3-108' y='186.027'/>
<use x='173.453' xlink:href='#g3-111' y='186.027'/>
<use x='177.452' xlink:href='#g3-119' y='186.027'/>
<use x='183' xlink:href='#g3-101' y='186.027'/>
<use x='186.764' xlink:href='#g3-114' y='186.027'/>
<use x='192.479' xlink:href='#g3-105' y='186.027'/>
<use x='194.499' xlink:href='#g3-115' y='186.027'/>
<use x='200.568' xlink:href='#g3-98' y='186.027'/>
<use x='205.176' xlink:href='#g3-101' y='186.027'/>
<use x='208.94' xlink:href='#g3-116' y='186.027'/>
<use x='211.998' xlink:href='#g3-116' y='186.027'/>
<use x='215.056' xlink:href='#g3-101' y='186.027'/>
<use x='218.819' xlink:href='#g3-114' y='186.027'/>
<use x='221.711' xlink:href='#g3-41' y='186.027'/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 75 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 93 KiB

View file

@ -0,0 +1,756 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 2.4.2 -->
<svg height='193.064pt' version='1.1' viewBox='52.938 51.67 381.624 193.064' width='381.624pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<clipPath id='clip7'>
<path d='M82.148 228.594H434.164V60.828H82.148Z'/>
</clipPath>
<use id='g3-40' transform='scale(1.143)' xlink:href='#g0-40'/>
<use id='g3-41' transform='scale(1.143)' xlink:href='#g0-41'/>
<use id='g3-78' transform='scale(1.143)' xlink:href='#g0-78'/>
<use id='g3-97' transform='scale(1.143)' xlink:href='#g0-97'/>
<use id='g3-98' transform='scale(1.143)' xlink:href='#g0-98'/>
<use id='g3-99' transform='scale(1.143)' xlink:href='#g0-99'/>
<use id='g3-100' transform='scale(1.143)' xlink:href='#g0-100'/>
<use id='g3-101' transform='scale(1.143)' xlink:href='#g0-101'/>
<use id='g3-102' transform='scale(1.143)' xlink:href='#g0-102'/>
<use id='g3-105' transform='scale(1.143)' xlink:href='#g0-105'/>
<use id='g3-108' transform='scale(1.143)' xlink:href='#g0-108'/>
<use id='g3-109' transform='scale(1.143)' xlink:href='#g0-109'/>
<use id='g3-110' transform='scale(1.143)' xlink:href='#g0-110'/>
<use id='g3-111' transform='scale(1.143)' xlink:href='#g0-111'/>
<use id='g3-112' transform='scale(1.143)' xlink:href='#g0-112'/>
<use id='g3-114' transform='scale(1.143)' xlink:href='#g0-114'/>
<use id='g3-115' transform='scale(1.143)' xlink:href='#g0-115'/>
<use id='g3-116' transform='scale(1.143)' xlink:href='#g0-116'/>
<use id='g3-119' transform='scale(1.143)' xlink:href='#g0-119'/>
<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g1-82'/>
<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g1-97'/>
<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g1-101'/>
<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g1-105'/>
<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g1-108'/>
<path d='M1.462 -1.91C1.462 -2.851 2.197 -3.425 3.013 -3.434V-4.08C2.367 -4.071 1.775 -3.748 1.408 -3.219V-4.035H0.744V0H1.462V-1.91Z' id='g1-114'/>
<path d='M3.165 -3.847C2.609 -4.098 2.197 -4.133 1.829 -4.133C1.623 -4.133 0.305 -4.133 0.305 -2.95C0.305 -2.52 0.565 -2.251 0.664 -2.152C1.004 -1.856 1.237 -1.811 1.847 -1.695C2.134 -1.641 2.645 -1.542 2.645 -1.085C2.645 -0.502 1.919 -0.502 1.802 -0.502C1.273 -0.502 0.762 -0.681 0.377 -0.95L0.26 -0.296C0.798 -0.009 1.345 0.099 1.802 0.099C2.385 0.099 3.318 -0.09 3.318 -1.157C3.318 -1.47 3.192 -1.784 2.878 -2.053C2.573 -2.313 2.304 -2.367 1.748 -2.475C1.426 -2.537 0.977 -2.618 0.977 -3.04C0.977 -3.569 1.614 -3.569 1.748 -3.569C2.403 -3.569 2.789 -3.362 3.049 -3.219L3.165 -3.847Z' id='g1-115'/>
<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g1-116'/>
<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g1-118'/>
<use id='g2-46' transform='scale(0.714)' xlink:href='#g0-46'/>
<use id='g2-48' transform='scale(0.714)' xlink:href='#g0-48'/>
<use id='g2-49' transform='scale(0.714)' xlink:href='#g0-49'/>
<use id='g2-50' transform='scale(0.714)' xlink:href='#g0-50'/>
<use id='g2-51' transform='scale(0.714)' xlink:href='#g0-51'/>
<use id='g2-52' transform='scale(0.714)' xlink:href='#g0-52'/>
<use id='g2-53' transform='scale(0.714)' xlink:href='#g0-53'/>
<use id='g2-54' transform='scale(0.714)' xlink:href='#g0-54'/>
<use id='g2-55' transform='scale(0.714)' xlink:href='#g0-55'/>
<use id='g2-56' transform='scale(0.714)' xlink:href='#g0-56'/>
<use id='g2-57' transform='scale(0.714)' xlink:href='#g0-57'/>
<use id='g2-120' transform='scale(0.714)' xlink:href='#g0-120'/>
<path d='M2.127 -5.23C2.008 -5.23 1.995 -5.23 1.911 -5.154C1.032 -4.387 0.586 -3.145 0.586 -1.743C0.586 -0.425 0.983 0.844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 0.063C1.276 -0.481 1.193 -1.053 1.193 -1.743C1.193 -4.156 2.322 -5.112 2.462 -5.23H2.127Z' id='g0-40'/>
<path d='M0.746 1.743C0.865 1.743 0.879 1.743 0.962 1.667C1.841 0.9 2.287 -0.342 2.287 -1.743C2.287 -3.062 1.89 -4.331 0.969 -5.14C0.879 -5.23 0.865 -5.23 0.746 -5.23H0.411C0.432 -5.216 1.109 -4.638 1.43 -3.55C1.597 -3.006 1.681 -2.434 1.681 -1.743C1.681 0.669 0.551 1.625 0.411 1.743H0.746Z' id='g0-41'/>
<path d='M1.339 -0.628H0.711V0H1.339V-0.628Z' id='g0-46'/>
<path d='M3.403 -2.267C3.403 -2.601 3.403 -3.417 3.075 -3.989C2.72 -4.617 2.183 -4.721 1.848 -4.721C1.534 -4.721 0.99 -4.624 0.642 -4.024C0.307 -3.466 0.293 -2.706 0.293 -2.267C0.293 -1.75 0.321 -1.116 0.614 -0.586C0.921 -0.021 1.437 0.146 1.848 0.146C2.545 0.146 2.929 -0.258 3.138 -0.697C3.382 -1.193 3.403 -1.834 3.403 -2.267ZM1.848 -0.314C1.555 -0.314 1.22 -0.481 1.046 -0.983C0.907 -1.409 0.9 -1.848 0.9 -2.357C0.9 -2.999 0.9 -4.261 1.848 -4.261S2.797 -2.999 2.797 -2.357C2.797 -1.897 2.797 -1.374 2.629 -0.928C2.434 -0.425 2.078 -0.314 1.848 -0.314Z' id='g0-48'/>
<path d='M2.239 -4.721H2.085C1.632 -4.303 1.06 -4.275 0.642 -4.261V-3.822C0.914 -3.829 1.262 -3.843 1.611 -3.982V-0.439H0.683V0H3.166V-0.439H2.239V-4.721Z' id='g0-49'/>
<path d='M1.974 -0.537C1.89 -0.537 1.806 -0.53 1.723 -0.53H0.928L2.008 -1.485C2.134 -1.597 2.476 -1.855 2.608 -1.967C2.915 -2.246 3.327 -2.608 3.327 -3.215C3.327 -4.003 2.741 -4.721 1.743 -4.721C1.004 -4.721 0.544 -4.324 0.307 -3.612L0.635 -3.201C0.795 -3.787 1.039 -4.24 1.646 -4.24C2.232 -4.24 2.678 -3.829 2.678 -3.201C2.678 -2.622 2.336 -2.294 1.918 -1.897C1.778 -1.757 1.402 -1.444 1.255 -1.304C1.053 -1.123 0.572 -0.656 0.37 -0.481V0H3.327V-0.537H1.974Z' id='g0-50'/>
<path d='M0.697 -3.578C0.983 -4.135 1.485 -4.289 1.82 -4.289C2.232 -4.289 2.538 -4.052 2.538 -3.654C2.538 -3.285 2.287 -2.831 1.757 -2.741C1.723 -2.734 1.695 -2.734 1.234 -2.699V-2.239H1.778C2.441 -2.239 2.685 -1.716 2.685 -1.276C2.685 -0.732 2.35 -0.314 1.806 -0.314C1.311 -0.314 0.746 -0.551 0.398 -0.997L0.307 -0.544C0.711 -0.091 1.276 0.146 1.82 0.146C2.734 0.146 3.389 -0.537 3.389 -1.269C3.389 -1.841 2.929 -2.301 2.378 -2.462C2.908 -2.734 3.18 -3.201 3.18 -3.654C3.18 -4.247 2.573 -4.721 1.827 -4.721C1.213 -4.721 0.704 -4.4 0.411 -3.982L0.697 -3.578Z' id='g0-51'/>
<path d='M2.762 -1.165H3.487V-1.625H2.762V-4.575H2.071L0.209 -1.625V-1.165H2.162V0H2.762V-1.165ZM0.802 -1.625C1.011 -1.953 2.211 -3.815 2.211 -4.233V-1.625H0.802Z' id='g0-52'/>
<path d='M1.144 -4.094H3.075V-4.575H0.586V-1.967H1.095C1.262 -2.343 1.59 -2.511 1.904 -2.511C2.19 -2.511 2.622 -2.315 2.622 -1.43C2.622 -0.516 2.043 -0.314 1.688 -0.314C1.227 -0.314 0.781 -0.558 0.544 -0.955L0.279 -0.537C0.621 -0.112 1.137 0.146 1.688 0.146C2.608 0.146 3.327 -0.565 3.327 -1.416C3.327 -2.28 2.685 -2.971 1.918 -2.971C1.618 -2.971 1.353 -2.866 1.144 -2.692V-4.094Z' id='g0-53'/>
<path d='M3.062 -4.582C2.685 -4.721 2.42 -4.721 2.287 -4.721C1.227 -4.721 0.307 -3.724 0.307 -2.253C0.307 -0.363 1.158 0.146 1.862 0.146C2.427 0.146 2.72 -0.119 2.936 -0.342C3.382 -0.816 3.389 -1.311 3.389 -1.555C3.389 -2.469 2.894 -3.229 2.218 -3.229C1.534 -3.229 1.165 -2.873 0.962 -2.671C1.053 -3.626 1.541 -4.289 2.294 -4.289C2.434 -4.289 2.713 -4.275 3.062 -4.142V-4.582ZM0.969 -1.534C0.969 -1.576 0.969 -1.681 0.976 -1.716C0.976 -2.19 1.276 -2.769 1.897 -2.769C2.748 -2.769 2.748 -1.792 2.748 -1.555C2.748 -1.29 2.748 -0.997 2.559 -0.704C2.392 -0.453 2.183 -0.314 1.862 -0.314C1.123 -0.314 1.004 -1.227 0.969 -1.534Z' id='g0-54'/>
<path d='M1.723 -4.038C1.806 -4.038 1.89 -4.045 1.974 -4.045H2.852C1.792 -3.006 1.116 -1.548 1.116 0.07H1.771C1.771 -1.967 2.762 -3.431 3.389 -4.087V-4.575H0.307V-4.038H1.723Z' id='g0-55'/>
<path d='M2.385 -2.469C2.845 -2.615 3.285 -2.985 3.285 -3.501C3.285 -4.135 2.678 -4.721 1.848 -4.721S0.411 -4.135 0.411 -3.501C0.411 -2.978 0.865 -2.608 1.311 -2.469C0.697 -2.28 0.307 -1.806 0.307 -1.269C0.307 -0.523 0.969 0.146 1.848 0.146S3.389 -0.523 3.389 -1.269C3.389 -1.806 2.992 -2.28 2.385 -2.469ZM1.848 -2.699C1.353 -2.699 0.948 -2.985 0.948 -3.494C0.948 -3.94 1.262 -4.289 1.848 -4.289C2.427 -4.289 2.748 -3.94 2.748 -3.494C2.748 -2.999 2.357 -2.699 1.848 -2.699ZM1.848 -0.314C1.367 -0.314 0.941 -0.621 0.941 -1.276C0.941 -1.904 1.346 -2.239 1.848 -2.239S2.755 -1.897 2.755 -1.276C2.755 -0.621 2.322 -0.314 1.848 -0.314Z' id='g0-56'/>
<path d='M0.537 -0.174C0.879 0.077 1.193 0.146 1.52 0.146C2.497 0.146 3.389 -0.837 3.389 -2.336C3.389 -4.24 2.545 -4.721 1.876 -4.721C1.255 -4.721 0.969 -4.428 0.767 -4.226C0.321 -3.773 0.307 -3.292 0.307 -3.02C0.307 -2.12 0.795 -1.346 1.478 -1.346C2.267 -1.346 2.699 -1.869 2.734 -1.911C2.636 -0.802 2.092 -0.314 1.52 -0.314C1.158 -0.314 0.934 -0.446 0.774 -0.579L0.537 -0.174ZM2.713 -3.027C2.72 -2.985 2.72 -2.915 2.72 -2.873C2.72 -2.357 2.406 -1.806 1.799 -1.806C1.534 -1.806 1.325 -1.883 1.144 -2.169C0.962 -2.441 0.948 -2.706 0.948 -3.02C0.948 -3.292 0.948 -3.605 1.165 -3.912C1.311 -4.122 1.52 -4.289 1.869 -4.289C2.545 -4.289 2.692 -3.473 2.713 -3.027Z' id='g0-57'/>
<path d='M1.646 -4.84H0.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-0.551H3.933L1.646 -4.84Z' id='g0-78'/>
<path d='M2.971 -2.008C2.971 -2.72 2.427 -3.201 1.736 -3.201C1.297 -3.201 0.962 -3.11 0.572 -2.901L0.614 -2.392C0.844 -2.545 1.186 -2.755 1.736 -2.755C2.043 -2.755 2.364 -2.525 2.364 -2.001V-1.723C1.332 -1.688 0.314 -1.471 0.314 -0.823C0.314 -0.474 0.551 0.07 1.165 0.07C1.465 0.07 2.015 0.007 2.385 -0.265V0H2.971V-2.008ZM2.364 -0.99C2.364 -0.851 2.364 -0.669 2.12 -0.523C1.897 -0.398 1.625 -0.391 1.548 -0.391C1.165 -0.391 0.872 -0.565 0.872 -0.83C0.872 -1.276 2.05 -1.318 2.364 -1.332V-0.99Z' id='g0-97'/>
<path d='M1.179 -4.84H0.593V0H1.2V-0.328C1.353 -0.195 1.688 0.07 2.197 0.07C2.957 0.07 3.571 -0.642 3.571 -1.555C3.571 -2.399 3.089 -3.166 2.392 -3.166C1.953 -3.166 1.527 -3.027 1.179 -2.769V-4.84ZM1.2 -2.197C1.2 -2.308 1.2 -2.392 1.444 -2.552C1.548 -2.615 1.736 -2.706 1.974 -2.706C2.441 -2.706 2.964 -2.392 2.964 -1.555C2.964 -0.704 2.385 -0.391 1.897 -0.391C1.639 -0.391 1.395 -0.509 1.2 -0.823V-2.197Z' id='g0-98'/>
<path d='M3.034 -0.76C2.685 -0.537 2.308 -0.411 1.876 -0.411C1.234 -0.411 0.858 -0.928 0.858 -1.555C0.858 -2.092 1.137 -2.72 1.897 -2.72C2.371 -2.72 2.594 -2.622 2.95 -2.399L3.041 -2.901C2.622 -3.11 2.441 -3.201 1.897 -3.201C0.851 -3.201 0.251 -2.357 0.251 -1.548C0.251 -0.697 0.921 0.07 1.869 0.07C2.357 0.07 2.776 -0.077 3.075 -0.251L3.034 -0.76Z' id='g0-99'/>
<path d='M3.229 -4.84H2.643V-2.797C2.197 -3.124 1.743 -3.166 1.541 -3.166C0.809 -3.166 0.251 -2.434 0.251 -1.548S0.802 0.07 1.52 0.07C1.953 0.07 2.357 -0.126 2.622 -0.363V0H3.229V-4.84ZM2.622 -0.865C2.448 -0.579 2.183 -0.391 1.848 -0.391C1.36 -0.391 0.858 -0.732 0.858 -1.541C0.858 -2.413 1.451 -2.706 1.925 -2.706C2.204 -2.706 2.441 -2.587 2.622 -2.35V-0.865Z' id='g0-100'/>
<path d='M2.999 -0.76C2.608 -0.481 2.169 -0.391 1.869 -0.391C1.262 -0.391 0.802 -0.886 0.781 -1.527H3.068C3.068 -1.848 3.034 -2.315 2.762 -2.713C2.511 -3.068 2.092 -3.201 1.75 -3.201C0.9 -3.201 0.244 -2.455 0.244 -1.569C0.244 -0.676 0.941 0.07 1.862 0.07C2.267 0.07 2.685 -0.049 3.041 -0.265L2.999 -0.76ZM0.83 -1.946C0.99 -2.504 1.402 -2.741 1.75 -2.741C2.057 -2.741 2.511 -2.594 2.643 -1.946H0.83Z' id='g0-101'/>
<path d='M1.325 -2.657H2.12V-3.096H1.304V-3.898C1.304 -4.38 1.743 -4.449 1.974 -4.449C2.12 -4.449 2.308 -4.428 2.566 -4.331V-4.84C2.385 -4.882 2.169 -4.91 1.981 -4.91C1.262 -4.91 0.739 -4.394 0.739 -3.703V-3.096H0.202V-2.657H0.739V0H1.325V-2.657Z' id='g0-102'/>
<path d='M1.227 -4.784H0.523V-4.08H1.227V-4.784ZM1.172 -3.096H0.586V0H1.172V-3.096Z' id='g0-105'/>
<path d='M1.172 -4.84H0.586V0H1.172V-4.84Z' id='g0-108'/>
<path d='M5.3 -2.064C5.3 -2.608 5.14 -3.166 4.282 -3.166C3.696 -3.166 3.333 -2.824 3.166 -2.601C3.096 -2.79 2.922 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-1.695C3.243 -2.155 3.438 -2.706 3.975 -2.706C4.693 -2.706 4.693 -2.218 4.693 -2.015V0H5.3V-2.064Z' id='g0-109'/>
<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-110'/>
<path d='M3.487 -1.527C3.487 -2.448 2.755 -3.201 1.848 -3.201S0.209 -2.441 0.209 -1.527C0.209 -0.642 0.948 0.07 1.848 0.07C2.755 0.07 3.487 -0.642 3.487 -1.527ZM1.848 -0.411C1.297 -0.411 0.816 -0.816 0.816 -1.604S1.332 -2.741 1.848 -2.741C2.371 -2.741 2.88 -2.378 2.88 -1.604C2.88 -0.809 2.385 -0.411 1.848 -0.411Z' id='g0-111'/>
<path d='M1.2 -0.328C1.569 0.007 1.967 0.07 2.204 0.07C2.943 0.07 3.571 -0.635 3.571 -1.555C3.571 -2.392 3.11 -3.166 2.42 -3.166C2.106 -3.166 1.583 -3.075 1.179 -2.762V-3.096H0.593V1.353H1.2V-0.328ZM1.2 -2.315C1.36 -2.511 1.632 -2.685 1.967 -2.685C2.525 -2.685 2.964 -2.169 2.964 -1.555C2.964 -0.865 2.441 -0.391 1.897 -0.391C1.792 -0.391 1.618 -0.404 1.437 -0.551C1.227 -0.711 1.2 -0.816 1.2 -0.948V-2.315Z' id='g0-112'/>
<path d='M1.179 -1.485C1.179 -2.239 1.806 -2.643 2.42 -2.65V-3.166C1.834 -3.159 1.409 -2.873 1.13 -2.504V-3.145H0.593V0H1.179V-1.485Z' id='g0-114'/>
<path d='M2.545 -2.985C2.071 -3.18 1.723 -3.201 1.471 -3.201C1.297 -3.201 0.244 -3.201 0.244 -2.273C0.244 -1.946 0.425 -1.764 0.516 -1.681C0.76 -1.437 1.053 -1.381 1.423 -1.311C1.75 -1.248 2.127 -1.179 2.127 -0.844C2.127 -0.404 1.548 -0.404 1.451 -0.404C1.004 -0.404 0.586 -0.565 0.307 -0.76L0.209 -0.237C0.446 -0.119 0.872 0.07 1.451 0.07C1.764 0.07 2.071 0.021 2.329 -0.167C2.587 -0.363 2.671 -0.669 2.671 -0.907C2.671 -1.032 2.657 -1.304 2.364 -1.569C2.106 -1.799 1.855 -1.848 1.52 -1.911C1.109 -1.988 0.788 -2.05 0.788 -2.357C0.788 -2.755 1.297 -2.755 1.402 -2.755C1.799 -2.755 2.106 -2.671 2.455 -2.49L2.545 -2.985Z' id='g0-115'/>
<path d='M1.311 -2.657H2.343V-3.096H1.311V-3.982H0.774V-3.096H0.139V-2.657H0.753V-0.893C0.753 -0.425 0.872 0.07 1.374 0.07S2.26 -0.091 2.469 -0.188L2.35 -0.635C2.12 -0.467 1.876 -0.411 1.681 -0.411C1.388 -0.411 1.311 -0.697 1.311 -1.018V-2.657Z' id='g0-116'/>
<path d='M4.951 -3.096H4.407C4.345 -2.901 3.954 -1.723 3.738 -0.997C3.682 -0.795 3.612 -0.572 3.592 -0.411H3.585C3.543 -0.697 3.299 -1.451 3.285 -1.499L2.769 -3.096H2.239C2.036 -2.497 1.513 -0.934 1.458 -0.425H1.451C1.395 -0.921 0.879 -2.462 0.767 -2.797C0.711 -2.964 0.711 -2.978 0.676 -3.096H0.105L1.123 0H1.709C1.716 -0.028 1.904 -0.579 2.148 -1.353C2.253 -1.695 2.462 -2.364 2.497 -2.671L2.504 -2.678C2.518 -2.532 2.559 -2.378 2.608 -2.204S2.706 -1.841 2.755 -1.681L3.292 0H3.933L4.951 -3.096Z' id='g0-119'/>
<path d='M1.932 -1.597L3.285 -3.096H2.671L1.681 -1.953L0.669 -3.096H0.042L1.437 -1.597L0 0H0.621L1.681 -1.311L2.783 0H3.41L1.932 -1.597Z' id='g0-120'/>
</defs>
<g id='page7'>
<path d='M140.82 237.449V228.594M199.488 237.449V228.594M258.156 237.449V228.594M316.824 237.449V228.594M375.496 237.449V228.594M140.82 51.969V60.828M199.488 51.969V60.828M258.156 51.969V60.828M316.824 51.969V60.828M375.496 51.969V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
<path d='M111.484 232.844V228.594M170.152 232.844V228.594M228.824 232.844V228.594M287.492 232.844V228.594M346.16 232.844V228.594M404.828 232.844V228.594M111.484 56.574V60.828M170.152 56.574V60.828M228.824 56.574V60.828M287.492 56.574V60.828M346.16 56.574V60.828M404.828 56.574V60.828' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
<path d='M82.148 228.594H86.402M82.148 195.039H86.402M82.148 161.484H86.402M82.148 127.934H86.402M82.148 94.379H86.402M82.148 60.828H86.402M434.164 228.594H429.91M434.164 195.039H429.91M434.164 161.484H429.91M434.164 127.934H429.91M434.164 94.379H429.91M434.164 60.828H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
<path d='M82.148 228.594V60.828H434.164V228.594H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<g transform='matrix(1 0 0 1 -11.54 34.954)'>
<use x='114.487' xlink:href='#g3-99' y='208.035'/>
<use x='118.25' xlink:href='#g3-102' y='208.035'/>
<use x='120.838' xlink:href='#g3-114' y='208.035'/>
<use x='123.73' xlink:href='#g3-97' y='208.035'/>
<use x='127.798' xlink:href='#g3-99' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 45.565 34.954)'>
<use x='114.487' xlink:href='#g3-108' y='208.035'/>
<use x='116.507' xlink:href='#g3-101' y='208.035'/>
<use x='120.271' xlink:href='#g3-97' y='208.035'/>
<use x='124.339' xlink:href='#g3-110' y='208.035'/>
<use x='128.711' xlink:href='#g3-78' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 106.188 34.954)'>
<use x='114.487' xlink:href='#g3-114' y='208.035'/>
<use x='117.379' xlink:href='#g3-101' y='208.035'/>
<use x='121.142' xlink:href='#g3-100' y='208.035'/>
<use x='125.515' xlink:href='#g3-105' y='208.035'/>
<use x='127.535' xlink:href='#g3-115' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 159.716 34.954)'>
<use x='114.487' xlink:href='#g3-108' y='208.035'/>
<use x='116.507' xlink:href='#g3-97' y='208.035'/>
<use x='120.34' xlink:href='#g3-114' y='208.035'/>
<use x='123.232' xlink:href='#g3-115' y='208.035'/>
<use x='126.478' xlink:href='#g3-111' y='208.035'/>
<use x='130.712' xlink:href='#g3-110' y='208.035'/>
<use x='135.085' xlink:href='#g3-78' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 215.596 34.954)'>
<use x='114.487' xlink:href='#g3-109' y='208.035'/>
<use x='121.211' xlink:href='#g3-115' y='208.035'/>
<use x='124.458' xlink:href='#g3-116' y='208.035'/>
<use x='127.516' xlink:href='#g3-114' y='208.035'/>
<use x='130.408' xlink:href='#g3-101' y='208.035'/>
<use x='134.171' xlink:href='#g3-115' y='208.035'/>
<use x='137.418' xlink:href='#g3-115' y='208.035'/>
<use x='140.664' xlink:href='#g3-78' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 277.158 34.954)'>
<use x='114.487' xlink:href='#g3-114' y='208.035'/>
<use x='117.379' xlink:href='#g3-112' y='208.035'/>
<use x='121.751' xlink:href='#g3-116' y='208.035'/>
<use x='124.809' xlink:href='#g3-101' y='208.035'/>
<use x='128.573' xlink:href='#g3-115' y='208.035'/>
<use x='131.819' xlink:href='#g3-116' y='208.035'/>
<use x='134.877' xlink:href='#g3-78' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 -40.942 22.192)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-120' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -11.361)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-53' y='208.035'/>
<use x='121.25' xlink:href='#g2-120' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -44.915)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-120' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -78.468)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-53' y='208.035'/>
<use x='121.25' xlink:href='#g2-120' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -112.021)'>
<use x='114.487' xlink:href='#g2-50' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-120' y='208.035'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -145.574)'>
<use x='114.487' xlink:href='#g2-50' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-53' y='208.035'/>
<use x='121.25' xlink:href='#g2-120' y='208.035'/>
</g>
<path clip-path='url(#clip7)' d='M82.148 161.484H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M88.945 228.594H92.18V161.484H88.945ZM147.613 228.594H150.852V161.484H147.613ZM206.281 228.594H209.52V161.484H206.281ZM264.949 228.594H268.188V161.484H264.949ZM323.621 228.594H326.859V161.484H323.621ZM382.289 228.594H385.527V161.484H382.289Z' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M88.945 228.594H92.18V161.484H88.945ZM147.613 228.594H150.852V161.484H147.613ZM206.281 228.594H209.52V161.484H206.281ZM264.949 228.594H268.188V161.484H264.949ZM323.621 228.594H326.859V161.484H323.621ZM382.289 228.594H385.527V161.484H382.289Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M90.563 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M88.57 161.484H92.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M90.563 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M88.57 161.484H92.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M149.231 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M147.238 161.484H151.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M149.231 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M147.238 161.484H151.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M207.902 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M205.906 161.484H209.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M207.902 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M205.906 161.484H209.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M266.57 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M264.578 161.484H268.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M266.57 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M264.578 161.484H268.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M325.238 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M323.246 161.484H327.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M325.238 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M323.246 161.484H327.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M383.906 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M381.914 161.484H385.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M383.906 161.484V161.484' fill='#ffffff'/>
<path clip-path='url(#clip7)' d='M381.914 161.484H385.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M94.176 228.594H97.41V74.719H94.176ZM152.844 228.594H156.082V172.559H152.844ZM211.512 228.594H214.75V145.852H211.512ZM270.18 228.594H273.418V154.773H270.18ZM328.852 228.594H332.09V193.43H328.852ZM387.52 228.594H390.758V191.148H387.52Z' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M94.176 228.594H97.41V74.719H94.176ZM152.844 228.594H156.082V172.559H152.844ZM211.512 228.594H214.75V145.852H211.512ZM270.18 228.594H273.418V154.773H270.18ZM328.852 228.594H332.09V193.43H328.852ZM387.52 228.594H390.758V191.148H387.52Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M95.793 74.719V74.719' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M93.801 74.719H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M95.793 74.719V74.719' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M93.801 74.719H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M154.461 172.559V172.559' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M152.469 172.558H156.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M154.461 172.559V172.559' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M152.469 172.558H156.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M213.133 145.852V145.852' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M211.137 145.851H215.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M213.133 145.852V145.852' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M211.137 145.851H215.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M271.801 154.773V154.773' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M269.809 154.773H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M271.801 154.773V154.773' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M269.809 154.773H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M330.469 193.43V193.43' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M328.477 193.429H332.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M330.469 193.43V193.43' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M328.477 193.429H332.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M389.137 191.148V191.148' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M387.145 191.149H391.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M389.137 191.148V191.148' fill='#f0e0f0'/>
<path clip-path='url(#clip7)' d='M387.145 191.149H391.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M99.406 228.594H102.641V138.133H99.406ZM158.074 228.594H161.313V162.961H158.074ZM216.742 228.594H219.981V157.797H216.742ZM275.41 228.594H278.649V141.02H275.41ZM334.082 228.594H337.32V191.816H334.082ZM392.75 228.594H395.988V179.871H392.75Z' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M99.406 228.594H102.641V138.133H99.406ZM158.074 228.594H161.313V162.961H158.074ZM216.742 228.594H219.981V157.797H216.742ZM275.41 228.594H278.649V141.02H275.41ZM334.082 228.594H337.32V191.816H334.082ZM392.75 228.594H395.988V179.871H392.75Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M101.024 138.133V138.133' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M99.031 138.133H103.016' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M101.024 138.133V138.133' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M99.031 138.133H103.016' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M159.691 162.961V162.961' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M157.699 162.961H161.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M159.691 162.961V162.961' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M157.699 162.961H161.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M218.363 157.797V157.797' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M216.367 157.797H220.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M218.363 157.797V157.797' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M216.367 157.797H220.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M277.031 141.02V141.02' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M275.039 141.02H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M277.031 141.02V141.02' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M275.039 141.02H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M335.699 191.816V191.816' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M333.707 191.816H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M335.699 191.816V191.816' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M333.707 191.816H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M394.367 179.871V179.871' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M392.375 179.871H396.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M394.367 179.871V179.871' fill='#e1c2e1'/>
<path clip-path='url(#clip7)' d='M392.375 179.871H396.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M104.637 228.594H107.871V140.883H104.637ZM163.305 228.594H166.543V152.695H163.305ZM221.973 228.594H225.211V115.184H221.973ZM280.641 228.594H283.879V167.793H280.641ZM339.313 228.594H342.551V189.738H339.313ZM397.981 228.594H401.219V194.367H397.981Z' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M104.637 228.594H107.871V140.883H104.637ZM163.305 228.594H166.543V152.695H163.305ZM221.973 228.594H225.211V115.184H221.973ZM280.641 228.594H283.879V167.793H280.641ZM339.313 228.594H342.551V189.738H339.313ZM397.981 228.594H401.219V194.367H397.981Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M106.254 140.883V140.883' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M104.261 140.882H108.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M106.254 140.883V140.883' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M104.261 140.882H108.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M164.922 152.695V152.695' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M162.929 152.695H166.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M164.922 152.695V152.695' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M162.929 152.695H166.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M223.594 115.184V115.184' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M221.597 115.184H225.585' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M223.594 115.184V115.184' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M221.597 115.184H225.585' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M282.262 167.793V167.793' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M280.269 167.793H284.253' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M282.262 167.793V167.793' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M280.269 167.793H284.253' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M340.93 189.738V189.738' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M338.937 189.739H342.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M340.93 189.738V189.738' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M338.937 189.739H342.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M399.598 194.367V194.367' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M397.605 194.367H401.589' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M399.598 194.367V194.367' fill='#d1a3d1'/>
<path clip-path='url(#clip7)' d='M397.605 194.367H401.589' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M109.867 228.594H113.102V163.031H109.867ZM168.535 228.594H171.774V157.191H168.535ZM227.203 228.594H230.442V142.094H227.203ZM285.871 228.594H289.109V150.414H285.871ZM344.543 228.594H347.781V150.949H344.543ZM403.211 228.594H406.449V103.105H403.211Z' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M109.867 228.594H113.102V163.031H109.867ZM168.535 228.594H171.774V157.191H168.535ZM227.203 228.594H230.442V142.094H227.203ZM285.871 228.594H289.109V150.414H285.871ZM344.543 228.594H347.781V150.949H344.543ZM403.211 228.594H406.449V103.105H403.211Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M111.484 163.031V163.031' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M109.492 163.031H113.477' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M111.484 163.031V163.031' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M109.492 163.031H113.477' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M170.152 157.191V157.191' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M168.16 157.191H172.145' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M170.152 157.191V157.191' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M168.16 157.191H172.145' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M228.824 142.094V142.094' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M226.828 142.093H230.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M228.824 142.094V142.094' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M226.828 142.093H230.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M287.492 150.414V150.414' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M285.5 150.414H289.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M287.492 150.414V150.414' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M285.5 150.414H289.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M346.16 150.949V150.949' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M344.168 150.949H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M346.16 150.949V150.949' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M344.168 150.949H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M404.828 103.105V103.105' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M402.836 103.106H406.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M404.828 103.105V103.105' fill='#c285c2'/>
<path clip-path='url(#clip7)' d='M402.836 103.106H406.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M115.098 228.594H118.332V133.906H115.098ZM173.766 228.594H177.004V148.133H173.766ZM232.434 228.594H235.672V144.91H232.434ZM291.102 228.594H294.34V160.48H291.102ZM349.774 228.594H353.012V168.801H349.774ZM408.442 228.594H411.68V181.484H408.442Z' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M115.098 228.594H118.332V133.906H115.098ZM173.766 228.594H177.004V148.133H173.766ZM232.434 228.594H235.672V144.91H232.434ZM291.102 228.594H294.34V160.48H291.102ZM349.774 228.594H353.012V168.801H349.774ZM408.442 228.594H411.68V181.484H408.442Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M116.715 133.906V133.906' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M114.722 133.906H118.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M116.715 133.906V133.906' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M114.722 133.906H118.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M175.383 148.133V148.133' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M173.39 148.133H177.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M175.383 148.133V148.133' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M173.39 148.133H177.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M234.055 144.91V144.91' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M232.058 144.91H236.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M234.055 144.91V144.91' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M232.058 144.91H236.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M292.723 160.48V160.48' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M290.73 160.48H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M292.723 160.48V160.48' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M290.73 160.48H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M351.391 168.801V168.801' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M349.398 168.801H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M351.391 168.801V168.801' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M349.398 168.801H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M410.059 181.484V181.484' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M408.066 181.485H412.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M410.059 181.484V181.484' fill='#b366b3'/>
<path clip-path='url(#clip7)' d='M408.066 181.485H412.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M120.328 228.594H123.563V140.48H120.328ZM178.996 228.594H182.234V159.473H178.996ZM237.664 228.594H240.902V159.406H237.664ZM296.332 228.594H299.57V157.797H296.332ZM355.004 228.594H358.238V172.355H355.004ZM413.672 228.594H416.91V184.637H413.672Z' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M120.328 228.594H123.563V140.48H120.328ZM178.996 228.594H182.234V159.473H178.996ZM237.664 228.594H240.902V159.406H237.664ZM296.332 228.594H299.57V157.797H296.332ZM355.004 228.594H358.238V172.355H355.004ZM413.672 228.594H416.91V184.637H413.672Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M121.945 140.48V140.48' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M119.953 140.481H123.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M121.945 140.48V140.48' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M119.953 140.481H123.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M180.613 159.473V159.473' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M178.621 159.473H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M180.613 159.473V159.473' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M178.621 159.473H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M239.285 159.406V159.406' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M237.289 159.407H241.274' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M239.285 159.406V159.406' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M237.289 159.407H241.274' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M297.953 157.797V157.797' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M295.961 157.797H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M297.953 157.797V157.797' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M295.961 157.797H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M356.621 172.355V172.355' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M354.629 172.355H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M356.621 172.355V172.355' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M354.629 172.355H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M415.289 184.637V184.637' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M413.297 184.637H417.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M415.289 184.637V184.637' fill='#a447a4'/>
<path clip-path='url(#clip7)' d='M413.297 184.637H417.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M125.559 228.594H128.793V163.098H125.559ZM184.227 228.594H187.465V151.824H184.227ZM242.895 228.594H246.133V161.082H242.895ZM301.563 228.594H304.801V167.457H301.563ZM360.234 228.594H363.469V168.195H360.234ZM418.902 228.594H422.141V199.332H418.902Z' fill='#942994'/>
<path clip-path='url(#clip7)' d='M125.559 228.594H128.793V163.098H125.559ZM184.227 228.594H187.465V151.824H184.227ZM242.895 228.594H246.133V161.082H242.895ZM301.563 228.594H304.801V167.457H301.563ZM360.234 228.594H363.469V168.195H360.234ZM418.902 228.594H422.141V199.332H418.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M127.176 163.098V163.098' fill='#942994'/>
<path clip-path='url(#clip7)' d='M125.183 163.097H129.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M127.176 163.098V163.098' fill='#942994'/>
<path clip-path='url(#clip7)' d='M125.183 163.097H129.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M185.844 151.824V151.824' fill='#942994'/>
<path clip-path='url(#clip7)' d='M183.851 151.825H187.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M185.844 151.824V151.824' fill='#942994'/>
<path clip-path='url(#clip7)' d='M183.851 151.825H187.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M244.516 161.082V161.082' fill='#942994'/>
<path clip-path='url(#clip7)' d='M242.519 161.082H246.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M244.516 161.082V161.082' fill='#942994'/>
<path clip-path='url(#clip7)' d='M242.519 161.082H246.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M303.184 167.457V167.457' fill='#942994'/>
<path clip-path='url(#clip7)' d='M301.191 167.457H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M303.184 167.457V167.457' fill='#942994'/>
<path clip-path='url(#clip7)' d='M301.191 167.457H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M361.852 168.195V168.195' fill='#942994'/>
<path clip-path='url(#clip7)' d='M359.859 168.196H363.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M361.852 168.195V168.195' fill='#942994'/>
<path clip-path='url(#clip7)' d='M359.859 168.196H363.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M420.52 199.332V199.332' fill='#942994'/>
<path clip-path='url(#clip7)' d='M418.527 199.332H422.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M420.52 199.332V199.332' fill='#942994'/>
<path clip-path='url(#clip7)' d='M418.527 199.332H422.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M130.789 228.594H134.024V157.996H130.789ZM189.457 228.594H192.695V153.969H189.457ZM248.125 228.594H251.363V154.305H248.125ZM306.793 228.594H310.031V122.633H306.793ZM365.465 228.594H368.699V165.98H365.465ZM424.133 228.594H427.371V150.211H424.133Z' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M130.789 228.594H134.024V157.996H130.789ZM189.457 228.594H192.695V153.969H189.457ZM248.125 228.594H251.363V154.305H248.125ZM306.793 228.594H310.031V122.633H306.793ZM365.465 228.594H368.699V165.98H365.465ZM424.133 228.594H427.371V150.211H424.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M132.406 157.996V157.996' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M130.414 157.996H134.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M132.406 157.996V157.996' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M130.414 157.996H134.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M191.074 153.969V153.969' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M189.082 153.969H193.067' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M191.074 153.969V153.969' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M189.082 153.969H193.067' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M249.746 154.305V154.305' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M247.75 154.305H251.735' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M249.746 154.305V154.305' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M247.75 154.305H251.735' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M308.414 122.633V122.633' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M306.422 122.633H310.407' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M308.414 122.633V122.633' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M306.422 122.633H310.407' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M367.082 165.98V165.98' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M365.09 165.98H369.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M367.082 165.98V165.98' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M365.09 165.98H369.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M425.75 150.211V150.211' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M423.758 150.211H427.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip7)' d='M425.75 150.211V150.211' fill='#850a85'/>
<path clip-path='url(#clip7)' d='M423.758 150.211H427.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<g transform='matrix(0 -1 1 0 -115.838 269.769)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -57.169 269.769)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 1.5 269.769)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 60.169 269.769)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 118.838 269.769)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 177.507 269.769)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -110.608 183.001)'>
<use x='114.487' xlink:href='#g2-50' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-50' y='208.035'/>
<use x='121.25' xlink:href='#g2-57' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -51.938 280.841)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-56' y='208.035'/>
<use x='121.25' xlink:href='#g2-52' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 6.731 254.133)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-50' y='208.035'/>
<use x='121.25' xlink:href='#g2-51' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 65.4 263.058)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-49' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 124.069 301.711)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-53' y='208.035'/>
<use x='121.25' xlink:href='#g2-50' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 182.738 299.43)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-53' y='208.035'/>
<use x='121.25' xlink:href='#g2-54' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -105.377 246.416)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-51' y='208.035'/>
<use x='121.25' xlink:href='#g2-53' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -46.708 271.245)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-57' y='208.035'/>
<use x='121.25' xlink:href='#g2-56' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 11.961 266.078)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-53' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 70.63 249.302)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-51' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 129.299 300.101)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-53' y='208.035'/>
<use x='121.25' xlink:href='#g2-53' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 187.968 288.156)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-55' y='208.035'/>
<use x='121.25' xlink:href='#g2-51' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -100.147 249.167)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-51' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -41.478 260.978)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-49' y='208.035'/>
<use x='121.25' xlink:href='#g2-51' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 17.191 223.466)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-54' y='208.035'/>
<use x='121.25' xlink:href='#g2-57' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 75.86 276.077)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-57' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 134.529 298.021)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-53' y='208.035'/>
<use x='121.25' xlink:href='#g2-56' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 193.198 302.651)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-53' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -94.916 271.312)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-57' y='208.035'/>
<use x='121.25' xlink:href='#g2-56' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -36.247 265.474)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-54' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 22.422 250.375)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-50' y='208.035'/>
<use x='121.25' xlink:href='#g2-57' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 81.091 258.696)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-49' y='208.035'/>
<use x='121.25' xlink:href='#g2-54' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 139.76 259.233)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-49' y='208.035'/>
<use x='121.25' xlink:href='#g2-54' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 198.429 211.387)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-56' y='208.035'/>
<use x='121.25' xlink:href='#g2-55' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -89.686 242.188)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-52' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -31.017 256.415)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-50' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 27.652 253.194)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-50' y='208.035'/>
<use x='121.25' xlink:href='#g2-53' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 86.321 268.762)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-50' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 144.99 277.083)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-56' y='208.035'/>
<use x='121.25' xlink:href='#g2-57' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 203.659 289.767)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-55' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -84.455 248.765)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-51' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -25.786 267.756)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-51' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 32.883 267.689)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-51' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 91.552 266.078)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-53' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 150.221 280.64)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-56' y='208.035'/>
<use x='121.25' xlink:href='#g2-52' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 208.89 292.921)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-54' y='208.035'/>
<use x='121.25' xlink:href='#g2-54' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -79.225 271.379)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-57' y='208.035'/>
<use x='121.25' xlink:href='#g2-56' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -20.556 260.106)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-49' y='208.035'/>
<use x='121.25' xlink:href='#g2-52' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 38.113 269.366)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 96.782 275.741)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-57' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 155.451 276.48)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-57' y='208.035'/>
<use x='121.25' xlink:href='#g2-48' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 214.12 307.617)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-52' y='208.035'/>
<use x='121.25' xlink:href='#g2-52' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -73.994 266.279)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-48' y='208.035'/>
<use x='121.25' xlink:href='#g2-53' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -15.325 262.253)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-49' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 43.344 262.589)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-49' y='208.035'/>
<use x='121.25' xlink:href='#g2-49' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 102.013 230.914)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-53' y='208.035'/>
<use x='121.25' xlink:href='#g2-56' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 160.682 274.265)'>
<use x='114.487' xlink:href='#g2-48' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-57' y='208.035'/>
<use x='121.25' xlink:href='#g2-51' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 219.351 258.495)'>
<use x='114.487' xlink:href='#g2-49' y='208.035'/>
<use x='117.133' xlink:href='#g2-46' y='208.035'/>
<use x='118.603' xlink:href='#g2-49' y='208.035'/>
<use x='121.25' xlink:href='#g2-55' y='208.035'/>
</g>
<g transform='matrix(0 -1 1 0 -148.675 311.091)'>
<use x='114.487' xlink:href='#g1-82' y='208.035'/>
<use x='120.457' xlink:href='#g1-101' y='208.035'/>
<use x='124.553' xlink:href='#g1-108' y='208.035'/>
<use x='126.753' xlink:href='#g1-97' y='208.035'/>
<use x='131.181' xlink:href='#g1-116' y='208.035'/>
<use x='134.509' xlink:href='#g1-105' y='208.035'/>
<use x='136.709' xlink:href='#g1-118' y='208.035'/>
<use x='140.957' xlink:href='#g1-101' y='208.035'/>
<use x='148.124' xlink:href='#g1-114' y='208.035'/>
<use x='151.272' xlink:href='#g1-115' y='208.035'/>
<use x='154.805' xlink:href='#g1-115' y='208.035'/>
<use x='161.409' xlink:href='#g3-40' y='208.035'/>
<use x='164.702' xlink:href='#g3-108' y='208.035'/>
<use x='166.722' xlink:href='#g3-111' y='208.035'/>
<use x='170.721' xlink:href='#g3-119' y='208.035'/>
<use x='176.27' xlink:href='#g3-101' y='208.035'/>
<use x='180.034' xlink:href='#g3-114' y='208.035'/>
<use x='185.749' xlink:href='#g3-105' y='208.035'/>
<use x='187.769' xlink:href='#g3-115' y='208.035'/>
<use x='193.838' xlink:href='#g3-98' y='208.035'/>
<use x='198.446' xlink:href='#g3-101' y='208.035'/>
<use x='202.209' xlink:href='#g3-116' y='208.035'/>
<use x='205.267' xlink:href='#g3-116' y='208.035'/>
<use x='208.325' xlink:href='#g3-101' y='208.035'/>
<use x='212.089' xlink:href='#g3-114' y='208.035'/>
<use x='214.981' xlink:href='#g3-41' y='208.035'/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 63 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 81 KiB

View file

@ -0,0 +1,867 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- This file was generated by dvisvgm 2.4.2 -->
<svg height='165.084pt' version='1.1' viewBox='52.938 54.996 381.624 165.084' width='381.624pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<clipPath id='clip5'>
<path d='M82.148 203.937H434.164V78.691H82.148Z'/>
</clipPath>
<use id='g3-40' transform='scale(1.143)' xlink:href='#g0-40'/>
<use id='g3-41' transform='scale(1.143)' xlink:href='#g0-41'/>
<use id='g3-78' transform='scale(1.143)' xlink:href='#g0-78'/>
<use id='g3-97' transform='scale(1.143)' xlink:href='#g0-97'/>
<use id='g3-98' transform='scale(1.143)' xlink:href='#g0-98'/>
<use id='g3-99' transform='scale(1.143)' xlink:href='#g0-99'/>
<use id='g3-100' transform='scale(1.143)' xlink:href='#g0-100'/>
<use id='g3-101' transform='scale(1.143)' xlink:href='#g0-101'/>
<use id='g3-102' transform='scale(1.143)' xlink:href='#g0-102'/>
<use id='g3-105' transform='scale(1.143)' xlink:href='#g0-105'/>
<use id='g3-108' transform='scale(1.143)' xlink:href='#g0-108'/>
<use id='g3-109' transform='scale(1.143)' xlink:href='#g0-109'/>
<use id='g3-110' transform='scale(1.143)' xlink:href='#g0-110'/>
<use id='g3-111' transform='scale(1.143)' xlink:href='#g0-111'/>
<use id='g3-112' transform='scale(1.143)' xlink:href='#g0-112'/>
<use id='g3-114' transform='scale(1.143)' xlink:href='#g0-114'/>
<use id='g3-115' transform='scale(1.143)' xlink:href='#g0-115'/>
<use id='g3-116' transform='scale(1.143)' xlink:href='#g0-116'/>
<use id='g3-119' transform='scale(1.143)' xlink:href='#g0-119'/>
<path d='M3.891 -2.914C4.806 -3.165 5.452 -3.811 5.452 -4.546C5.452 -5.469 4.411 -6.223 3.129 -6.223H0.87V0H1.704V-2.824H3.138L4.842 0H5.703L3.891 -2.914ZM1.704 -3.407V-5.694H3.022C4.062 -5.694 4.671 -5.192 4.671 -4.546C4.671 -3.963 4.125 -3.407 3.022 -3.407H1.704Z' id='g1-82'/>
<path d='M3.694 -2.591C3.694 -3.479 3.04 -4.133 2.152 -4.133C1.569 -4.133 1.139 -3.981 0.708 -3.739L0.762 -3.102C1.21 -3.434 1.65 -3.569 2.143 -3.569C2.645 -3.569 2.95 -3.165 2.95 -2.582V-2.206C1.408 -2.17 0.395 -1.766 0.395 -1.04C0.395 -0.619 0.672 0.099 1.453 0.099C1.632 0.099 2.412 0.081 2.977 -0.341V0H3.694V-2.591ZM2.95 -1.255C2.95 -1.067 2.95 -0.843 2.627 -0.655C2.403 -0.52 2.107 -0.484 1.928 -0.484C1.47 -0.484 1.085 -0.699 1.085 -1.058C1.085 -1.695 2.833 -1.722 2.95 -1.722V-1.255Z' id='g1-97'/>
<path d='M3.829 -1.964C3.829 -2.242 3.82 -2.923 3.47 -3.461C3.093 -4.026 2.52 -4.133 2.179 -4.133C1.139 -4.133 0.314 -3.174 0.314 -2.026C0.314 -0.843 1.193 0.099 2.313 0.099C2.744 0.099 3.264 -0.009 3.784 -0.341L3.73 -0.959C3.165 -0.556 2.636 -0.484 2.322 -0.484C1.578 -0.484 1.004 -1.139 0.977 -1.964H3.829ZM1.031 -2.493C1.175 -3.067 1.614 -3.551 2.179 -3.551C2.511 -3.551 3.12 -3.398 3.291 -2.493H1.031Z' id='g1-101'/>
<path d='M1.524 -6.133H0.664V-5.272H1.524V-6.133ZM1.453 -3.981H0.735V0H1.453V-3.981Z' id='g1-105'/>
<path d='M1.453 -6.223H0.735V0H1.453V-6.223Z' id='g1-108'/>
<path d='M6.581 -2.663C6.581 -3.327 6.402 -4.08 5.317 -4.08C4.564 -4.08 4.142 -3.622 3.927 -3.344C3.865 -3.524 3.676 -4.08 2.762 -4.08C2.053 -4.08 1.623 -3.667 1.417 -3.398V-4.035H0.726V0H1.47V-2.188C1.47 -2.78 1.704 -3.497 2.385 -3.497C3.282 -3.497 3.282 -2.86 3.282 -2.6V0H4.026V-2.188C4.026 -2.78 4.259 -3.497 4.94 -3.497C5.837 -3.497 5.837 -2.86 5.837 -2.6V0H6.581V-2.663Z' id='g1-109'/>
<path d='M1.623 -3.425H2.914V-3.981H1.623V-5.12H0.959V-3.981H0.17V-3.425H0.933V-1.13C0.933 -0.601 1.049 0.099 1.704 0.099C2.098 0.099 2.564 0.018 3.067 -0.233L2.914 -0.798C2.681 -0.619 2.367 -0.511 2.089 -0.511C1.739 -0.511 1.623 -0.825 1.623 -1.291V-3.425Z' id='g1-116'/>
<path d='M4.116 -3.981H3.407L2.699 -2.161C2.52 -1.695 2.188 -0.825 2.143 -0.493H2.125C2.107 -0.646 2.08 -0.816 1.587 -2.107C1.318 -2.833 0.879 -3.927 0.861 -3.981H0.126L1.704 0H2.537L4.116 -3.981Z' id='g1-118'/>
<use id='g2-46' transform='scale(0.714)' xlink:href='#g0-46'/>
<use id='g2-48' transform='scale(0.714)' xlink:href='#g0-48'/>
<use id='g2-49' transform='scale(0.714)' xlink:href='#g0-49'/>
<use id='g2-50' transform='scale(0.714)' xlink:href='#g0-50'/>
<use id='g2-51' transform='scale(0.714)' xlink:href='#g0-51'/>
<use id='g2-52' transform='scale(0.714)' xlink:href='#g0-52'/>
<use id='g2-53' transform='scale(0.714)' xlink:href='#g0-53'/>
<use id='g2-54' transform='scale(0.714)' xlink:href='#g0-54'/>
<use id='g2-55' transform='scale(0.714)' xlink:href='#g0-55'/>
<use id='g2-56' transform='scale(0.714)' xlink:href='#g0-56'/>
<use id='g2-57' transform='scale(0.714)' xlink:href='#g0-57'/>
<use id='g2-120' transform='scale(0.714)' xlink:href='#g0-120'/>
<path d='M1.445 -1.245C1.445 -1.41 1.305 -1.549 1.141 -1.549S0.837 -1.41 0.837 -1.245S0.976 -0.941 1.141 -0.941S1.445 -1.081 1.445 -1.245Z' id='g4-1'/>
<path d='M2.127 -5.23C2.008 -5.23 1.995 -5.23 1.911 -5.154C1.032 -4.387 0.586 -3.145 0.586 -1.743C0.586 -0.425 0.983 0.844 1.904 1.653C1.995 1.743 2.008 1.743 2.127 1.743H2.462C2.441 1.73 1.764 1.151 1.444 0.063C1.276 -0.481 1.193 -1.053 1.193 -1.743C1.193 -4.156 2.322 -5.112 2.462 -5.23H2.127Z' id='g0-40'/>
<path d='M0.746 1.743C0.865 1.743 0.879 1.743 0.962 1.667C1.841 0.9 2.287 -0.342 2.287 -1.743C2.287 -3.062 1.89 -4.331 0.969 -5.14C0.879 -5.23 0.865 -5.23 0.746 -5.23H0.411C0.432 -5.216 1.109 -4.638 1.43 -3.55C1.597 -3.006 1.681 -2.434 1.681 -1.743C1.681 0.669 0.551 1.625 0.411 1.743H0.746Z' id='g0-41'/>
<path d='M1.339 -0.628H0.711V0H1.339V-0.628Z' id='g0-46'/>
<path d='M3.403 -2.267C3.403 -2.601 3.403 -3.417 3.075 -3.989C2.72 -4.617 2.183 -4.721 1.848 -4.721C1.534 -4.721 0.99 -4.624 0.642 -4.024C0.307 -3.466 0.293 -2.706 0.293 -2.267C0.293 -1.75 0.321 -1.116 0.614 -0.586C0.921 -0.021 1.437 0.146 1.848 0.146C2.545 0.146 2.929 -0.258 3.138 -0.697C3.382 -1.193 3.403 -1.834 3.403 -2.267ZM1.848 -0.314C1.555 -0.314 1.22 -0.481 1.046 -0.983C0.907 -1.409 0.9 -1.848 0.9 -2.357C0.9 -2.999 0.9 -4.261 1.848 -4.261S2.797 -2.999 2.797 -2.357C2.797 -1.897 2.797 -1.374 2.629 -0.928C2.434 -0.425 2.078 -0.314 1.848 -0.314Z' id='g0-48'/>
<path d='M2.239 -4.721H2.085C1.632 -4.303 1.06 -4.275 0.642 -4.261V-3.822C0.914 -3.829 1.262 -3.843 1.611 -3.982V-0.439H0.683V0H3.166V-0.439H2.239V-4.721Z' id='g0-49'/>
<path d='M1.974 -0.537C1.89 -0.537 1.806 -0.53 1.723 -0.53H0.928L2.008 -1.485C2.134 -1.597 2.476 -1.855 2.608 -1.967C2.915 -2.246 3.327 -2.608 3.327 -3.215C3.327 -4.003 2.741 -4.721 1.743 -4.721C1.004 -4.721 0.544 -4.324 0.307 -3.612L0.635 -3.201C0.795 -3.787 1.039 -4.24 1.646 -4.24C2.232 -4.24 2.678 -3.829 2.678 -3.201C2.678 -2.622 2.336 -2.294 1.918 -1.897C1.778 -1.757 1.402 -1.444 1.255 -1.304C1.053 -1.123 0.572 -0.656 0.37 -0.481V0H3.327V-0.537H1.974Z' id='g0-50'/>
<path d='M0.697 -3.578C0.983 -4.135 1.485 -4.289 1.82 -4.289C2.232 -4.289 2.538 -4.052 2.538 -3.654C2.538 -3.285 2.287 -2.831 1.757 -2.741C1.723 -2.734 1.695 -2.734 1.234 -2.699V-2.239H1.778C2.441 -2.239 2.685 -1.716 2.685 -1.276C2.685 -0.732 2.35 -0.314 1.806 -0.314C1.311 -0.314 0.746 -0.551 0.398 -0.997L0.307 -0.544C0.711 -0.091 1.276 0.146 1.82 0.146C2.734 0.146 3.389 -0.537 3.389 -1.269C3.389 -1.841 2.929 -2.301 2.378 -2.462C2.908 -2.734 3.18 -3.201 3.18 -3.654C3.18 -4.247 2.573 -4.721 1.827 -4.721C1.213 -4.721 0.704 -4.4 0.411 -3.982L0.697 -3.578Z' id='g0-51'/>
<path d='M2.762 -1.165H3.487V-1.625H2.762V-4.575H2.071L0.209 -1.625V-1.165H2.162V0H2.762V-1.165ZM0.802 -1.625C1.011 -1.953 2.211 -3.815 2.211 -4.233V-1.625H0.802Z' id='g0-52'/>
<path d='M1.144 -4.094H3.075V-4.575H0.586V-1.967H1.095C1.262 -2.343 1.59 -2.511 1.904 -2.511C2.19 -2.511 2.622 -2.315 2.622 -1.43C2.622 -0.516 2.043 -0.314 1.688 -0.314C1.227 -0.314 0.781 -0.558 0.544 -0.955L0.279 -0.537C0.621 -0.112 1.137 0.146 1.688 0.146C2.608 0.146 3.327 -0.565 3.327 -1.416C3.327 -2.28 2.685 -2.971 1.918 -2.971C1.618 -2.971 1.353 -2.866 1.144 -2.692V-4.094Z' id='g0-53'/>
<path d='M3.062 -4.582C2.685 -4.721 2.42 -4.721 2.287 -4.721C1.227 -4.721 0.307 -3.724 0.307 -2.253C0.307 -0.363 1.158 0.146 1.862 0.146C2.427 0.146 2.72 -0.119 2.936 -0.342C3.382 -0.816 3.389 -1.311 3.389 -1.555C3.389 -2.469 2.894 -3.229 2.218 -3.229C1.534 -3.229 1.165 -2.873 0.962 -2.671C1.053 -3.626 1.541 -4.289 2.294 -4.289C2.434 -4.289 2.713 -4.275 3.062 -4.142V-4.582ZM0.969 -1.534C0.969 -1.576 0.969 -1.681 0.976 -1.716C0.976 -2.19 1.276 -2.769 1.897 -2.769C2.748 -2.769 2.748 -1.792 2.748 -1.555C2.748 -1.29 2.748 -0.997 2.559 -0.704C2.392 -0.453 2.183 -0.314 1.862 -0.314C1.123 -0.314 1.004 -1.227 0.969 -1.534Z' id='g0-54'/>
<path d='M1.723 -4.038C1.806 -4.038 1.89 -4.045 1.974 -4.045H2.852C1.792 -3.006 1.116 -1.548 1.116 0.07H1.771C1.771 -1.967 2.762 -3.431 3.389 -4.087V-4.575H0.307V-4.038H1.723Z' id='g0-55'/>
<path d='M2.385 -2.469C2.845 -2.615 3.285 -2.985 3.285 -3.501C3.285 -4.135 2.678 -4.721 1.848 -4.721S0.411 -4.135 0.411 -3.501C0.411 -2.978 0.865 -2.608 1.311 -2.469C0.697 -2.28 0.307 -1.806 0.307 -1.269C0.307 -0.523 0.969 0.146 1.848 0.146S3.389 -0.523 3.389 -1.269C3.389 -1.806 2.992 -2.28 2.385 -2.469ZM1.848 -2.699C1.353 -2.699 0.948 -2.985 0.948 -3.494C0.948 -3.94 1.262 -4.289 1.848 -4.289C2.427 -4.289 2.748 -3.94 2.748 -3.494C2.748 -2.999 2.357 -2.699 1.848 -2.699ZM1.848 -0.314C1.367 -0.314 0.941 -0.621 0.941 -1.276C0.941 -1.904 1.346 -2.239 1.848 -2.239S2.755 -1.897 2.755 -1.276C2.755 -0.621 2.322 -0.314 1.848 -0.314Z' id='g0-56'/>
<path d='M0.537 -0.174C0.879 0.077 1.193 0.146 1.52 0.146C2.497 0.146 3.389 -0.837 3.389 -2.336C3.389 -4.24 2.545 -4.721 1.876 -4.721C1.255 -4.721 0.969 -4.428 0.767 -4.226C0.321 -3.773 0.307 -3.292 0.307 -3.02C0.307 -2.12 0.795 -1.346 1.478 -1.346C2.267 -1.346 2.699 -1.869 2.734 -1.911C2.636 -0.802 2.092 -0.314 1.52 -0.314C1.158 -0.314 0.934 -0.446 0.774 -0.579L0.537 -0.174ZM2.713 -3.027C2.72 -2.985 2.72 -2.915 2.72 -2.873C2.72 -2.357 2.406 -1.806 1.799 -1.806C1.534 -1.806 1.325 -1.883 1.144 -2.169C0.962 -2.441 0.948 -2.706 0.948 -3.02C0.948 -3.292 0.948 -3.605 1.165 -3.912C1.311 -4.122 1.52 -4.289 1.869 -4.289C2.545 -4.289 2.692 -3.473 2.713 -3.027Z' id='g0-57'/>
<path d='M1.646 -4.84H0.697V0H1.283V-4.289H1.29L3.578 0H4.526V-4.84H3.94V-0.551H3.933L1.646 -4.84Z' id='g0-78'/>
<path d='M2.971 -2.008C2.971 -2.72 2.427 -3.201 1.736 -3.201C1.297 -3.201 0.962 -3.11 0.572 -2.901L0.614 -2.392C0.844 -2.545 1.186 -2.755 1.736 -2.755C2.043 -2.755 2.364 -2.525 2.364 -2.001V-1.723C1.332 -1.688 0.314 -1.471 0.314 -0.823C0.314 -0.474 0.551 0.07 1.165 0.07C1.465 0.07 2.015 0.007 2.385 -0.265V0H2.971V-2.008ZM2.364 -0.99C2.364 -0.851 2.364 -0.669 2.12 -0.523C1.897 -0.398 1.625 -0.391 1.548 -0.391C1.165 -0.391 0.872 -0.565 0.872 -0.83C0.872 -1.276 2.05 -1.318 2.364 -1.332V-0.99Z' id='g0-97'/>
<path d='M1.179 -4.84H0.593V0H1.2V-0.328C1.353 -0.195 1.688 0.07 2.197 0.07C2.957 0.07 3.571 -0.642 3.571 -1.555C3.571 -2.399 3.089 -3.166 2.392 -3.166C1.953 -3.166 1.527 -3.027 1.179 -2.769V-4.84ZM1.2 -2.197C1.2 -2.308 1.2 -2.392 1.444 -2.552C1.548 -2.615 1.736 -2.706 1.974 -2.706C2.441 -2.706 2.964 -2.392 2.964 -1.555C2.964 -0.704 2.385 -0.391 1.897 -0.391C1.639 -0.391 1.395 -0.509 1.2 -0.823V-2.197Z' id='g0-98'/>
<path d='M3.034 -0.76C2.685 -0.537 2.308 -0.411 1.876 -0.411C1.234 -0.411 0.858 -0.928 0.858 -1.555C0.858 -2.092 1.137 -2.72 1.897 -2.72C2.371 -2.72 2.594 -2.622 2.95 -2.399L3.041 -2.901C2.622 -3.11 2.441 -3.201 1.897 -3.201C0.851 -3.201 0.251 -2.357 0.251 -1.548C0.251 -0.697 0.921 0.07 1.869 0.07C2.357 0.07 2.776 -0.077 3.075 -0.251L3.034 -0.76Z' id='g0-99'/>
<path d='M3.229 -4.84H2.643V-2.797C2.197 -3.124 1.743 -3.166 1.541 -3.166C0.809 -3.166 0.251 -2.434 0.251 -1.548S0.802 0.07 1.52 0.07C1.953 0.07 2.357 -0.126 2.622 -0.363V0H3.229V-4.84ZM2.622 -0.865C2.448 -0.579 2.183 -0.391 1.848 -0.391C1.36 -0.391 0.858 -0.732 0.858 -1.541C0.858 -2.413 1.451 -2.706 1.925 -2.706C2.204 -2.706 2.441 -2.587 2.622 -2.35V-0.865Z' id='g0-100'/>
<path d='M2.999 -0.76C2.608 -0.481 2.169 -0.391 1.869 -0.391C1.262 -0.391 0.802 -0.886 0.781 -1.527H3.068C3.068 -1.848 3.034 -2.315 2.762 -2.713C2.511 -3.068 2.092 -3.201 1.75 -3.201C0.9 -3.201 0.244 -2.455 0.244 -1.569C0.244 -0.676 0.941 0.07 1.862 0.07C2.267 0.07 2.685 -0.049 3.041 -0.265L2.999 -0.76ZM0.83 -1.946C0.99 -2.504 1.402 -2.741 1.75 -2.741C2.057 -2.741 2.511 -2.594 2.643 -1.946H0.83Z' id='g0-101'/>
<path d='M1.325 -2.657H2.12V-3.096H1.304V-3.898C1.304 -4.38 1.743 -4.449 1.974 -4.449C2.12 -4.449 2.308 -4.428 2.566 -4.331V-4.84C2.385 -4.882 2.169 -4.91 1.981 -4.91C1.262 -4.91 0.739 -4.394 0.739 -3.703V-3.096H0.202V-2.657H0.739V0H1.325V-2.657Z' id='g0-102'/>
<path d='M1.227 -4.784H0.523V-4.08H1.227V-4.784ZM1.172 -3.096H0.586V0H1.172V-3.096Z' id='g0-105'/>
<path d='M1.172 -4.84H0.586V0H1.172V-4.84Z' id='g0-108'/>
<path d='M5.3 -2.064C5.3 -2.608 5.14 -3.166 4.282 -3.166C3.696 -3.166 3.333 -2.824 3.166 -2.601C3.096 -2.79 2.922 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-1.695C3.243 -2.155 3.438 -2.706 3.975 -2.706C4.693 -2.706 4.693 -2.218 4.693 -2.015V0H5.3V-2.064Z' id='g0-109'/>
<path d='M3.243 -2.064C3.243 -2.608 3.082 -3.166 2.225 -3.166C1.827 -3.166 1.444 -3.006 1.137 -2.636V-3.145H0.579V0H1.186V-1.695C1.186 -2.155 1.381 -2.706 1.918 -2.706C2.636 -2.706 2.636 -2.218 2.636 -2.015V0H3.243V-2.064Z' id='g0-110'/>
<path d='M3.487 -1.527C3.487 -2.448 2.755 -3.201 1.848 -3.201S0.209 -2.441 0.209 -1.527C0.209 -0.642 0.948 0.07 1.848 0.07C2.755 0.07 3.487 -0.642 3.487 -1.527ZM1.848 -0.411C1.297 -0.411 0.816 -0.816 0.816 -1.604S1.332 -2.741 1.848 -2.741C2.371 -2.741 2.88 -2.378 2.88 -1.604C2.88 -0.809 2.385 -0.411 1.848 -0.411Z' id='g0-111'/>
<path d='M1.2 -0.328C1.569 0.007 1.967 0.07 2.204 0.07C2.943 0.07 3.571 -0.635 3.571 -1.555C3.571 -2.392 3.11 -3.166 2.42 -3.166C2.106 -3.166 1.583 -3.075 1.179 -2.762V-3.096H0.593V1.353H1.2V-0.328ZM1.2 -2.315C1.36 -2.511 1.632 -2.685 1.967 -2.685C2.525 -2.685 2.964 -2.169 2.964 -1.555C2.964 -0.865 2.441 -0.391 1.897 -0.391C1.792 -0.391 1.618 -0.404 1.437 -0.551C1.227 -0.711 1.2 -0.816 1.2 -0.948V-2.315Z' id='g0-112'/>
<path d='M1.179 -1.485C1.179 -2.239 1.806 -2.643 2.42 -2.65V-3.166C1.834 -3.159 1.409 -2.873 1.13 -2.504V-3.145H0.593V0H1.179V-1.485Z' id='g0-114'/>
<path d='M2.545 -2.985C2.071 -3.18 1.723 -3.201 1.471 -3.201C1.297 -3.201 0.244 -3.201 0.244 -2.273C0.244 -1.946 0.425 -1.764 0.516 -1.681C0.76 -1.437 1.053 -1.381 1.423 -1.311C1.75 -1.248 2.127 -1.179 2.127 -0.844C2.127 -0.404 1.548 -0.404 1.451 -0.404C1.004 -0.404 0.586 -0.565 0.307 -0.76L0.209 -0.237C0.446 -0.119 0.872 0.07 1.451 0.07C1.764 0.07 2.071 0.021 2.329 -0.167C2.587 -0.363 2.671 -0.669 2.671 -0.907C2.671 -1.032 2.657 -1.304 2.364 -1.569C2.106 -1.799 1.855 -1.848 1.52 -1.911C1.109 -1.988 0.788 -2.05 0.788 -2.357C0.788 -2.755 1.297 -2.755 1.402 -2.755C1.799 -2.755 2.106 -2.671 2.455 -2.49L2.545 -2.985Z' id='g0-115'/>
<path d='M1.311 -2.657H2.343V-3.096H1.311V-3.982H0.774V-3.096H0.139V-2.657H0.753V-0.893C0.753 -0.425 0.872 0.07 1.374 0.07S2.26 -0.091 2.469 -0.188L2.35 -0.635C2.12 -0.467 1.876 -0.411 1.681 -0.411C1.388 -0.411 1.311 -0.697 1.311 -1.018V-2.657Z' id='g0-116'/>
<path d='M4.951 -3.096H4.407C4.345 -2.901 3.954 -1.723 3.738 -0.997C3.682 -0.795 3.612 -0.572 3.592 -0.411H3.585C3.543 -0.697 3.299 -1.451 3.285 -1.499L2.769 -3.096H2.239C2.036 -2.497 1.513 -0.934 1.458 -0.425H1.451C1.395 -0.921 0.879 -2.462 0.767 -2.797C0.711 -2.964 0.711 -2.978 0.676 -3.096H0.105L1.123 0H1.709C1.716 -0.028 1.904 -0.579 2.148 -1.353C2.253 -1.695 2.462 -2.364 2.497 -2.671L2.504 -2.678C2.518 -2.532 2.559 -2.378 2.608 -2.204S2.706 -1.841 2.755 -1.681L3.292 0H3.933L4.951 -3.096Z' id='g0-119'/>
<path d='M1.932 -1.597L3.285 -3.096H2.671L1.681 -1.953L0.669 -3.096H0.042L1.437 -1.597L0 0H0.621L1.681 -1.311L2.783 0H3.41L1.932 -1.597Z' id='g0-120'/>
</defs>
<g id='page5'>
<path d='M140.82 212.793V203.937M199.488 212.793V203.937M258.156 212.793V203.937M316.824 212.793V203.937M375.496 212.793V203.937M140.82 69.836V78.691M199.488 69.836V78.691M258.156 69.836V78.691M316.824 69.836V78.691M375.496 69.836V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
<path d='M111.484 208.191V203.937M170.152 208.191V203.937M228.824 208.191V203.937M287.492 208.191V203.937M346.16 208.191V203.937M404.828 208.191V203.937M111.484 74.441V78.691M170.152 74.441V78.691M228.824 74.441V78.691M287.492 74.441V78.691M346.16 74.441V78.691M404.828 74.441V78.691' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
<path d='M82.148 203.937H86.402M82.148 172.625H86.402M82.148 141.316H86.402M82.148 110.004H86.402M82.148 78.691H86.402M434.164 203.937H429.91M434.164 172.625H429.91M434.164 141.316H429.91M434.164 110.004H429.91M434.164 78.691H429.91' fill='none' stroke='#808080' stroke-miterlimit='10' stroke-width='0.199'/>
<path d='M82.148 203.937V78.691H434.164V203.937H82.148Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<g transform='matrix(1 0 0 1 -11.54 34.954)'>
<use x='114.487' xlink:href='#g3-99' y='183.381'/>
<use x='118.25' xlink:href='#g3-102' y='183.381'/>
<use x='120.838' xlink:href='#g3-114' y='183.381'/>
<use x='123.73' xlink:href='#g3-97' y='183.381'/>
<use x='127.798' xlink:href='#g3-99' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 45.565 34.954)'>
<use x='114.487' xlink:href='#g3-108' y='183.381'/>
<use x='116.507' xlink:href='#g3-101' y='183.381'/>
<use x='120.271' xlink:href='#g3-97' y='183.381'/>
<use x='124.339' xlink:href='#g3-110' y='183.381'/>
<use x='128.711' xlink:href='#g3-78' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 106.188 34.954)'>
<use x='114.487' xlink:href='#g3-114' y='183.381'/>
<use x='117.379' xlink:href='#g3-101' y='183.381'/>
<use x='121.142' xlink:href='#g3-100' y='183.381'/>
<use x='125.515' xlink:href='#g3-105' y='183.381'/>
<use x='127.535' xlink:href='#g3-115' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 159.716 34.954)'>
<use x='114.487' xlink:href='#g3-108' y='183.381'/>
<use x='116.507' xlink:href='#g3-97' y='183.381'/>
<use x='120.34' xlink:href='#g3-114' y='183.381'/>
<use x='123.232' xlink:href='#g3-115' y='183.381'/>
<use x='126.478' xlink:href='#g3-111' y='183.381'/>
<use x='130.712' xlink:href='#g3-110' y='183.381'/>
<use x='135.085' xlink:href='#g3-78' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 215.596 34.954)'>
<use x='114.487' xlink:href='#g3-109' y='183.381'/>
<use x='121.211' xlink:href='#g3-115' y='183.381'/>
<use x='124.458' xlink:href='#g3-116' y='183.381'/>
<use x='127.516' xlink:href='#g3-114' y='183.381'/>
<use x='130.408' xlink:href='#g3-101' y='183.381'/>
<use x='134.171' xlink:href='#g3-115' y='183.381'/>
<use x='137.418' xlink:href='#g3-115' y='183.381'/>
<use x='140.664' xlink:href='#g3-78' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 277.158 34.954)'>
<use x='114.487' xlink:href='#g3-114' y='183.381'/>
<use x='117.379' xlink:href='#g3-112' y='183.381'/>
<use x='121.751' xlink:href='#g3-116' y='183.381'/>
<use x='124.809' xlink:href='#g3-101' y='183.381'/>
<use x='128.573' xlink:href='#g3-115' y='183.381'/>
<use x='131.819' xlink:href='#g3-116' y='183.381'/>
<use x='134.877' xlink:href='#g3-78' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 -40.942 22.192)'>
<use x='114.487' xlink:href='#g2-48' y='183.381'/>
<use x='117.133' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -9.12)'>
<use x='114.487' xlink:href='#g2-48' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-53' y='183.381'/>
<use x='121.25' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -40.431)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -71.743)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-53' y='183.381'/>
<use x='121.25' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(1 0 0 1 -45.059 -103.054)'>
<use x='114.487' xlink:href='#g2-50' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-120' y='183.381'/>
</g>
<path clip-path='url(#clip5)' d='M82.148 141.316H434.164' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M88.945 203.937H92.18V141.316H88.945ZM147.613 203.937H150.852V141.316H147.613ZM206.281 203.937H209.52V141.316H206.281ZM264.949 203.937H268.188V141.316H264.949ZM323.621 203.937H326.859V141.316H323.621ZM382.289 203.937H385.527V141.316H382.289Z' fill='#993333'/>
<path clip-path='url(#clip5)' d='M88.945 203.937H92.18V141.316H88.945ZM147.613 203.937H150.852V141.316H147.613ZM206.281 203.937H209.52V141.316H206.281ZM264.949 203.937H268.188V141.316H264.949ZM323.621 203.937H326.859V141.316H323.621ZM382.289 203.937H385.527V141.316H382.289Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M90.563 141.316V141.129' fill='#993333'/>
<path clip-path='url(#clip5)' d='M90.563 141.316V141.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M88.57 141.129H92.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M90.563 141.316V141.504' fill='#993333'/>
<path clip-path='url(#clip5)' d='M90.563 141.316V141.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M92.555 141.504H88.57' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M149.231 141.316V140.937' fill='#993333'/>
<path clip-path='url(#clip5)' d='M149.231 141.316V140.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M147.238 140.937H151.223' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M149.231 141.316V141.691' fill='#993333'/>
<path clip-path='url(#clip5)' d='M149.231 141.316V141.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M151.223 141.692H147.238' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M207.902 141.316V139.562' fill='#993333'/>
<path clip-path='url(#clip5)' d='M207.902 141.316V139.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M205.906 139.563H209.894' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M207.902 141.316V143.07' fill='#993333'/>
<path clip-path='url(#clip5)' d='M207.902 141.316V143.07' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M209.895 143.071H205.91' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M266.57 141.316V140.25' fill='#993333'/>
<path clip-path='url(#clip5)' d='M266.57 141.316V140.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M264.578 140.25H268.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M266.57 141.316V142.379' fill='#993333'/>
<path clip-path='url(#clip5)' d='M266.57 141.316V142.379' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M268.562 142.379H264.578' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M325.238 141.316V139.312' fill='#993333'/>
<path clip-path='url(#clip5)' d='M325.238 141.316V139.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M323.246 139.312H327.23' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M325.238 141.316V143.32' fill='#993333'/>
<path clip-path='url(#clip5)' d='M325.238 141.316V143.32' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M327.231 143.32H323.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M383.906 141.316V139.875' fill='#993333'/>
<path clip-path='url(#clip5)' d='M383.906 141.316V139.875' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M381.914 139.875H385.898' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M383.906 141.316V142.754' fill='#993333'/>
<path clip-path='url(#clip5)' d='M383.906 141.316V142.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M385.902 142.753H381.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M94.176 203.937H97.41V140.875H94.176ZM152.844 203.937H156.082V135.617H152.844ZM211.512 203.937H214.75V136.805H211.512ZM270.18 203.937H273.418V78.691H270.18ZM328.852 203.937H332.09V139.625H328.852ZM387.52 203.937H390.758V105.746H387.52Z' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M94.176 203.937H97.41V140.875H94.176ZM152.844 203.937H156.082V135.617H152.844ZM211.512 203.937H214.75V136.805H211.512ZM270.18 203.937H273.418V78.691H270.18ZM328.852 203.937H332.09V139.625H328.852ZM387.52 203.937H390.758V105.746H387.52Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M95.793 140.875V140.625' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M95.793 140.875V140.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M93.801 140.625H97.785' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M95.793 140.875V141.129' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M95.793 140.875V141.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M97.785 141.129H93.801' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M154.461 135.617V135.242' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M154.461 135.617V135.242' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M152.469 135.242H156.454' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M154.461 135.617V135.992' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M154.461 135.617V135.992' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M156.453 135.992H152.468' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M213.133 136.805V135.68' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M213.133 136.805V135.68' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M211.137 135.68H215.125' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M213.133 136.805V137.934' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M213.133 136.805V137.934' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M215.125 137.934H211.14' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M271.801 78.691V78.691' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M269.809 78.691H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M271.801 78.691V78.691' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M269.809 78.691H273.793' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M330.469 139.625V139.312' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M330.469 139.625V139.312' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M328.477 139.312H332.461' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M330.469 139.625V139.937' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M330.469 139.625V139.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M332.461 139.937H328.476' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M389.137 105.746V99.609' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M389.137 105.746V99.609' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M387.145 99.609H391.129' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M389.137 105.746V111.883' fill='#8080bf'/>
<path clip-path='url(#clip5)' d='M389.137 105.746V111.883' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M391.132 111.883H387.144' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M99.406 203.937H102.641V139.437H99.406ZM158.074 203.937H161.313V140.437H158.074ZM216.742 203.937H219.981V132.922H216.742ZM275.41 203.937H278.649V78.691H275.41ZM334.082 203.937H337.32V106.996H334.082ZM392.75 203.937H395.988V78.691H392.75Z' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M99.406 203.937H102.641V139.437H99.406ZM158.074 203.937H161.313V140.437H158.074ZM216.742 203.937H219.981V132.922H216.742ZM275.41 203.937H278.649V78.691H275.41ZM334.082 203.937H337.32V106.996H334.082ZM392.75 203.937H395.988V78.691H392.75Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M101.024 139.437V139.25' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M101.024 139.437V139.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M99.031 139.25H103.016' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M101.024 139.437V139.625' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M101.024 139.437V139.625' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M103.016 139.625H99.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M159.691 140.437V140.062' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M159.691 140.437V140.062' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M157.699 140.063H161.684' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M159.691 140.437V140.812' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M159.691 140.437V140.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M161.684 140.812H157.699' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M218.363 132.922V131.547' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M218.363 132.922V131.547' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M216.367 131.547H220.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M218.363 132.922V134.301' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M218.363 132.922V134.301' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M220.356 134.3H216.371' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M277.031 78.691V78.691' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M275.039 78.691H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M277.031 78.691V78.691' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M275.039 78.691H279.023' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M335.699 106.996V105.621' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M335.699 106.996V105.621' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M333.707 105.621H337.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M335.699 106.996V108.375' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M335.699 106.996V108.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M337.692 108.375H333.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M394.367 78.691V78.691' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M392.375 78.691H396.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M394.367 78.691V78.691' fill='#ffb733'/>
<path clip-path='url(#clip5)' d='M392.375 78.691H396.359' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M104.637 203.937H107.871V124.344H104.637ZM163.305 203.937H166.543V135.742H163.305ZM221.973 203.937H225.211V105.996H221.973ZM280.641 203.937H283.879V98.168H280.641ZM339.313 203.937H342.551V122.715H339.313ZM397.981 203.937H401.219V120.336H397.981Z' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M104.637 203.937H107.871V124.344H104.637ZM163.305 203.937H166.543V135.742H163.305ZM221.973 203.937H225.211V105.996H221.973ZM280.641 203.937H283.879V98.168H280.641ZM339.313 203.937H342.551V122.715H339.313ZM397.981 203.937H401.219V120.336H397.981Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M106.254 124.344V124.031' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M106.254 124.344V124.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M104.261 124.031H108.246' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M106.254 124.344V124.656' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M106.254 124.344V124.656' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M108.246 124.656H104.261' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M164.922 135.742V135.555' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M164.922 135.742V135.555' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M162.929 135.555H166.914' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M164.922 135.742V135.93' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M164.922 135.742V135.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M166.914 135.93H162.929' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M223.594 105.996V104.805' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M223.594 105.996V104.805' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M221.597 104.805H225.585' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M223.594 105.996V107.187' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M223.594 105.996V107.187' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M225.586 107.188H221.601' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M282.262 98.168V96.289' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M282.262 98.168V96.289' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M280.269 96.289H284.253' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M282.262 98.168V100.047' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M282.262 98.168V100.047' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M284.254 100.047H280.269' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M340.93 122.715V121.527' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M340.93 122.715V121.527' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M338.937 121.527H342.921' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M340.93 122.715V123.906' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M340.93 122.715V123.906' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M342.922 123.906H338.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M399.598 120.336V114.137' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M399.598 120.336V114.137' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M397.605 114.137H401.589' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M399.598 120.336V126.535' fill='#bf80bf'/>
<path clip-path='url(#clip5)' d='M399.598 120.336V126.535' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M401.593 126.535H397.605' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M109.867 203.937H113.102V140.687H109.867ZM168.535 203.937H171.774V141.316H168.535ZM227.203 203.937H230.442V140.625H227.203ZM285.871 203.937H289.109V136.555H285.871ZM344.543 203.937H347.781V115.453H344.543ZM403.211 203.937H406.449V135.242H403.211Z' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M109.867 203.937H113.102V140.687H109.867ZM168.535 203.937H171.774V141.316H168.535ZM227.203 203.937H230.442V140.625H227.203ZM285.871 203.937H289.109V136.555H285.871ZM344.543 203.937H347.781V115.453H344.543ZM403.211 203.937H406.449V135.242H403.211Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M111.484 140.687V140.562' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M111.484 140.687V140.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M109.492 140.563H113.477' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M111.484 140.687V140.812' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M111.484 140.687V140.812' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M113.477 140.812H109.492' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M170.152 141.316V140.937' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M170.152 141.316V140.937' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M168.16 140.937H172.145' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M170.152 141.316V141.691' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M170.152 141.316V141.691' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M172.145 141.692H168.16' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M228.824 140.625V139.25' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M228.824 140.625V139.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M226.828 139.25H230.816' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M228.824 140.625V142.004' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M228.824 140.625V142.004' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M230.817 142.004H226.832' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M287.492 136.555V134.801' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M287.492 136.555V134.801' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M285.5 134.8H289.484' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M287.492 136.555V138.309' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M287.492 136.555V138.309' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M289.485 138.308H285.5' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M346.16 115.453V114.074' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M346.16 115.453V114.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M344.168 114.074H348.152' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M346.16 115.453V116.828' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M346.16 115.453V116.828' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M348.153 116.829H344.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M404.828 135.242V128.539' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M404.828 135.242V128.539' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M402.836 128.539H406.82' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M404.828 135.242V141.941' fill='#dfbf9f'/>
<path clip-path='url(#clip5)' d='M404.828 135.242V141.941' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M406.824 141.941H402.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M115.098 203.937H118.332V136.055H115.098ZM173.766 203.937H177.004V128.539H173.766ZM232.434 203.937H235.672V116.016H232.434ZM291.102 203.937H294.34V78.691H291.102ZM349.774 203.937H353.012V78.691H349.774ZM408.442 203.937H411.68V78.691H408.442Z' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M115.098 203.937H118.332V136.055H115.098ZM173.766 203.937H177.004V128.539H173.766ZM232.434 203.937H235.672V116.016H232.434ZM291.102 203.937H294.34V78.691H291.102ZM349.774 203.937H353.012V78.691H349.774ZM408.442 203.937H411.68V78.691H408.442Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M116.715 136.055V135.93' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M116.715 136.055V135.93' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M114.722 135.93H118.707' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M116.715 136.055V136.18' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M116.715 136.055V136.18' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M118.707 136.18H114.722' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M175.383 128.539V126.723' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M175.383 128.539V126.723' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M173.39 126.723H177.375' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M175.383 128.539V130.355' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M175.383 128.539V130.355' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M177.375 130.355H173.39' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M234.055 116.016V114.449' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M234.055 116.016V114.449' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M232.058 114.449H236.046' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M234.055 116.016V117.582' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M234.055 116.016V117.582' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M236.047 117.582H232.062' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M292.723 78.691V78.691' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M290.73 78.691H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M292.723 78.691V78.691' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M290.73 78.691H294.714' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M351.391 78.691V78.691' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M349.398 78.691H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M351.391 78.691V78.691' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M349.398 78.691H353.382' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M410.059 78.691V78.691' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M408.066 78.691H412.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M410.059 78.691V78.691' fill='#80bf80'/>
<path clip-path='url(#clip5)' d='M408.066 78.691H412.05' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M120.328 203.937H123.563V137.621H120.328ZM178.996 203.937H182.234V197.676H178.996ZM237.664 203.937H240.902V136.43H237.664ZM296.332 203.937H299.57V116.953H296.332ZM355.004 203.937H358.238V197.676H355.004ZM413.672 203.937H416.91V78.691H413.672Z' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M120.328 203.937H123.563V137.621H120.328ZM178.996 203.937H182.234V197.676H178.996ZM237.664 203.937H240.902V136.43H237.664ZM296.332 203.937H299.57V116.953H296.332ZM355.004 203.937H358.238V197.676H355.004ZM413.672 203.937H416.91V78.691H413.672Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M121.945 137.621V137.371' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M121.945 137.621V137.371' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M119.953 137.371H123.938' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M121.945 137.621V137.871' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M121.945 137.621V137.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M123.938 137.871H119.953' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M180.613 197.676V197.676' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M178.621 197.676H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M180.613 197.676V197.676' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M178.621 197.676H182.606' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M239.285 136.43V134.988' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M239.285 136.43V134.988' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M237.289 134.988H241.274' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M239.285 136.43V137.871' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M239.285 136.43V137.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M241.278 137.871H237.293' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M297.953 116.953V115.391' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M297.953 116.953V115.391' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M295.961 115.39H299.945' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M297.953 116.953V118.519' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M297.953 116.953V118.519' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M299.946 118.519H295.961' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M356.621 197.676V197.676' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M354.629 197.676H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M356.621 197.676V197.676' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M354.629 197.676H358.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M415.289 78.691V78.691' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M413.297 78.691H417.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M415.289 78.691V78.691' fill='#bfbf80'/>
<path clip-path='url(#clip5)' d='M413.297 78.691H417.281' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M125.559 203.937H128.793V138.121H125.559ZM184.227 203.937H187.465V132.047H184.227ZM242.895 203.937H246.133V134.426H242.895ZM301.563 203.937H304.801V78.691H301.563ZM360.234 203.937H363.469V78.691H360.234ZM418.902 203.937H422.141V109.254H418.902Z' fill='#339999'/>
<path clip-path='url(#clip5)' d='M125.559 203.937H128.793V138.121H125.559ZM184.227 203.937H187.465V132.047H184.227ZM242.895 203.937H246.133V134.426H242.895ZM301.563 203.937H304.801V78.691H301.563ZM360.234 203.937H363.469V78.691H360.234ZM418.902 203.937H422.141V109.254H418.902Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M127.176 138.121V137.934' fill='#339999'/>
<path clip-path='url(#clip5)' d='M127.176 138.121V137.934' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M125.183 137.934H129.168' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M127.176 138.121V138.309' fill='#339999'/>
<path clip-path='url(#clip5)' d='M127.176 138.121V138.309' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M129.168 138.308H125.183' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M185.844 132.047V131.672' fill='#339999'/>
<path clip-path='url(#clip5)' d='M185.844 132.047V131.672' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M183.851 131.672H187.836' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M185.844 132.047V132.422' fill='#339999'/>
<path clip-path='url(#clip5)' d='M185.844 132.047V132.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M187.836 132.422H183.851' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M244.516 134.426V133.488' fill='#339999'/>
<path clip-path='url(#clip5)' d='M244.516 134.426V133.488' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M242.519 133.488H246.504' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M244.516 134.426V135.367' fill='#339999'/>
<path clip-path='url(#clip5)' d='M244.516 134.426V135.367' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M246.508 135.367H242.523' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M303.184 78.691V78.691' fill='#339999'/>
<path clip-path='url(#clip5)' d='M301.191 78.691H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M303.184 78.691V78.691' fill='#339999'/>
<path clip-path='url(#clip5)' d='M301.191 78.691H305.175' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M361.852 78.691V78.691' fill='#339999'/>
<path clip-path='url(#clip5)' d='M359.859 78.691H363.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M361.852 78.691V78.691' fill='#339999'/>
<path clip-path='url(#clip5)' d='M359.859 78.691H363.843' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M420.52 109.254V107.25' fill='#339999'/>
<path clip-path='url(#clip5)' d='M420.52 109.254V107.25' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M418.527 107.25H422.511' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M420.52 109.254V111.258' fill='#339999'/>
<path clip-path='url(#clip5)' d='M420.52 109.254V111.258' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M422.512 111.258H418.527' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M130.789 203.937H134.024V139.187H130.789ZM189.457 203.937H192.695V139.312H189.457ZM248.125 203.937H251.363V140.062H248.125ZM306.793 203.937H310.031V126.035H306.793ZM365.465 203.937H368.699V103.176H365.465ZM424.133 203.937H427.371V113.762H424.133Z' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M130.789 203.937H134.024V139.187H130.789ZM189.457 203.937H192.695V139.312H189.457ZM248.125 203.937H251.363V140.062H248.125ZM306.793 203.937H310.031V126.035H306.793ZM365.465 203.937H368.699V103.176H365.465ZM424.133 203.937H427.371V113.762H424.133Z' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M132.406 139.187V138.934' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M132.406 139.187V138.934' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M130.414 138.933H134.399' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M132.406 139.187V139.437' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M132.406 139.187V139.437' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M134.399 139.437H130.414' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M191.074 139.312V139.062' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M191.074 139.312V139.062' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M189.082 139.063H193.067' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M191.074 139.312V139.562' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M191.074 139.312V139.562' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M193.067 139.563H189.082' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M249.746 140.062V138.871' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M249.746 140.062V138.871' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M247.75 138.871H251.735' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M249.746 140.062V141.254' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M249.746 140.062V141.254' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M251.739 141.254H247.754' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M308.414 126.035V125.031' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M308.414 126.035V125.031' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M306.422 125.031H310.407' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M308.414 126.035V127.035' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M308.414 126.035V127.035' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M310.407 127.035H306.422' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M367.082 103.176V101.613' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M367.082 103.176V101.613' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M365.09 101.613H369.074' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M367.082 103.176V104.742' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M367.082 103.176V104.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M369.075 104.742H365.09' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M425.75 113.762V105.184' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M425.75 113.762V105.184' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M423.758 105.184H427.742' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M425.75 113.762V122.34' fill='#bf8080'/>
<path clip-path='url(#clip5)' d='M425.75 113.762V122.34' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<path clip-path='url(#clip5)' d='M427.743 122.34H423.758' fill='none' stroke='#000000' stroke-miterlimit='10' stroke-width='0.399'/>
<g transform='matrix(0 -1 1 0 -91.184 249.777)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -32.515 249.777)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 26.154 249.777)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 84.823 249.777)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 143.492 249.777)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 202.161 249.777)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -85.954 249.339)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-49' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -27.284 244.079)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-57' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 31.385 245.269)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-55' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 90.054 187.154)'>
<use x='109.598' xlink:href='#g4-1' y='183.381'/>
<use x='113.103' xlink:href='#g4-1' y='183.381'/>
<use x='116.608' xlink:href='#g4-1' y='183.381'/>
<use x='120.114' xlink:href='#g2-52' y='183.381'/>
<use x='122.76' xlink:href='#g2-46' y='183.381'/>
<use x='124.23' xlink:href='#g2-57' y='183.381'/>
<use x='126.877' xlink:href='#g2-52' y='183.381'/>
<use x='129.523' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 148.723 248.087)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-51' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 207.392 214.208)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-53' y='183.381'/>
<use x='121.25' xlink:href='#g2-55' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -80.723 247.899)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-51' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -22.054 248.901)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-49' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 36.615 241.386)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-49' y='183.381'/>
<use x='121.25' xlink:href='#g2-51' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 95.284 187.154)'>
<use x='109.598' xlink:href='#g4-1' y='183.381'/>
<use x='113.103' xlink:href='#g4-1' y='183.381'/>
<use x='116.608' xlink:href='#g4-1' y='183.381'/>
<use x='120.114' xlink:href='#g2-53' y='183.381'/>
<use x='122.76' xlink:href='#g2-46' y='183.381'/>
<use x='124.23' xlink:href='#g2-50' y='183.381'/>
<use x='126.877' xlink:href='#g2-50' y='183.381'/>
<use x='129.523' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 153.953 215.46)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-53' y='183.381'/>
<use x='121.25' xlink:href='#g2-53' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 212.622 187.154)'>
<use x='109.598' xlink:href='#g4-1' y='183.381'/>
<use x='113.103' xlink:href='#g4-1' y='183.381'/>
<use x='116.608' xlink:href='#g4-1' y='183.381'/>
<use x='120.114' xlink:href='#g2-51' y='183.381'/>
<use x='122.76' xlink:href='#g2-46' y='183.381'/>
<use x='124.23' xlink:href='#g2-55' y='183.381'/>
<use x='126.877' xlink:href='#g2-56' y='183.381'/>
<use x='129.523' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -75.493 232.807)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-50' y='183.381'/>
<use x='121.25' xlink:href='#g2-55' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -16.824 244.204)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-57' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 41.845 214.458)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-53' y='183.381'/>
<use x='121.25' xlink:href='#g2-54' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 100.514 206.63)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-54' y='183.381'/>
<use x='121.25' xlink:href='#g2-57' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 159.183 231.178)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-51' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 217.852 228.799)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-51' y='183.381'/>
<use x='121.25' xlink:href='#g2-52' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -70.262 249.151)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-49' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -11.593 249.777)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 47.076 249.089)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-49' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 105.745 245.018)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-56' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 164.414 223.914)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-52' y='183.381'/>
<use x='121.25' xlink:href='#g2-49' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 223.083 243.703)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-49' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -65.032 244.517)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-56' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -6.363 237.002)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-50' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 52.306 224.478)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-52' y='183.381'/>
<use x='121.25' xlink:href='#g2-48' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 110.975 187.154)'>
<use x='109.598' xlink:href='#g4-1' y='183.381'/>
<use x='113.103' xlink:href='#g4-1' y='183.381'/>
<use x='116.608' xlink:href='#g4-1' y='183.381'/>
<use x='120.114' xlink:href='#g2-51' y='183.381'/>
<use x='122.76' xlink:href='#g2-46' y='183.381'/>
<use x='124.23' xlink:href='#g2-48' y='183.381'/>
<use x='126.877' xlink:href='#g2-50' y='183.381'/>
<use x='129.523' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 169.644 187.154)'>
<use x='109.598' xlink:href='#g4-1' y='183.381'/>
<use x='113.103' xlink:href='#g4-1' y='183.381'/>
<use x='116.608' xlink:href='#g4-1' y='183.381'/>
<use x='120.114' xlink:href='#g2-50' y='183.381'/>
<use x='122.76' xlink:href='#g2-46' y='183.381'/>
<use x='124.23' xlink:href='#g2-51' y='183.381'/>
<use x='126.877' xlink:href='#g2-49' y='183.381'/>
<use x='129.523' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 228.313 187.154)'>
<use x='109.598' xlink:href='#g4-1' y='183.381'/>
<use x='113.103' xlink:href='#g4-1' y='183.381'/>
<use x='116.608' xlink:href='#g4-1' y='183.381'/>
<use x='120.114' xlink:href='#g2-52' y='183.381'/>
<use x='122.76' xlink:href='#g2-46' y='183.381'/>
<use x='124.23' xlink:href='#g2-54' y='183.381'/>
<use x='126.877' xlink:href='#g2-51' y='183.381'/>
<use x='129.523' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -59.801 246.083)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-54' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -1.66 306.138)'>
<use x='114.487' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 57.537 244.893)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-56' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 116.206 225.417)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-51' y='183.381'/>
<use x='121.25' xlink:href='#g2-57' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 174.347 306.138)'>
<use x='114.487' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 233.544 187.154)'>
<use x='109.598' xlink:href='#g4-1' y='183.381'/>
<use x='113.103' xlink:href='#g4-1' y='183.381'/>
<use x='116.608' xlink:href='#g4-1' y='183.381'/>
<use x='120.114' xlink:href='#g2-51' y='183.381'/>
<use x='122.76' xlink:href='#g2-46' y='183.381'/>
<use x='124.23' xlink:href='#g2-56' y='183.381'/>
<use x='126.877' xlink:href='#g2-53' y='183.381'/>
<use x='129.523' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -54.571 246.584)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-53' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 4.098 240.509)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-49' y='183.381'/>
<use x='121.25' xlink:href='#g2-53' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 62.767 242.889)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-49' y='183.381'/>
<use x='121.25' xlink:href='#g2-49' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 121.436 187.154)'>
<use x='109.598' xlink:href='#g4-1' y='183.381'/>
<use x='113.103' xlink:href='#g4-1' y='183.381'/>
<use x='116.608' xlink:href='#g4-1' y='183.381'/>
<use x='120.114' xlink:href='#g2-51' y='183.381'/>
<use x='122.76' xlink:href='#g2-46' y='183.381'/>
<use x='124.23' xlink:href='#g2-50' y='183.381'/>
<use x='126.877' xlink:href='#g2-50' y='183.381'/>
<use x='129.523' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 180.105 187.154)'>
<use x='109.598' xlink:href='#g4-1' y='183.381'/>
<use x='113.103' xlink:href='#g4-1' y='183.381'/>
<use x='116.608' xlink:href='#g4-1' y='183.381'/>
<use x='120.114' xlink:href='#g2-50' y='183.381'/>
<use x='122.76' xlink:href='#g2-46' y='183.381'/>
<use x='124.23' xlink:href='#g2-56' y='183.381'/>
<use x='126.877' xlink:href='#g2-56' y='183.381'/>
<use x='129.523' xlink:href='#g2-120' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 238.774 217.714)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-53' y='183.381'/>
<use x='121.25' xlink:href='#g2-49' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -49.34 247.648)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-51' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 9.329 247.773)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-51' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 67.998 248.525)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-48' y='183.381'/>
<use x='121.25' xlink:href='#g2-50' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 126.667 234.497)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-50' y='183.381'/>
<use x='121.25' xlink:href='#g2-52' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 185.336 211.64)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-54' y='183.381'/>
<use x='121.25' xlink:href='#g2-49' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 244.005 222.223)'>
<use x='114.487' xlink:href='#g2-49' y='183.381'/>
<use x='117.133' xlink:href='#g2-46' y='183.381'/>
<use x='118.603' xlink:href='#g2-52' y='183.381'/>
<use x='121.25' xlink:href='#g2-52' y='183.381'/>
</g>
<g transform='matrix(0 -1 1 0 -124.021 311.062)'>
<use x='114.487' xlink:href='#g1-82' y='183.381'/>
<use x='120.457' xlink:href='#g1-101' y='183.381'/>
<use x='124.553' xlink:href='#g1-108' y='183.381'/>
<use x='126.753' xlink:href='#g1-97' y='183.381'/>
<use x='131.181' xlink:href='#g1-116' y='183.381'/>
<use x='134.509' xlink:href='#g1-105' y='183.381'/>
<use x='136.709' xlink:href='#g1-118' y='183.381'/>
<use x='140.957' xlink:href='#g1-101' y='183.381'/>
<use x='148.124' xlink:href='#g1-116' y='183.381'/>
<use x='151.452' xlink:href='#g1-105' y='183.381'/>
<use x='153.652' xlink:href='#g1-109' y='183.381'/>
<use x='160.972' xlink:href='#g1-101' y='183.381'/>
<use x='168.139' xlink:href='#g3-40' y='183.381'/>
<use x='171.432' xlink:href='#g3-108' y='183.381'/>
<use x='173.453' xlink:href='#g3-111' y='183.381'/>
<use x='177.452' xlink:href='#g3-119' y='183.381'/>
<use x='183' xlink:href='#g3-101' y='183.381'/>
<use x='186.764' xlink:href='#g3-114' y='183.381'/>
<use x='192.479' xlink:href='#g3-105' y='183.381'/>
<use x='194.499' xlink:href='#g3-115' y='183.381'/>
<use x='200.568' xlink:href='#g3-98' y='183.381'/>
<use x='205.176' xlink:href='#g3-101' y='183.381'/>
<use x='208.94' xlink:href='#g3-116' y='183.381'/>
<use x='211.998' xlink:href='#g3-116' y='183.381'/>
<use x='215.056' xlink:href='#g3-101' y='183.381'/>
<use x='218.819' xlink:href='#g3-114' y='183.381'/>
<use x='221.711' xlink:href='#g3-41' y='183.381'/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 75 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 93 KiB

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.0 PROJECT_NUMBER = 1.4
# 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

@ -26,7 +26,7 @@ without code changes, for example, on Unix you can use it as:
Notable aspects of the design include: Notable aspects of the design include:
- __small and consistent__: the library is less than 3500 LOC using simple and - __small and consistent__: the library is less than 6k LOC using simple and
consistent data structures. This makes it very suitable consistent data structures. This makes it very suitable
to integrate and adapt in other projects. For runtime systems it to integrate and adapt in other projects. For runtime systems it
provides hooks for a monotonic _heartbeat_ and deferred freeing (for provides hooks for a monotonic _heartbeat_ and deferred freeing (for
@ -74,6 +74,8 @@ Further information:
- \ref typed - \ref typed
- \ref analysis - \ref analysis
- \ref options - \ref options
- \ref posix
- \ref cpp
*/ */
@ -297,10 +299,17 @@ size_t mi_good_size(size_t size);
void mi_collect(bool force); void mi_collect(bool force);
/// Print the main statistics. /// Print the main statistics.
/// @param out Output function. Use \a NULL for outputting to \a stderr. /// @param out Ignored, outputs to the registered output function or stderr by default.
/// ///
/// Most detailed when using a debug build. /// Most detailed when using a debug build.
void mi_stats_print(mi_output_fun* out); void mi_stats_print(void* out);
/// Print the main statistics.
/// @param out An output function or \a NULL for the default.
/// @param arg Optional argument passed to \a out (if not \a NULL)
///
/// Most detailed when using a debug build.
void mi_stats_print(mi_output_fun* out, void* arg);
/// Reset statistics. /// Reset statistics.
void mi_stats_reset(void); void mi_stats_reset(void);
@ -320,20 +329,23 @@ void mi_thread_init(void);
void mi_thread_done(void); void mi_thread_done(void);
/// Print out heap statistics for this thread. /// Print out heap statistics for this thread.
/// @param out Output function. Use \a NULL for outputting to \a stderr. /// @param out An output function or \a NULL for the default.
/// @param arg Optional argument passed to \a out (if not \a NULL)
/// ///
/// Most detailed when using a debug build. /// Most detailed when using a debug build.
void mi_thread_stats_print(mi_output_fun* out); void mi_thread_stats_print_out(mi_output_fun* out, void* arg);
/// Type of deferred free functions. /// Type of deferred free functions.
/// @param force If \a true all outstanding items should be freed. /// @param force If \a true all outstanding items should be freed.
/// @param heartbeat A monotonically increasing count. /// @param heartbeat A monotonically increasing count.
/// @param arg Argument that was passed at registration to hold extra state.
/// ///
/// @see mi_register_deferred_free /// @see mi_register_deferred_free
typedef void (mi_deferred_free_fun)(bool force, unsigned long long heartbeat); typedef void (mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg);
/// Register a deferred free function. /// Register a deferred free function.
/// @param deferred_free Address of a deferred free-ing function or \a NULL to unregister. /// @param deferred_free Address of a deferred free-ing function or \a NULL to unregister.
/// @param arg Argument that will be passed on to the deferred free function.
/// ///
/// Some runtime systems use deferred free-ing, for example when using /// Some runtime systems use deferred free-ing, for example when using
/// reference counting to limit the worst case free time. /// reference counting to limit the worst case free time.
@ -346,20 +358,46 @@ typedef void (mi_deferred_free_fun)(bool force, unsigned long long heartbeat);
/// to be called deterministically after some number of allocations /// to be called deterministically after some number of allocations
/// (regardless of freeing or available free memory). /// (regardless of freeing or available free memory).
/// At most one \a deferred_free function can be active. /// At most one \a deferred_free function can be active.
void mi_register_deferred_free(mi_deferred_free_fun* deferred_free); void mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg);
/// Type of output functions. /// Type of output functions.
/// @param msg Message to output. /// @param msg Message to output.
/// @param arg Argument that was passed at registration to hold extra state.
/// ///
/// @see mi_register_output() /// @see mi_register_output()
typedef void (mi_output_fun)(const char* msg); typedef void (mi_output_fun)(const char* msg, void* arg);
/// Register an output function. /// Register an output function.
/// @param out The output function, use `NULL` to output to stdout. /// @param out The output function, use `NULL` to output to stderr.
/// @param arg Argument that will be passed on to the output function.
/// ///
/// The `out` function is called to output any information from mimalloc, /// The `out` function is called to output any information from mimalloc,
/// like verbose or warning messages. /// like verbose or warning messages.
void mi_register_output(mi_output_fun* out) mi_attr_noexcept; void mi_register_output(mi_output_fun* out, void* arg);
/// Type of error callback functions.
/// @param err Error code (see mi_register_error() for a complete list).
/// @param arg Argument that was passed at registration to hold extra state.
///
/// @see mi_register_error()
typedef void (mi_error_fun)(int err, void* arg);
/// Register an error callback function.
/// @param errfun The error function that is called on an error (use \a NULL for default)
/// @param arg Extra argument that will be passed on to the error function.
///
/// The \a errfun function is called on an error in mimalloc after emitting
/// an error message (through the output function). It as always legal to just
/// return from the \a errfun function in which case allocation functions generally
/// return \a NULL or ignore the condition. The default function only calls abort()
/// when compiled in secure mode with an \a EFAULT error. The possible error
/// codes are:
/// * \a EAGAIN: Double free was detected (only in debug and secure mode).
/// * \a EFAULT: Corrupted free list or meta-data was detected (only in debug and secure mode).
/// * \a ENOMEM: Not enough memory available to satisfy the request.
/// * \a EOVERFLOW: Too large a request, for example in mi_calloc(), the \a count and \a size parameters are too large.
/// * \a EINVAL: Trying to free or re-allocate an invalid pointer.
void mi_register_error(mi_error_fun* errfun, void* arg);
/// Is a pointer part of our heap? /// Is a pointer part of our heap?
/// @param p The pointer to check. /// @param p The pointer to check.
@ -367,18 +405,35 @@ void mi_register_output(mi_output_fun* out) mi_attr_noexcept;
/// This function is relatively fast. /// This function is relatively fast.
bool mi_is_in_heap_region(const void* p); bool mi_is_in_heap_region(const void* p);
/// Reserve \a pages of huge OS pages (1GiB) but stops after at most `max_secs` seconds.
/// Reserve \a pages of huge OS pages (1GiB) evenly divided over \a numa_nodes nodes,
/// but stops after at most `timeout_msecs` seconds.
/// @param pages The number of 1GiB pages to reserve. /// @param pages The number of 1GiB pages to reserve.
/// @param max_secs Maximum number of seconds to try reserving. /// @param numa_nodes The number of nodes do evenly divide the pages over, or 0 for using the actual number of NUMA nodes.
/// @param pages_reserved If not \a NULL, it is set to the actual number of pages that were reserved. /// @param timeout_msecs Maximum number of milli-seconds to try reserving, or 0 for no timeout.
/// @returns 0 if successfull, \a ENOMEM if running out of memory, or \a ETIMEDOUT if timed out. /// @returns 0 if successfull, \a ENOMEM if running out of memory, or \a ETIMEDOUT if timed out.
/// ///
/// The reserved memory is used by mimalloc to satisfy allocations. /// The reserved memory is used by mimalloc to satisfy allocations.
/// May quit before \a max_secs are expired if it estimates it will take more than /// May quit before \a timeout_msecs are expired if it estimates it will take more than
/// 1.5 times \a max_secs. The time limit is needed because on some operating systems /// 1.5 times \a timeout_msecs. The time limit is needed because on some operating systems
/// it can take a long time to reserve contiguous memory if the physical memory is /// it can take a long time to reserve contiguous memory if the physical memory is
/// fragmented. /// fragmented.
int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved); int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs);
/// Reserve \a pages of huge OS pages (1GiB) at a specific \a numa_node,
/// but stops after at most `timeout_msecs` seconds.
/// @param pages The number of 1GiB pages to reserve.
/// @param numa_node The NUMA node where the memory is reserved (start at 0).
/// @param timeout_msecs Maximum number of milli-seconds to try reserving, or 0 for no timeout.
/// @returns 0 if successfull, \a ENOMEM if running out of memory, or \a ETIMEDOUT if timed out.
///
/// The reserved memory is used by mimalloc to satisfy allocations.
/// May quit before \a timeout_msecs are expired if it estimates it will take more than
/// 1.5 times \a timeout_msecs. The time limit is needed because on some operating systems
/// it can take a long time to reserve contiguous memory if the physical memory is
/// fragmented.
int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs);
/// Is the C runtime \a malloc API redirected? /// Is the C runtime \a malloc API redirected?
/// @returns \a true if all malloc API calls are redirected to mimalloc. /// @returns \a true if all malloc API calls are redirected to mimalloc.
@ -569,7 +624,10 @@ void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, siz
/// \defgroup typed Typed Macros /// \defgroup typed Typed Macros
/// ///
/// Typed allocation macros /// Typed allocation macros. For example:
/// ```
/// int* p = mi_malloc_tp(int)
/// ```
/// ///
/// \{ /// \{
@ -703,11 +761,12 @@ typedef enum mi_option_e {
mi_option_large_os_pages, ///< Use large OS pages (2MiB in size) if possible mi_option_large_os_pages, ///< Use large OS pages (2MiB in size) if possible
mi_option_reserve_huge_os_pages, ///< The number of huge OS pages (1GiB in size) to reserve at the start of the program. mi_option_reserve_huge_os_pages, ///< The number of huge OS pages (1GiB in size) to reserve at the start of the program.
mi_option_segment_cache, ///< The number of segments per thread to keep cached. mi_option_segment_cache, ///< The number of segments per thread to keep cached.
mi_option_page_reset, ///< Reset page memory when it becomes free. mi_option_page_reset, ///< Reset page memory after \a mi_option_reset_delay milliseconds when it becomes free.
mi_option_cache_reset, ///< Reset segment memory when a segment is cached. mi_option_segment_reset, ///< Experimental
mi_option_reset_delay, ///< Delay in milli-seconds before resetting a page (100ms by default)
mi_option_use_numa_nodes, ///< Pretend there are at most N NUMA nodes
mi_option_reset_decommits, ///< Experimental mi_option_reset_decommits, ///< Experimental
mi_option_eager_commit_delay, ///< Experimental mi_option_eager_commit_delay, ///< Experimental
mi_option_segment_reset, ///< Experimental
mi_option_os_tag, ///< OS tag to assign to mimalloc'd memory mi_option_os_tag, ///< OS tag to assign to mimalloc'd memory
_mi_option_last _mi_option_last
} mi_option_t; } mi_option_t;
@ -751,18 +810,51 @@ void mi_free_size(void* p, size_t size);
void mi_free_size_aligned(void* p, size_t size, size_t alignment); void mi_free_size_aligned(void* p, size_t size, size_t alignment);
void mi_free_aligned(void* p, size_t alignment); void mi_free_aligned(void* p, size_t alignment);
/// raise `std::bad_alloc` exception on failure. /// \}
/// \defgroup cpp C++ wrappers
///
/// `mi_` prefixed implementations of various allocation functions
/// that use C++ semantics on out-of-memory, generally calling
/// `std::get_new_handler` and raising a `std::bad_alloc` exception on failure.
///
/// Note: use the `mimalloc-new-delete.h` header to override the \a new
/// and \a delete operators globally. The wrappers here are mostly
/// for convience for library writers that need to interface with
/// mimalloc from C++.
///
/// \{
/// like mi_malloc(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
void* mi_new(std::size_t n) noexcept(false); void* mi_new(std::size_t n) noexcept(false);
/// raise `std::bad_alloc` exception on failure. /// like mi_mallocn(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
void* mi_new_n(size_t count, size_t size) noexcept(false);
/// like mi_malloc_aligned(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
void* mi_new_aligned(std::size_t n, std::align_val_t alignment) noexcept(false); void* mi_new_aligned(std::size_t n, std::align_val_t alignment) noexcept(false);
/// return `NULL` on failure. /// like `mi_malloc`, but when out of memory, use `std::get_new_handler` but return \a NULL on failure.
void* mi_new_nothrow(size_t n); void* mi_new_nothrow(size_t n);
``
/// return `NULL` on failure. /// like `mi_malloc_aligned`, but when out of memory, use `std::get_new_handler` but return \a NULL on failure.
void* mi_new_aligned_nothrow(size_t n, size_t alignment); void* mi_new_aligned_nothrow(size_t n, size_t alignment);
/// like mi_realloc(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
void* mi_new_realloc(void* p, size_t newsize);
/// like mi_reallocn(), but when out of memory, use `std::get_new_handler` and raise `std::bad_alloc` exception on failure.
void* mi_new_reallocn(void* p, size_t newcount, size_t size);
/// \a std::allocator implementation for mimalloc for use in STL containers.
/// For example:
/// ```
/// std::vector<int, mi_stl_allocator<int> > vec;
/// vec.push_back(1);
/// vec.pop_back();
/// ```
template<class T> struct mi_stl_allocator { }
/// \} /// \}
/*! \page build Building /*! \page build Building
@ -774,7 +866,7 @@ git clone https://github.com/microsoft/mimalloc
## Windows ## Windows
Open `ide/vs2017/mimalloc.sln` in Visual Studio 2017 and build. Open `ide/vs2019/mimalloc.sln` in Visual Studio 2019 and build (or `ide/vs2017/mimalloc.sln`).
The `mimalloc` project builds a static library (in `out/msvc-x64`), while the The `mimalloc` project builds a static library (in `out/msvc-x64`), while the
`mimalloc-override` project builds a DLL for overriding malloc `mimalloc-override` project builds a DLL for overriding malloc
in the entire program. in the entire program.
@ -826,6 +918,7 @@ Notes:
/*! \page using Using the library /*! \page using Using the library
### Build
The preferred usage is including `<mimalloc.h>`, linking with The preferred usage is including `<mimalloc.h>`, linking with
the shared- or static library, and using the `mi_malloc` API exclusively for allocation. For example, the shared- or static library, and using the `mi_malloc` API exclusively for allocation. For example,
@ -849,6 +942,19 @@ target_link_libraries(myapp PUBLIC mimalloc-static)
``` ```
to link with the static library. See `test\CMakeLists.txt` for an example. to link with the static library. See `test\CMakeLists.txt` for an example.
### C++
For best performance in C++ programs, it is also recommended to override the
global `new` and `delete` operators. For convience, mimalloc provides
[`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h) which does this for you -- just include it in a single(!) source file in your project.
In C++, mimalloc also provides the `mi_stl_allocator` struct which implements the `std::allocator`
interface. For example:
```
std::vector<some_struct, mi_stl_allocator<some_struct>> vec;
vec.push_back(some_struct());
```
### Statistics
You can pass environment variables to print verbose messages (`MIMALLOC_VERBOSE=1`) You can pass environment variables to print verbose messages (`MIMALLOC_VERBOSE=1`)
and statistics (`MIMALLOC_SHOW_STATS=1`) (in the debug version): and statistics (`MIMALLOC_SHOW_STATS=1`) (in the debug version):
@ -897,20 +1003,33 @@ See \ref overrides for more info.
/*! \page environment Environment Options /*! \page environment Environment Options
You can set further options either programmatically You can set further options either programmatically (using [`mi_option_set`](https://microsoft.github.io/mimalloc/group__options.html)),
(using [`mi_option_set`](https://microsoft.github.io/mimalloc/group__options.html)),
or via environment variables. 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
memory fragmentation in long running (server) programs. If performance is impacted,
`MIMALLOC_RESET_DELAY=`_msecs_ can be set higher (100ms by default) to make the page
reset occur less frequently.
- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages when available; for some workloads this can significantly - `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages 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]). 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
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_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, in reality it is always better 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. 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
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 [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
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).
[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
@ -960,25 +1079,28 @@ Note: unfortunately, at this time, dynamic overriding on macOS seems broken but
### Windows ### Windows
On Windows you need to link your program explicitly with the mimalloc Overriding on Windows is robust but requires that you link your program explicitly with
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 Moreover, you need to ensure the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) is available
in the same folder as the mimalloc DLL at runtime (as it as referred to by the mimalloc DLL). in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency).
The redirection DLL's ensure all calls to the C runtime malloc API get redirected to mimalloc. The redirection DLL ensures that all calls to the C runtime malloc API get redirected to
mimalloc (in `mimalloc-override.dll`).
To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some 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 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
[`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 successfully redirected. overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected.
(Note: in principle, it should be possible to patch existing executables (Note: in principle, it is possible to patch existing executables
that are linked with the dynamic C runtime (`ucrtbase.dll`) by just putting the mimalloc DLL into 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)
the import table (and putting `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)).
## Static override ## Static override
On Unix systems, you can also statically link with _mimalloc_ to override the standard On Unix systems, you can also statically link with _mimalloc_ to override the standard

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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -105,6 +105,7 @@ $(document).ready(function(){initNavTree('annotated.html','');});
<div class="textblock">Here are the data structures with brief descriptions:</div><div class="directory"> <div class="textblock">Here are the data structures with brief descriptions:</div><div class="directory">
<table class="directory"> <table class="directory">
<tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="group__analysis.html#structmi__heap__area__t" target="_self">mi_heap_area_t</a></td><td class="desc">An area of heap space contains blocks of a single size </td></tr> <tr id="row_0_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="group__analysis.html#structmi__heap__area__t" target="_self">mi_heap_area_t</a></td><td class="desc">An area of heap space contains blocks of a single size </td></tr>
<tr id="row_1_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><span class="icona"><span class="icon">C</span></span><a class="el" href="group__cpp.html#structmi__stl__allocator" target="_self">mi_stl_allocator</a></td><td class="desc"><em>std::allocator</em> implementation for mimalloc for use in STL containers </td></tr>
</table> </table>
</div><!-- directory --> </div><!-- directory -->
</div><!-- contents --> </div><!-- contents -->

View file

@ -1,4 +1,5 @@
var annotated_dup = var annotated_dup =
[ [
[ "mi_heap_area_t", "group__analysis.html#structmi__heap__area__t", "group__analysis_structmi__heap__area__t" ] [ "mi_heap_area_t", "group__analysis.html#structmi__heap__area__t", "group__analysis_structmi__heap__area__t" ],
[ "mi_stl_allocator", "group__cpp.html#structmi__stl__allocator", null ]
]; ];

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.0</span> &#160;<span id="projectnumber">1.4</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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -103,7 +103,7 @@ $(document).ready(function(){initNavTree('build.html','');});
</div><!--header--> </div><!--header-->
<div class="contents"> <div class="contents">
<div class="textblock"><p>Checkout the sources from Github: </p><div class="fragment"><div class="line">git clone https:<span class="comment">//github.com/microsoft/mimalloc</span></div></div><!-- fragment --><h2>Windows</h2> <div class="textblock"><p>Checkout the sources from Github: </p><div class="fragment"><div class="line">git clone https:<span class="comment">//github.com/microsoft/mimalloc</span></div></div><!-- fragment --><h2>Windows</h2>
<p>Open <code>ide/vs2017/mimalloc.sln</code> in Visual Studio 2017 and build. The <code>mimalloc</code> project builds a static library (in <code>out/msvc-x64</code>), while the <code>mimalloc-override</code> project builds a DLL for overriding malloc in the entire program.</p> <p>Open <code>ide/vs2019/mimalloc.sln</code> in Visual Studio 2019 and build (or <code>ide/vs2017/mimalloc.sln</code>). The <code>mimalloc</code> project builds a static library (in <code>out/msvc-x64</code>), while the <code>mimalloc-override</code> project builds a DLL for overriding malloc in the entire program.</p>
<h2>macOS, Linux, BSD, etc.</h2> <h2>macOS, Linux, BSD, etc.</h2>
<p>We use <a href="https://cmake.org"><code>cmake</code></a><sup>1</sup> as the build system:</p> <p>We use <a href="https://cmake.org"><code>cmake</code></a><sup>1</sup> as the build system:</p>
<div class="fragment"><div class="line">&gt; mkdir -p out/release</div><div class="line">&gt; cd out/release</div><div class="line">&gt; cmake ../..</div><div class="line">&gt; make</div></div><!-- fragment --><p> This builds the library as a shared (dynamic) library (<code>.so</code> or <code>.dylib</code>), a static library (<code>.a</code>), and as a single object file (<code>.o</code>).</p> <div class="fragment"><div class="line">&gt; mkdir -p out/release</div><div class="line">&gt; cd out/release</div><div class="line">&gt; cmake ../..</div><div class="line">&gt; make</div></div><!-- fragment --><p> This builds the library as a shared (dynamic) library (<code>.so</code> or <code>.dylib</code>), a static library (<code>.a</code>), and as a single object file (<code>.o</code>).</p>

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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -105,10 +105,10 @@ $(document).ready(function(){initNavTree('classes.html','');});
<div class="qindex"><a class="qindex" href="#letter_m">m</a></div> <div class="qindex"><a class="qindex" href="#letter_m">m</a></div>
<table class="classindex"> <table class="classindex">
<tr><td rowspan="2" valign="bottom"><a name="letter_m"></a><table border="0" cellspacing="0" cellpadding="0"><tr><td><div class="ah">&#160;&#160;m&#160;&#160;</div></td></tr></table> <tr><td rowspan="2" valign="bottom"><a name="letter_m"></a><table border="0" cellspacing="0" cellpadding="0"><tr><td><div class="ah">&#160;&#160;m&#160;&#160;</div></td></tr></table>
</td><td></td></tr> </td><td valign="top"><a class="el" href="group__cpp.html#structmi__stl__allocator">mi_stl_allocator</a>&#160;&#160;&#160;</td><td></td></tr>
<tr><td></td><td></td></tr> <tr><td></td><td></td><td></td></tr>
<tr><td valign="top"><a class="el" href="group__analysis.html#structmi__heap__area__t">mi_heap_area_t</a>&#160;&#160;&#160;</td><td></td></tr> <tr><td valign="top"><a class="el" href="group__analysis.html#structmi__heap__area__t">mi_heap_area_t</a>&#160;&#160;&#160;</td><td></td><td></td></tr>
<tr><td></td><td></td></tr> <tr><td></td><td></td><td></td></tr>
</table> </table>
<div class="qindex"><a class="qindex" href="#letter_m">m</a></div> <div class="qindex"><a class="qindex" href="#letter_m">m</a></div>
</div><!-- contents --> </div><!-- contents -->

127
docs/environment.html Normal file
View file

@ -0,0 +1,127 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>mi-malloc: Environment Options</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(initResizable);
/* @license-end */</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function() { init_search(); });
/* @license-end */
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span>
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.15 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('environment.html','');});
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="PageDoc"><div class="header">
<div class="headertitle">
<div class="title">Environment Options </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>You can set further options either programmatically (using <a href="https://microsoft.github.io/mimalloc/group__options.html"><code>mi_option_set</code></a>), or via environment variables.</p>
<ul>
<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_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_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_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 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>
</div></div><!-- PageDoc -->
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.15 </li>
</ul>
</div>
</body>
</html>

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.0</span> &#160;<span id="projectnumber">1.4</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.0</span> &#160;<span id="projectnumber">1.4</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.0</span> &#160;<span id="projectnumber">1.4</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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

396
docs/group__cpp.html Normal file
View file

@ -0,0 +1,396 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>mi-malloc: C++ wrappers</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(initResizable);
/* @license-end */</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function() { init_search(); });
/* @license-end */
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span>
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.15 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('group__cpp.html','');});
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="header">
<div class="summary">
<a href="#nested-classes">Data Structures</a> &#124;
<a href="#func-members">Functions</a> </div>
<div class="headertitle">
<div class="title">C++ wrappers</div> </div>
</div><!--header-->
<div class="contents">
<p><code>mi_</code> prefixed implementations of various allocation functions that use C++ semantics on out-of-memory, generally calling <code>std::get_new_handler</code> and raising a <code>std::bad_alloc</code> exception on failure.
<a href="#details">More...</a></p>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="nested-classes"></a>
Data Structures</h2></td></tr>
<tr class="memitem:structmi__stl__allocator"><td class="memItemLeft" align="right" valign="top">struct &#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#structmi__stl__allocator">mi_stl_allocator&lt; T &gt;</a></td></tr>
<tr class="memdesc:structmi__stl__allocator"><td class="mdescLeft">&#160;</td><td class="mdescRight"><em>std::allocator</em> implementation for mimalloc for use in STL containers. <a href="group__cpp.html#structmi__stl__allocator">More...</a><br /></td></tr>
<tr class="separator:structmi__stl__allocator"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
Functions</h2></td></tr>
<tr class="memitem:gaad048a9fce3d02c5909cd05c6ec24545"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545">mi_new</a> (std::size_t n) noexcept(false)</td></tr>
<tr class="memdesc:gaad048a9fce3d02c5909cd05c6ec24545"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <a href="#gaad048a9fce3d02c5909cd05c6ec24545">More...</a><br /></td></tr>
<tr class="separator:gaad048a9fce3d02c5909cd05c6ec24545"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gae7bc4f56cd57ed3359060ff4f38bda81"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81">mi_new_n</a> (size_t count, size_t size) noexcept(false)</td></tr>
<tr class="memdesc:gae7bc4f56cd57ed3359060ff4f38bda81"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6" title="Allocate count elements of size bytes.">mi_mallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <a href="#gae7bc4f56cd57ed3359060ff4f38bda81">More...</a><br /></td></tr>
<tr class="separator:gae7bc4f56cd57ed3359060ff4f38bda81"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaef2c2bdb4f70857902d3c8903ac095f3"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3">mi_new_aligned</a> (std::size_t n, std::align_val_t alignment) noexcept(false)</td></tr>
<tr class="memdesc:gaef2c2bdb4f70857902d3c8903ac095f3"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56" title="Allocate size bytes aligned by alignment.">mi_malloc_aligned()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <a href="#gaef2c2bdb4f70857902d3c8903ac095f3">More...</a><br /></td></tr>
<tr class="separator:gaef2c2bdb4f70857902d3c8903ac095f3"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaeaded64eda71ed6b1d569d3e723abc4a"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a">mi_new_nothrow</a> (size_t n)</td></tr>
<tr class="memdesc:gaeaded64eda71ed6b1d569d3e723abc4a"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <code>mi_malloc</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure. <a href="#gaeaded64eda71ed6b1d569d3e723abc4a">More...</a><br /></td></tr>
<tr class="separator:gaeaded64eda71ed6b1d569d3e723abc4a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gab5e29558926d934c3f1cae8c815f942c"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gab5e29558926d934c3f1cae8c815f942c">mi_new_aligned_nothrow</a> (size_t n, size_t alignment)</td></tr>
<tr class="memdesc:gab5e29558926d934c3f1cae8c815f942c"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <code>mi_malloc_aligned</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure. <a href="#gab5e29558926d934c3f1cae8c815f942c">More...</a><br /></td></tr>
<tr class="separator:gab5e29558926d934c3f1cae8c815f942c"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaab78a32f55149e9fbf432d5288e38e1e"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e">mi_new_realloc</a> (void *p, size_t newsize)</td></tr>
<tr class="memdesc:gaab78a32f55149e9fbf432d5288e38e1e"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6" title="Re-allocate memory to newsize bytes.">mi_realloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <a href="#gaab78a32f55149e9fbf432d5288e38e1e">More...</a><br /></td></tr>
<tr class="separator:gaab78a32f55149e9fbf432d5288e38e1e"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga756f4b2bc6a7ecd0a90baea8e90c7907"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907">mi_new_reallocn</a> (void *p, size_t newcount, size_t size)</td></tr>
<tr class="memdesc:ga756f4b2bc6a7ecd0a90baea8e90c7907"><td class="mdescLeft">&#160;</td><td class="mdescRight">like <a class="el" href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853" title="Re-allocate memory to count elements of size bytes.">mi_reallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. <a href="#ga756f4b2bc6a7ecd0a90baea8e90c7907">More...</a><br /></td></tr>
<tr class="separator:ga756f4b2bc6a7ecd0a90baea8e90c7907"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<p><code>mi_</code> prefixed implementations of various allocation functions that use C++ semantics on out-of-memory, generally calling <code>std::get_new_handler</code> and raising a <code>std::bad_alloc</code> exception on failure. </p>
<p>Note: use the <code>mimalloc-new-delete.h</code> header to override the <em>new</em> and <em>delete</em> operators globally. The wrappers here are mostly for convience for library writers that need to interface with mimalloc from C++. </p>
<hr/><h2 class="groupheader">Data Structure Documentation</h2>
<a name="structmi__stl__allocator" id="structmi__stl__allocator"></a>
<h2 class="memtitle"><span class="permalink"><a href="#structmi__stl__allocator">&#9670;&nbsp;</a></span>mi_stl_allocator</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">struct mi_stl_allocator</td>
</tr>
</table>
</div><div class="memdoc">
<div class="textblock"><h3>template&lt;class T&gt;<br />
struct mi_stl_allocator&lt; T &gt;</h3>
<p><em>std::allocator</em> implementation for mimalloc for use in STL containers. </p>
<p>For example: </p><div class="fragment"><div class="line">std::vector&lt;int, mi_stl_allocator&lt;int&gt; &gt; vec;</div><div class="line">vec.push_back(1);</div><div class="line">vec.pop_back();</div></div><!-- fragment --> </div>
</div>
</div>
<h2 class="groupheader">Function Documentation</h2>
<a id="gaad048a9fce3d02c5909cd05c6ec24545"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gaad048a9fce3d02c5909cd05c6ec24545">&#9670;&nbsp;</a></span>mi_new()</h2>
<div class="memitem">
<div class="memproto">
<table class="mlabels">
<tr>
<td class="mlabels-left">
<table class="memname">
<tr>
<td class="memname">void* mi_new </td>
<td>(</td>
<td class="paramtype">std::size_t&#160;</td>
<td class="paramname"><em>n</em></td><td>)</td>
<td></td>
</tr>
</table>
</td>
<td class="mlabels-right">
<span class="mlabels"><span class="mlabel">noexcept</span></span> </td>
</tr>
</table>
</div><div class="memdoc">
<p>like <a class="el" href="group__malloc.html#ga3406e8b168bc74c8637b11571a6da83a" title="Allocate size bytes.">mi_malloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
</div>
</div>
<a id="gaef2c2bdb4f70857902d3c8903ac095f3"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gaef2c2bdb4f70857902d3c8903ac095f3">&#9670;&nbsp;</a></span>mi_new_aligned()</h2>
<div class="memitem">
<div class="memproto">
<table class="mlabels">
<tr>
<td class="mlabels-left">
<table class="memname">
<tr>
<td class="memname">void* mi_new_aligned </td>
<td>(</td>
<td class="paramtype">std::size_t&#160;</td>
<td class="paramname"><em>n</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">std::align_val_t&#160;</td>
<td class="paramname"><em>alignment</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</td>
<td class="mlabels-right">
<span class="mlabels"><span class="mlabel">noexcept</span></span> </td>
</tr>
</table>
</div><div class="memdoc">
<p>like <a class="el" href="group__aligned.html#ga68930196751fa2cca9e1fd0d71bade56" title="Allocate size bytes aligned by alignment.">mi_malloc_aligned()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
</div>
</div>
<a id="gab5e29558926d934c3f1cae8c815f942c"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gab5e29558926d934c3f1cae8c815f942c">&#9670;&nbsp;</a></span>mi_new_aligned_nothrow()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_new_aligned_nothrow </td>
<td>(</td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>n</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>like <code>mi_malloc_aligned</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure. </p>
</div>
</div>
<a id="gae7bc4f56cd57ed3359060ff4f38bda81"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gae7bc4f56cd57ed3359060ff4f38bda81">&#9670;&nbsp;</a></span>mi_new_n()</h2>
<div class="memitem">
<div class="memproto">
<table class="mlabels">
<tr>
<td class="mlabels-left">
<table class="memname">
<tr>
<td class="memname">void* mi_new_n </td>
<td>(</td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>count</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>size</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</td>
<td class="mlabels-right">
<span class="mlabels"><span class="mlabel">noexcept</span></span> </td>
</tr>
</table>
</div><div class="memdoc">
<p>like <a class="el" href="group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6" title="Allocate count elements of size bytes.">mi_mallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
</div>
</div>
<a id="gaeaded64eda71ed6b1d569d3e723abc4a"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gaeaded64eda71ed6b1d569d3e723abc4a">&#9670;&nbsp;</a></span>mi_new_nothrow()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_new_nothrow </td>
<td>(</td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>n</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>like <code>mi_malloc</code>, but when out of memory, use <code>std::get_new_handler</code> but return <em>NULL</em> on failure. </p>
</div>
</div>
<a id="gaab78a32f55149e9fbf432d5288e38e1e"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gaab78a32f55149e9fbf432d5288e38e1e">&#9670;&nbsp;</a></span>mi_new_realloc()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_new_realloc </td>
<td>(</td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newsize</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>like <a class="el" href="group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6" title="Re-allocate memory to newsize bytes.">mi_realloc()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
</div>
</div>
<a id="ga756f4b2bc6a7ecd0a90baea8e90c7907"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga756f4b2bc6a7ecd0a90baea8e90c7907">&#9670;&nbsp;</a></span>mi_new_reallocn()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_new_reallocn </td>
<td>(</td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newcount</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>size</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>like <a class="el" href="group__malloc.html#ga61d57b4144ba24fba5c1e9b956d13853" title="Re-allocate memory to count elements of size bytes.">mi_reallocn()</a>, but when out of memory, use <code>std::get_new_handler</code> and raise <code>std::bad_alloc</code> exception on failure. </p>
</div>
</div>
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.15 </li>
</ul>
</div>
</body>
</html>

11
docs/group__cpp.js Normal file
View file

@ -0,0 +1,11 @@
var group__cpp =
[
[ "mi_stl_allocator", "group__cpp.html#structmi__stl__allocator", null ],
[ "mi_new", "group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545", null ],
[ "mi_new_aligned", "group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3", null ],
[ "mi_new_aligned_nothrow", "group__cpp.html#gab5e29558926d934c3f1cae8c815f942c", null ],
[ "mi_new_n", "group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81", null ],
[ "mi_new_nothrow", "group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a", null ],
[ "mi_new_realloc", "group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e", null ],
[ "mi_new_reallocn", "group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907", null ]
];

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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -118,12 +118,15 @@ Macros</h2></td></tr>
</table><table class="memberdecls"> </table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a> <tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="typedef-members"></a>
Typedefs</h2></td></tr> Typedefs</h2></td></tr>
<tr class="memitem:ga22213691c3ce5ab4d91b24aff1023529"><td class="memItemLeft" align="right" valign="top">typedef void()&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga22213691c3ce5ab4d91b24aff1023529">mi_deferred_free_fun</a>(bool force, unsigned long long heartbeat)</td></tr> <tr class="memitem:ga299dae78d25ce112e384a98b7309c5be"><td class="memItemLeft" align="right" valign="top">typedef void()&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a>(bool force, unsigned long long heartbeat, void *arg)</td></tr>
<tr class="memdesc:ga22213691c3ce5ab4d91b24aff1023529"><td class="mdescLeft">&#160;</td><td class="mdescRight">Type of deferred free functions. <a href="#ga22213691c3ce5ab4d91b24aff1023529">More...</a><br /></td></tr> <tr class="memdesc:ga299dae78d25ce112e384a98b7309c5be"><td class="mdescLeft">&#160;</td><td class="mdescRight">Type of deferred free functions. <a href="#ga299dae78d25ce112e384a98b7309c5be">More...</a><br /></td></tr>
<tr class="separator:ga22213691c3ce5ab4d91b24aff1023529"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga299dae78d25ce112e384a98b7309c5be"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga2bed6d40b74591a67f81daea4b4a246f"><td class="memItemLeft" align="right" valign="top">typedef void()&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a>(const char *msg)</td></tr> <tr class="memitem:gad823d23444a4b77a40f66bf075a98a0c"><td class="memItemLeft" align="right" valign="top">typedef void()&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a>(const char *msg, void *arg)</td></tr>
<tr class="memdesc:ga2bed6d40b74591a67f81daea4b4a246f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Type of output functions. <a href="#ga2bed6d40b74591a67f81daea4b4a246f">More...</a><br /></td></tr> <tr class="memdesc:gad823d23444a4b77a40f66bf075a98a0c"><td class="mdescLeft">&#160;</td><td class="mdescRight">Type of output functions. <a href="#gad823d23444a4b77a40f66bf075a98a0c">More...</a><br /></td></tr>
<tr class="separator:ga2bed6d40b74591a67f81daea4b4a246f"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:gad823d23444a4b77a40f66bf075a98a0c"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga251d369cda3f1c2a955c555486ed90e5"><td class="memItemLeft" align="right" valign="top">typedef void()&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">mi_error_fun</a>(int err, void *arg)</td></tr>
<tr class="memdesc:ga251d369cda3f1c2a955c555486ed90e5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Type of error callback functions. <a href="#ga251d369cda3f1c2a955c555486ed90e5">More...</a><br /></td></tr>
<tr class="separator:ga251d369cda3f1c2a955c555486ed90e5"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls"> </table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a> <tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
Functions</h2></td></tr> Functions</h2></td></tr>
@ -142,9 +145,12 @@ Functions</h2></td></tr>
<tr class="memitem:ga421430e2226d7d468529cec457396756"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga421430e2226d7d468529cec457396756">mi_collect</a> (bool force)</td></tr> <tr class="memitem:ga421430e2226d7d468529cec457396756"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga421430e2226d7d468529cec457396756">mi_collect</a> (bool force)</td></tr>
<tr class="memdesc:ga421430e2226d7d468529cec457396756"><td class="mdescLeft">&#160;</td><td class="mdescRight">Eagerly free memory. <a href="#ga421430e2226d7d468529cec457396756">More...</a><br /></td></tr> <tr class="memdesc:ga421430e2226d7d468529cec457396756"><td class="mdescLeft">&#160;</td><td class="mdescRight">Eagerly free memory. <a href="#ga421430e2226d7d468529cec457396756">More...</a><br /></td></tr>
<tr class="separator:ga421430e2226d7d468529cec457396756"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga421430e2226d7d468529cec457396756"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga8ca07ccff283956d71f48272f4fd5c01"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga8ca07ccff283956d71f48272f4fd5c01">mi_stats_print</a> (<a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> *out)</td></tr> <tr class="memitem:ga2d126e5c62d3badc35445e5d84166df2"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga2d126e5c62d3badc35445e5d84166df2">mi_stats_print</a> (void *out)</td></tr>
<tr class="memdesc:ga8ca07ccff283956d71f48272f4fd5c01"><td class="mdescLeft">&#160;</td><td class="mdescRight">Print the main statistics. <a href="#ga8ca07ccff283956d71f48272f4fd5c01">More...</a><br /></td></tr> <tr class="memdesc:ga2d126e5c62d3badc35445e5d84166df2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Print the main statistics. <a href="#ga2d126e5c62d3badc35445e5d84166df2">More...</a><br /></td></tr>
<tr class="separator:ga8ca07ccff283956d71f48272f4fd5c01"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga2d126e5c62d3badc35445e5d84166df2"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga256cc6f13a142deabbadd954a217e228"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga256cc6f13a142deabbadd954a217e228">mi_stats_print</a> (<a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *out, void *arg)</td></tr>
<tr class="memdesc:ga256cc6f13a142deabbadd954a217e228"><td class="mdescLeft">&#160;</td><td class="mdescRight">Print the main statistics. <a href="#ga256cc6f13a142deabbadd954a217e228">More...</a><br /></td></tr>
<tr class="separator:ga256cc6f13a142deabbadd954a217e228"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99">mi_stats_reset</a> (void)</td></tr> <tr class="memitem:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99">mi_stats_reset</a> (void)</td></tr>
<tr class="memdesc:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reset statistics. <a href="#ga3bb8468b8cfcc6e2a61d98aee85c5f99">More...</a><br /></td></tr> <tr class="memdesc:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reset statistics. <a href="#ga3bb8468b8cfcc6e2a61d98aee85c5f99">More...</a><br /></td></tr>
<tr class="separator:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga3bb8468b8cfcc6e2a61d98aee85c5f99"><td class="memSeparator" colspan="2">&#160;</td></tr>
@ -157,21 +163,27 @@ Functions</h2></td></tr>
<tr class="memitem:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf">mi_thread_done</a> (void)</td></tr> <tr class="memitem:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf">mi_thread_done</a> (void)</td></tr>
<tr class="memdesc:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="mdescLeft">&#160;</td><td class="mdescRight">Uninitialize mimalloc on a thread. <a href="#ga0ae4581e85453456a0d658b2b98bf7bf">More...</a><br /></td></tr> <tr class="memdesc:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="mdescLeft">&#160;</td><td class="mdescRight">Uninitialize mimalloc on a thread. <a href="#ga0ae4581e85453456a0d658b2b98bf7bf">More...</a><br /></td></tr>
<tr class="separator:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga0ae4581e85453456a0d658b2b98bf7bf"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga489670a15d1a257ab4639e645ee4612a"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga489670a15d1a257ab4639e645ee4612a">mi_thread_stats_print</a> (<a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> *out)</td></tr> <tr class="memitem:gab1dac8476c46cb9eecab767eb40c1525"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gab1dac8476c46cb9eecab767eb40c1525">mi_thread_stats_print_out</a> (<a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *out, void *arg)</td></tr>
<tr class="memdesc:ga489670a15d1a257ab4639e645ee4612a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Print out heap statistics for this thread. <a href="#ga489670a15d1a257ab4639e645ee4612a">More...</a><br /></td></tr> <tr class="memdesc:gab1dac8476c46cb9eecab767eb40c1525"><td class="mdescLeft">&#160;</td><td class="mdescRight">Print out heap statistics for this thread. <a href="#gab1dac8476c46cb9eecab767eb40c1525">More...</a><br /></td></tr>
<tr class="separator:ga489670a15d1a257ab4639e645ee4612a"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:gab1dac8476c46cb9eecab767eb40c1525"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga24dc9cc6fca8daa2aa30aa8025467ce2"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2">mi_register_deferred_free</a> (<a class="el" href="group__extended.html#ga22213691c3ce5ab4d91b24aff1023529">mi_deferred_free_fun</a> *deferred_free)</td></tr> <tr class="memitem:ga3460a6ca91af97be4058f523d3cb8ece"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece">mi_register_deferred_free</a> (<a class="el" href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a> *deferred_free, void *arg)</td></tr>
<tr class="memdesc:ga24dc9cc6fca8daa2aa30aa8025467ce2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Register a deferred free function. <a href="#ga24dc9cc6fca8daa2aa30aa8025467ce2">More...</a><br /></td></tr> <tr class="memdesc:ga3460a6ca91af97be4058f523d3cb8ece"><td class="mdescLeft">&#160;</td><td class="mdescRight">Register a deferred free function. <a href="#ga3460a6ca91af97be4058f523d3cb8ece">More...</a><br /></td></tr>
<tr class="separator:ga24dc9cc6fca8daa2aa30aa8025467ce2"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga3460a6ca91af97be4058f523d3cb8ece"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga84a0c8b401e42eb5b1bce156852f44c5"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5">mi_register_output</a> (<a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> *out) mi_attr_noexcept</td></tr> <tr class="memitem:gae5b17ff027cd2150b43a33040250cf3f"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gae5b17ff027cd2150b43a33040250cf3f">mi_register_output</a> (<a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *out, void *arg)</td></tr>
<tr class="memdesc:ga84a0c8b401e42eb5b1bce156852f44c5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Register an output function. <a href="#ga84a0c8b401e42eb5b1bce156852f44c5">More...</a><br /></td></tr> <tr class="memdesc:gae5b17ff027cd2150b43a33040250cf3f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Register an output function. <a href="#gae5b17ff027cd2150b43a33040250cf3f">More...</a><br /></td></tr>
<tr class="separator:ga84a0c8b401e42eb5b1bce156852f44c5"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:gae5b17ff027cd2150b43a33040250cf3f"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaa1d55e0e894be240827e5d87ec3a1f45"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45">mi_register_error</a> (<a class="el" href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">mi_error_fun</a> *errfun, void *arg)</td></tr>
<tr class="memdesc:gaa1d55e0e894be240827e5d87ec3a1f45"><td class="mdescLeft">&#160;</td><td class="mdescRight">Register an error callback function. <a href="#gaa1d55e0e894be240827e5d87ec3a1f45">More...</a><br /></td></tr>
<tr class="separator:gaa1d55e0e894be240827e5d87ec3a1f45"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6">mi_is_in_heap_region</a> (const void *p)</td></tr> <tr class="memitem:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6">mi_is_in_heap_region</a> (const void *p)</td></tr>
<tr class="memdesc:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Is a pointer part of our heap? <a href="#ga5f071b10d4df1c3658e04e7fd67a94e6">More...</a><br /></td></tr> <tr class="memdesc:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Is a pointer part of our heap? <a href="#ga5f071b10d4df1c3658e04e7fd67a94e6">More...</a><br /></td></tr>
<tr class="separator:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga5f071b10d4df1c3658e04e7fd67a94e6"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga2664f36a2dd557741c429cb799f04641"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga2664f36a2dd557741c429cb799f04641">mi_reserve_huge_os_pages</a> (size_t pages, double max_secs, size_t *pages_reserved)</td></tr> <tr class="memitem:ga3132f521fb756fc0e8ec0b74fb58df50"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50">mi_reserve_huge_os_pages_interleave</a> (size_t pages, size_t numa_nodes, size_t timeout_msecs)</td></tr>
<tr class="memdesc:ga2664f36a2dd557741c429cb799f04641"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reserve <em>pages</em> of huge OS pages (1GiB) but stops after at most <code>max_secs</code> seconds. <a href="#ga2664f36a2dd557741c429cb799f04641">More...</a><br /></td></tr> <tr class="memdesc:ga3132f521fb756fc0e8ec0b74fb58df50"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reserve <em>pages</em> of huge OS pages (1GiB) evenly divided over <em>numa_nodes</em> nodes, but stops after at most <code>timeout_msecs</code> seconds. <a href="#ga3132f521fb756fc0e8ec0b74fb58df50">More...</a><br /></td></tr>
<tr class="separator:ga2664f36a2dd557741c429cb799f04641"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga3132f521fb756fc0e8ec0b74fb58df50"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga7795a13d20087447281858d2c771cca1"><td class="memItemLeft" align="right" valign="top">int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#ga7795a13d20087447281858d2c771cca1">mi_reserve_huge_os_pages_at</a> (size_t pages, int numa_node, size_t timeout_msecs)</td></tr>
<tr class="memdesc:ga7795a13d20087447281858d2c771cca1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Reserve <em>pages</em> of huge OS pages (1GiB) at a specific <em>numa_node</em>, but stops after at most <code>timeout_msecs</code> seconds. <a href="#ga7795a13d20087447281858d2c771cca1">More...</a><br /></td></tr>
<tr class="separator:ga7795a13d20087447281858d2c771cca1"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaad25050b19f30cd79397b227e0157a3f"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gaad25050b19f30cd79397b227e0157a3f">mi_is_redirected</a> ()</td></tr> <tr class="memitem:gaad25050b19f30cd79397b227e0157a3f"><td class="memItemLeft" align="right" valign="top">bool&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__extended.html#gaad25050b19f30cd79397b227e0157a3f">mi_is_redirected</a> ()</td></tr>
<tr class="memdesc:gaad25050b19f30cd79397b227e0157a3f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Is the C runtime <em>malloc</em> API redirected? <a href="#gaad25050b19f30cd79397b227e0157a3f">More...</a><br /></td></tr> <tr class="memdesc:gaad25050b19f30cd79397b227e0157a3f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Is the C runtime <em>malloc</em> API redirected? <a href="#gaad25050b19f30cd79397b227e0157a3f">More...</a><br /></td></tr>
<tr class="separator:gaad25050b19f30cd79397b227e0157a3f"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:gaad25050b19f30cd79397b227e0157a3f"><td class="memSeparator" colspan="2">&#160;</td></tr>
@ -196,14 +208,14 @@ Functions</h2></td></tr>
</div> </div>
</div> </div>
<h2 class="groupheader">Typedef Documentation</h2> <h2 class="groupheader">Typedef Documentation</h2>
<a id="ga22213691c3ce5ab4d91b24aff1023529"></a> <a id="ga299dae78d25ce112e384a98b7309c5be"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga22213691c3ce5ab4d91b24aff1023529">&#9670;&nbsp;</a></span>mi_deferred_free_fun</h2> <h2 class="memtitle"><span class="permalink"><a href="#ga299dae78d25ce112e384a98b7309c5be">&#9670;&nbsp;</a></span>mi_deferred_free_fun</h2>
<div class="memitem"> <div class="memitem">
<div class="memproto"> <div class="memproto">
<table class="memname"> <table class="memname">
<tr> <tr>
<td class="memname">typedef void() mi_deferred_free_fun(bool force, unsigned long long heartbeat)</td> <td class="memname">typedef void() mi_deferred_free_fun(bool force, unsigned long long heartbeat, void *arg)</td>
</tr> </tr>
</table> </table>
</div><div class="memdoc"> </div><div class="memdoc">
@ -213,21 +225,46 @@ Functions</h2></td></tr>
<table class="params"> <table class="params">
<tr><td class="paramname">force</td><td>If <em>true</em> all outstanding items should be freed. </td></tr> <tr><td class="paramname">force</td><td>If <em>true</em> all outstanding items should be freed. </td></tr>
<tr><td class="paramname">heartbeat</td><td>A monotonically increasing count. </td></tr> <tr><td class="paramname">heartbeat</td><td>A monotonically increasing count. </td></tr>
<tr><td class="paramname">arg</td><td>Argument that was passed at registration to hold extra state.</td></tr>
</table> </table>
</dd> </dd>
</dl> </dl>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2" title="Register a deferred free function.">mi_register_deferred_free</a> </dd></dl> <dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece" title="Register a deferred free function.">mi_register_deferred_free</a> </dd></dl>
</div> </div>
</div> </div>
<a id="ga2bed6d40b74591a67f81daea4b4a246f"></a> <a id="ga251d369cda3f1c2a955c555486ed90e5"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga2bed6d40b74591a67f81daea4b4a246f">&#9670;&nbsp;</a></span>mi_output_fun</h2> <h2 class="memtitle"><span class="permalink"><a href="#ga251d369cda3f1c2a955c555486ed90e5">&#9670;&nbsp;</a></span>mi_error_fun</h2>
<div class="memitem"> <div class="memitem">
<div class="memproto"> <div class="memproto">
<table class="memname"> <table class="memname">
<tr> <tr>
<td class="memname">typedef void() mi_output_fun(const char *msg)</td> <td class="memname">typedef void() mi_error_fun(int err, void *arg)</td>
</tr>
</table>
</div><div class="memdoc">
<p>Type of error callback functions. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">err</td><td>Error code (see <a class="el" href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45" title="Register an error callback function.">mi_register_error()</a> for a complete list). </td></tr>
<tr><td class="paramname">arg</td><td>Argument that was passed at registration to hold extra state.</td></tr>
</table>
</dd>
</dl>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45" title="Register an error callback function.">mi_register_error()</a> </dd></dl>
</div>
</div>
<a id="gad823d23444a4b77a40f66bf075a98a0c"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gad823d23444a4b77a40f66bf075a98a0c">&#9670;&nbsp;</a></span>mi_output_fun</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">typedef void() mi_output_fun(const char *msg, void *arg)</td>
</tr> </tr>
</table> </table>
</div><div class="memdoc"> </div><div class="memdoc">
@ -236,10 +273,11 @@ Functions</h2></td></tr>
<dl class="params"><dt>Parameters</dt><dd> <dl class="params"><dt>Parameters</dt><dd>
<table class="params"> <table class="params">
<tr><td class="paramname">msg</td><td>Message to output. </td></tr> <tr><td class="paramname">msg</td><td>Message to output. </td></tr>
<tr><td class="paramname">arg</td><td>Argument that was passed at registration to hold extra state.</td></tr>
</table> </table>
</dd> </dd>
</dl> </dl>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5" title="Register an output function.">mi_register_output()</a> </dd></dl> <dl class="section see"><dt>See also</dt><dd><a class="el" href="group__extended.html#gae5b17ff027cd2150b43a33040250cf3f" title="Register an output function.">mi_register_output()</a> </dd></dl>
</div> </div>
</div> </div>
@ -375,8 +413,8 @@ Functions</h2></td></tr>
</div> </div>
</div> </div>
<a id="ga24dc9cc6fca8daa2aa30aa8025467ce2"></a> <a id="ga3460a6ca91af97be4058f523d3cb8ece"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga24dc9cc6fca8daa2aa30aa8025467ce2">&#9670;&nbsp;</a></span>mi_register_deferred_free()</h2> <h2 class="memtitle"><span class="permalink"><a href="#ga3460a6ca91af97be4058f523d3cb8ece">&#9670;&nbsp;</a></span>mi_register_deferred_free()</h2>
<div class="memitem"> <div class="memitem">
<div class="memproto"> <div class="memproto">
@ -384,74 +422,14 @@ Functions</h2></td></tr>
<tr> <tr>
<td class="memname">void mi_register_deferred_free </td> <td class="memname">void mi_register_deferred_free </td>
<td>(</td> <td>(</td>
<td class="paramtype"><a class="el" href="group__extended.html#ga22213691c3ce5ab4d91b24aff1023529">mi_deferred_free_fun</a> *&#160;</td> <td class="paramtype"><a class="el" href="group__extended.html#ga299dae78d25ce112e384a98b7309c5be">mi_deferred_free_fun</a> *&#160;</td>
<td class="paramname"><em>deferred_free</em></td><td>)</td> <td class="paramname"><em>deferred_free</em>, </td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Register a deferred free function. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">deferred_free</td><td>Address of a deferred free-ing function or <em>NULL</em> to unregister.</td></tr>
</table>
</dd>
</dl>
<p>Some runtime systems use deferred free-ing, for example when using reference counting to limit the worst case free time. Such systems can register (re-entrant) deferred free function to free more memory on demand. When the <em>force</em> parameter is <em>true</em> all possible memory should be freed. The per-thread <em>heartbeat</em> parameter is monotonically increasing and guaranteed to be deterministic if the program allocates deterministically. The <em>deferred_free</em> function is guaranteed to be called deterministically after some number of allocations (regardless of freeing or available free memory). At most one <em>deferred_free</em> function can be active. </p>
</div>
</div>
<a id="ga84a0c8b401e42eb5b1bce156852f44c5"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga84a0c8b401e42eb5b1bce156852f44c5">&#9670;&nbsp;</a></span>mi_register_output()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void mi_register_output </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> *&#160;</td>
<td class="paramname"><em>out</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Register an output function. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">out</td><td>The output function, use <code>NULL</code> to output to stdout.</td></tr>
</table>
</dd>
</dl>
<p>The <code>out</code> function is called to output any information from mimalloc, like verbose or warning messages. </p>
</div>
</div>
<a id="ga2664f36a2dd557741c429cb799f04641"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga2664f36a2dd557741c429cb799f04641">&#9670;&nbsp;</a></span>mi_reserve_huge_os_pages()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">int mi_reserve_huge_os_pages </td>
<td>(</td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>pages</em>, </td>
</tr> </tr>
<tr> <tr>
<td class="paramkey"></td> <td class="paramkey"></td>
<td></td> <td></td>
<td class="paramtype">double&#160;</td> <td class="paramtype">void *&#160;</td>
<td class="paramname"><em>max_secs</em>, </td> <td class="paramname"><em>arg</em>&#160;</td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t *&#160;</td>
<td class="paramname"><em>pages_reserved</em>&#160;</td>
</tr> </tr>
<tr> <tr>
<td></td> <td></td>
@ -461,17 +439,189 @@ Functions</h2></td></tr>
</table> </table>
</div><div class="memdoc"> </div><div class="memdoc">
<p>Reserve <em>pages</em> of huge OS pages (1GiB) but stops after at most <code>max_secs</code> seconds. </p> <p>Register a deferred free function. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">deferred_free</td><td>Address of a deferred free-ing function or <em>NULL</em> to unregister. </td></tr>
<tr><td class="paramname">arg</td><td>Argument that will be passed on to the deferred free function.</td></tr>
</table>
</dd>
</dl>
<p>Some runtime systems use deferred free-ing, for example when using reference counting to limit the worst case free time. Such systems can register (re-entrant) deferred free function to free more memory on demand. When the <em>force</em> parameter is <em>true</em> all possible memory should be freed. The per-thread <em>heartbeat</em> parameter is monotonically increasing and guaranteed to be deterministic if the program allocates deterministically. The <em>deferred_free</em> function is guaranteed to be called deterministically after some number of allocations (regardless of freeing or available free memory). At most one <em>deferred_free</em> function can be active. </p>
</div>
</div>
<a id="gaa1d55e0e894be240827e5d87ec3a1f45"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gaa1d55e0e894be240827e5d87ec3a1f45">&#9670;&nbsp;</a></span>mi_register_error()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void mi_register_error </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__extended.html#ga251d369cda3f1c2a955c555486ed90e5">mi_error_fun</a> *&#160;</td>
<td class="paramname"><em>errfun</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>arg</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Register an error callback function. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">errfun</td><td>The error function that is called on an error (use <em>NULL</em> for default) </td></tr>
<tr><td class="paramname">arg</td><td>Extra argument that will be passed on to the error function.</td></tr>
</table>
</dd>
</dl>
<p>The <em>errfun</em> function is called on an error in mimalloc after emitting an error message (through the output function). It as always legal to just return from the <em>errfun</em> function in which case allocation functions generally return <em>NULL</em> or ignore the condition. The default function only calls abort() when compiled in secure mode with an <em>EFAULT</em> error. The possible error codes are:</p><ul>
<li><em>EAGAIN:</em> Double free was detected (only in debug and secure mode).</li>
<li><em>EFAULT:</em> Corrupted free list or meta-data was detected (only in debug and secure mode).</li>
<li><em>ENOMEM:</em> Not enough memory available to satisfy the request.</li>
<li><em>EOVERFLOW:</em> Too large a request, for example in <a class="el" href="group__malloc.html#ga97fedb4f7107c592fd7f0f0a8949a57d" title="Allocate zero-initialized count elements of size bytes.">mi_calloc()</a>, the <em>count</em> and <em>size</em> parameters are too large.</li>
<li><em>EINVAL:</em> Trying to free or re-allocate an invalid pointer. </li>
</ul>
</div>
</div>
<a id="gae5b17ff027cd2150b43a33040250cf3f"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gae5b17ff027cd2150b43a33040250cf3f">&#9670;&nbsp;</a></span>mi_register_output()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void mi_register_output </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *&#160;</td>
<td class="paramname"><em>out</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>arg</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Register an output function. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">out</td><td>The output function, use <code>NULL</code> to output to stderr. </td></tr>
<tr><td class="paramname">arg</td><td>Argument that will be passed on to the output function.</td></tr>
</table>
</dd>
</dl>
<p>The <code>out</code> function is called to output any information from mimalloc, like verbose or warning messages. </p>
</div>
</div>
<a id="ga7795a13d20087447281858d2c771cca1"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga7795a13d20087447281858d2c771cca1">&#9670;&nbsp;</a></span>mi_reserve_huge_os_pages_at()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">int mi_reserve_huge_os_pages_at </td>
<td>(</td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>pages</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">int&#160;</td>
<td class="paramname"><em>numa_node</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>timeout_msecs</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Reserve <em>pages</em> of huge OS pages (1GiB) at a specific <em>numa_node</em>, but stops after at most <code>timeout_msecs</code> seconds. </p>
<dl class="params"><dt>Parameters</dt><dd> <dl class="params"><dt>Parameters</dt><dd>
<table class="params"> <table class="params">
<tr><td class="paramname">pages</td><td>The number of 1GiB pages to reserve. </td></tr> <tr><td class="paramname">pages</td><td>The number of 1GiB pages to reserve. </td></tr>
<tr><td class="paramname">max_secs</td><td>Maximum number of seconds to try reserving. </td></tr> <tr><td class="paramname">numa_node</td><td>The NUMA node where the memory is reserved (start at 0). </td></tr>
<tr><td class="paramname">pages_reserved</td><td>If not <em>NULL</em>, it is set to the actual number of pages that were reserved. </td></tr> <tr><td class="paramname">timeout_msecs</td><td>Maximum number of milli-seconds to try reserving, or 0 for no timeout. </td></tr>
</table> </table>
</dd> </dd>
</dl> </dl>
<dl class="section return"><dt>Returns</dt><dd>0 if successfull, <em>ENOMEM</em> if running out of memory, or <em>ETIMEDOUT</em> if timed out.</dd></dl> <dl class="section return"><dt>Returns</dt><dd>0 if successfull, <em>ENOMEM</em> if running out of memory, or <em>ETIMEDOUT</em> if timed out.</dd></dl>
<p>The reserved memory is used by mimalloc to satisfy allocations. May quit before <em>max_secs</em> are expired if it estimates it will take more than 1.5 times <em>max_secs</em>. The time limit is needed because on some operating systems it can take a long time to reserve contiguous memory if the physical memory is fragmented. </p> <p>The reserved memory is used by mimalloc to satisfy allocations. May quit before <em>timeout_msecs</em> are expired if it estimates it will take more than 1.5 times <em>timeout_msecs</em>. The time limit is needed because on some operating systems it can take a long time to reserve contiguous memory if the physical memory is fragmented. </p>
</div>
</div>
<a id="ga3132f521fb756fc0e8ec0b74fb58df50"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga3132f521fb756fc0e8ec0b74fb58df50">&#9670;&nbsp;</a></span>mi_reserve_huge_os_pages_interleave()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">int mi_reserve_huge_os_pages_interleave </td>
<td>(</td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>pages</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>numa_nodes</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>timeout_msecs</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Reserve <em>pages</em> of huge OS pages (1GiB) evenly divided over <em>numa_nodes</em> nodes, but stops after at most <code>timeout_msecs</code> seconds. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">pages</td><td>The number of 1GiB pages to reserve. </td></tr>
<tr><td class="paramname">numa_nodes</td><td>The number of nodes do evenly divide the pages over, or 0 for using the actual number of NUMA nodes. </td></tr>
<tr><td class="paramname">timeout_msecs</td><td>Maximum number of milli-seconds to try reserving, or 0 for no timeout. </td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>0 if successfull, <em>ENOMEM</em> if running out of memory, or <em>ETIMEDOUT</em> if timed out.</dd></dl>
<p>The reserved memory is used by mimalloc to satisfy allocations. May quit before <em>timeout_msecs</em> are expired if it estimates it will take more than 1.5 times <em>timeout_msecs</em>. The time limit is needed because on some operating systems it can take a long time to reserve contiguous memory if the physical memory is fragmented. </p>
</div> </div>
</div> </div>
@ -495,8 +645,8 @@ Functions</h2></td></tr>
</div> </div>
</div> </div>
<a id="ga8ca07ccff283956d71f48272f4fd5c01"></a> <a id="ga2d126e5c62d3badc35445e5d84166df2"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga8ca07ccff283956d71f48272f4fd5c01">&#9670;&nbsp;</a></span>mi_stats_print()</h2> <h2 class="memtitle"><span class="permalink"><a href="#ga2d126e5c62d3badc35445e5d84166df2">&#9670;&nbsp;</a></span>mi_stats_print() <span class="overload">[1/2]</span></h2>
<div class="memitem"> <div class="memitem">
<div class="memproto"> <div class="memproto">
@ -504,7 +654,7 @@ Functions</h2></td></tr>
<tr> <tr>
<td class="memname">void mi_stats_print </td> <td class="memname">void mi_stats_print </td>
<td>(</td> <td>(</td>
<td class="paramtype"><a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> *&#160;</td> <td class="paramtype">void *&#160;</td>
<td class="paramname"><em>out</em></td><td>)</td> <td class="paramname"><em>out</em></td><td>)</td>
<td></td> <td></td>
</tr> </tr>
@ -514,7 +664,45 @@ Functions</h2></td></tr>
<p>Print the main statistics. </p> <p>Print the main statistics. </p>
<dl class="params"><dt>Parameters</dt><dd> <dl class="params"><dt>Parameters</dt><dd>
<table class="params"> <table class="params">
<tr><td class="paramname">out</td><td>Output function. Use <em>NULL</em> for outputting to <em>stderr</em>.</td></tr> <tr><td class="paramname">out</td><td>Ignored, outputs to the registered output function or stderr by default.</td></tr>
</table>
</dd>
</dl>
<p>Most detailed when using a debug build. </p>
</div>
</div>
<a id="ga256cc6f13a142deabbadd954a217e228"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga256cc6f13a142deabbadd954a217e228">&#9670;&nbsp;</a></span>mi_stats_print() <span class="overload">[2/2]</span></h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void mi_stats_print </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *&#160;</td>
<td class="paramname"><em>out</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>arg</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Print the main statistics. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">out</td><td>An output function or <em>NULL</em> for the default. </td></tr>
<tr><td class="paramname">arg</td><td>Optional argument passed to <em>out</em> (if not <em>NULL</em>)</td></tr>
</table> </table>
</dd> </dd>
</dl> </dl>
@ -584,18 +772,28 @@ Functions</h2></td></tr>
</div> </div>
</div> </div>
<a id="ga489670a15d1a257ab4639e645ee4612a"></a> <a id="gab1dac8476c46cb9eecab767eb40c1525"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga489670a15d1a257ab4639e645ee4612a">&#9670;&nbsp;</a></span>mi_thread_stats_print()</h2> <h2 class="memtitle"><span class="permalink"><a href="#gab1dac8476c46cb9eecab767eb40c1525">&#9670;&nbsp;</a></span>mi_thread_stats_print_out()</h2>
<div class="memitem"> <div class="memitem">
<div class="memproto"> <div class="memproto">
<table class="memname"> <table class="memname">
<tr> <tr>
<td class="memname">void mi_thread_stats_print </td> <td class="memname">void mi_thread_stats_print_out </td>
<td>(</td> <td>(</td>
<td class="paramtype"><a class="el" href="group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f">mi_output_fun</a> *&#160;</td> <td class="paramtype"><a class="el" href="group__extended.html#gad823d23444a4b77a40f66bf075a98a0c">mi_output_fun</a> *&#160;</td>
<td class="paramname"><em>out</em></td><td>)</td> <td class="paramname"><em>out</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td> <td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>arg</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr> </tr>
</table> </table>
</div><div class="memdoc"> </div><div class="memdoc">
@ -603,7 +801,8 @@ Functions</h2></td></tr>
<p>Print out heap statistics for this thread. </p> <p>Print out heap statistics for this thread. </p>
<dl class="params"><dt>Parameters</dt><dd> <dl class="params"><dt>Parameters</dt><dd>
<table class="params"> <table class="params">
<tr><td class="paramname">out</td><td>Output function. Use <em>NULL</em> for outputting to <em>stderr</em>.</td></tr> <tr><td class="paramname">out</td><td>An output function or <em>NULL</em> for the default. </td></tr>
<tr><td class="paramname">arg</td><td>Optional argument passed to <em>out</em> (if not <em>NULL</em>)</td></tr>
</table> </table>
</dd> </dd>
</dl> </dl>

View file

@ -1,22 +1,26 @@
var group__extended = var group__extended =
[ [
[ "MI_SMALL_SIZE_MAX", "group__extended.html#ga1ea64283508718d9d645c38efc2f4305", null ], [ "MI_SMALL_SIZE_MAX", "group__extended.html#ga1ea64283508718d9d645c38efc2f4305", null ],
[ "mi_deferred_free_fun", "group__extended.html#ga22213691c3ce5ab4d91b24aff1023529", null ], [ "mi_deferred_free_fun", "group__extended.html#ga299dae78d25ce112e384a98b7309c5be", null ],
[ "mi_output_fun", "group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f", null ], [ "mi_error_fun", "group__extended.html#ga251d369cda3f1c2a955c555486ed90e5", null ],
[ "mi_output_fun", "group__extended.html#gad823d23444a4b77a40f66bf075a98a0c", null ],
[ "mi_collect", "group__extended.html#ga421430e2226d7d468529cec457396756", null ], [ "mi_collect", "group__extended.html#ga421430e2226d7d468529cec457396756", null ],
[ "mi_good_size", "group__extended.html#gac057927cd06c854b45fe7847e921bd47", null ], [ "mi_good_size", "group__extended.html#gac057927cd06c854b45fe7847e921bd47", null ],
[ "mi_is_in_heap_region", "group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6", null ], [ "mi_is_in_heap_region", "group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6", null ],
[ "mi_is_redirected", "group__extended.html#gaad25050b19f30cd79397b227e0157a3f", null ], [ "mi_is_redirected", "group__extended.html#gaad25050b19f30cd79397b227e0157a3f", null ],
[ "mi_malloc_small", "group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99", null ], [ "mi_malloc_small", "group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99", null ],
[ "mi_register_deferred_free", "group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2", null ], [ "mi_register_deferred_free", "group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece", null ],
[ "mi_register_output", "group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5", null ], [ "mi_register_error", "group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45", null ],
[ "mi_reserve_huge_os_pages", "group__extended.html#ga2664f36a2dd557741c429cb799f04641", null ], [ "mi_register_output", "group__extended.html#gae5b17ff027cd2150b43a33040250cf3f", null ],
[ "mi_reserve_huge_os_pages_at", "group__extended.html#ga7795a13d20087447281858d2c771cca1", null ],
[ "mi_reserve_huge_os_pages_interleave", "group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50", null ],
[ "mi_stats_merge", "group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1", null ], [ "mi_stats_merge", "group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1", null ],
[ "mi_stats_print", "group__extended.html#ga8ca07ccff283956d71f48272f4fd5c01", null ], [ "mi_stats_print", "group__extended.html#ga2d126e5c62d3badc35445e5d84166df2", null ],
[ "mi_stats_print", "group__extended.html#ga256cc6f13a142deabbadd954a217e228", null ],
[ "mi_stats_reset", "group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99", null ], [ "mi_stats_reset", "group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99", null ],
[ "mi_thread_done", "group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf", null ], [ "mi_thread_done", "group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf", null ],
[ "mi_thread_init", "group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17", null ], [ "mi_thread_init", "group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17", null ],
[ "mi_thread_stats_print", "group__extended.html#ga489670a15d1a257ab4639e645ee4612a", null ], [ "mi_thread_stats_print_out", "group__extended.html#gab1dac8476c46cb9eecab767eb40c1525", null ],
[ "mi_usable_size", "group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee", null ], [ "mi_usable_size", "group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee", null ],
[ "mi_zalloc_small", "group__extended.html#ga220f29f40a44404b0061c15bc1c31152", null ] [ "mi_zalloc_small", "group__extended.html#ga220f29f40a44404b0061c15bc1c31152", null ]
]; ];

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.0</span> &#160;<span id="projectnumber">1.4</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.0</span> &#160;<span id="projectnumber">1.4</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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -123,11 +123,12 @@ Enumerations</h2></td></tr>
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1">mi_option_segment_cache</a>, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1">mi_option_segment_cache</a>,
<br /> <br />
&#160;&#160;<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968">mi_option_page_reset</a>, &#160;&#160;<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968">mi_option_page_reset</a>,
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07">mi_option_cache_reset</a>, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d">mi_option_segment_reset</a>,
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536">mi_option_reset_decommits</a>, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5">mi_option_reset_delay</a>,
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c">mi_option_eager_commit_delay</a>, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74">mi_option_use_numa_nodes</a>,
<br /> <br />
&#160;&#160;<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d">mi_option_segment_reset</a>, &#160;&#160;<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536">mi_option_reset_decommits</a>,
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c">mi_option_eager_commit_delay</a>,
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf">mi_option_os_tag</a>, <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf">mi_option_os_tag</a>,
<a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a">_mi_option_last</a> <a class="el" href="group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a">_mi_option_last</a>
<br /> <br />
@ -183,16 +184,18 @@ Functions</h2></td></tr>
</td></tr> </td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1"></a>mi_option_segment_cache&#160;</td><td class="fielddoc"><p>The number of segments per thread to keep cached. </p> <tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1"></a>mi_option_segment_cache&#160;</td><td class="fielddoc"><p>The number of segments per thread to keep cached. </p>
</td></tr> </td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968"></a>mi_option_page_reset&#160;</td><td class="fielddoc"><p>Reset page memory when it becomes free. </p> <tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968"></a>mi_option_page_reset&#160;</td><td class="fielddoc"><p>Reset page memory after <em>mi_option_reset_delay</em> milliseconds when it becomes free. </p>
</td></tr> </td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07"></a>mi_option_cache_reset&#160;</td><td class="fielddoc"><p>Reset segment memory when a segment is cached. </p> <tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d"></a>mi_option_segment_reset&#160;</td><td class="fielddoc"><p>Experimental. </p>
</td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5"></a>mi_option_reset_delay&#160;</td><td class="fielddoc"><p>Delay in milli-seconds before resetting a page (100ms by default) </p>
</td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74"></a>mi_option_use_numa_nodes&#160;</td><td class="fielddoc"><p>Pretend there are at most N NUMA nodes. </p>
</td></tr> </td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536"></a>mi_option_reset_decommits&#160;</td><td class="fielddoc"><p>Experimental. </p> <tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536"></a>mi_option_reset_decommits&#160;</td><td class="fielddoc"><p>Experimental. </p>
</td></tr> </td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c"></a>mi_option_eager_commit_delay&#160;</td><td class="fielddoc"><p>Experimental. </p> <tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c"></a>mi_option_eager_commit_delay&#160;</td><td class="fielddoc"><p>Experimental. </p>
</td></tr> </td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d"></a>mi_option_segment_reset&#160;</td><td class="fielddoc"><p>Experimental. </p>
</td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf"></a>mi_option_os_tag&#160;</td><td class="fielddoc"><p>OS tag to assign to mimalloc'd memory. </p> <tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf"></a>mi_option_os_tag&#160;</td><td class="fielddoc"><p>OS tag to assign to mimalloc'd memory. </p>
</td></tr> </td></tr>
<tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a"></a>_mi_option_last&#160;</td><td class="fielddoc"></td></tr> <tr><td class="fieldname"><a id="ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a"></a>_mi_option_last&#160;</td><td class="fielddoc"></td></tr>

View file

@ -10,10 +10,11 @@ var group__options =
[ "mi_option_reserve_huge_os_pages", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2", null ], [ "mi_option_reserve_huge_os_pages", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2", null ],
[ "mi_option_segment_cache", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1", null ], [ "mi_option_segment_cache", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1", null ],
[ "mi_option_page_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968", null ], [ "mi_option_page_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968", null ],
[ "mi_option_cache_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07", null ], [ "mi_option_segment_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d", null ],
[ "mi_option_reset_delay", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5", null ],
[ "mi_option_use_numa_nodes", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74", null ],
[ "mi_option_reset_decommits", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536", null ], [ "mi_option_reset_decommits", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536", null ],
[ "mi_option_eager_commit_delay", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c", null ], [ "mi_option_eager_commit_delay", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c", null ],
[ "mi_option_segment_reset", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d", null ],
[ "mi_option_os_tag", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf", null ], [ "mi_option_os_tag", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf", null ],
[ "_mi_option_last", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a", null ] [ "_mi_option_last", "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a", null ]
] ], ] ],

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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -137,18 +137,6 @@ Functions</h2></td></tr>
<tr class="separator:ga72e9d7ffb5fe94d69bc722c8506e27bc"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga72e9d7ffb5fe94d69bc722c8506e27bc"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga0d28d5cf61e6bfbb18c63092939fe5c9"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9">mi_free_aligned</a> (void *p, size_t alignment)</td></tr> <tr class="memitem:ga0d28d5cf61e6bfbb18c63092939fe5c9"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9">mi_free_aligned</a> (void *p, size_t alignment)</td></tr>
<tr class="separator:ga0d28d5cf61e6bfbb18c63092939fe5c9"><td class="memSeparator" colspan="2">&#160;</td></tr> <tr class="separator:ga0d28d5cf61e6bfbb18c63092939fe5c9"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaad048a9fce3d02c5909cd05c6ec24545"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gaad048a9fce3d02c5909cd05c6ec24545">mi_new</a> (std::size_t n) noexcept(false)</td></tr>
<tr class="memdesc:gaad048a9fce3d02c5909cd05c6ec24545"><td class="mdescLeft">&#160;</td><td class="mdescRight">raise <code>std::bad_alloc</code> exception on failure. <a href="#gaad048a9fce3d02c5909cd05c6ec24545">More...</a><br /></td></tr>
<tr class="separator:gaad048a9fce3d02c5909cd05c6ec24545"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaef2c2bdb4f70857902d3c8903ac095f3"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gaef2c2bdb4f70857902d3c8903ac095f3">mi_new_aligned</a> (std::size_t n, std::align_val_t alignment) noexcept(false)</td></tr>
<tr class="memdesc:gaef2c2bdb4f70857902d3c8903ac095f3"><td class="mdescLeft">&#160;</td><td class="mdescRight">raise <code>std::bad_alloc</code> exception on failure. <a href="#gaef2c2bdb4f70857902d3c8903ac095f3">More...</a><br /></td></tr>
<tr class="separator:gaef2c2bdb4f70857902d3c8903ac095f3"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaeaded64eda71ed6b1d569d3e723abc4a"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gaeaded64eda71ed6b1d569d3e723abc4a">mi_new_nothrow</a> (size_t n)</td></tr>
<tr class="memdesc:gaeaded64eda71ed6b1d569d3e723abc4a"><td class="mdescLeft">&#160;</td><td class="mdescRight">return <code>NULL</code> on failure. <a href="#gaeaded64eda71ed6b1d569d3e723abc4a">More...</a><br /></td></tr>
<tr class="separator:gaeaded64eda71ed6b1d569d3e723abc4a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gab5e29558926d934c3f1cae8c815f942c"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__posix.html#gab5e29558926d934c3f1cae8c815f942c">mi_new_aligned_nothrow</a> (size_t n, size_t alignment)</td></tr>
<tr class="memdesc:gab5e29558926d934c3f1cae8c815f942c"><td class="mdescLeft">&#160;</td><td class="mdescRight">return <code>NULL</code> on failure. <a href="#gab5e29558926d934c3f1cae8c815f942c">More...</a><br /></td></tr>
<tr class="separator:gab5e29558926d934c3f1cae8c815f942c"><td class="memSeparator" colspan="2">&#160;</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><code>mi_</code> prefixed implementations of various Posix, Unix, and C++ allocation functions. </p> <p><code>mi_</code> prefixed implementations of various Posix, Unix, and C++ allocation functions. </p>
@ -388,122 +376,6 @@ Functions</h2></td></tr>
</table> </table>
</div><div class="memdoc"> </div><div class="memdoc">
</div>
</div>
<a id="gaad048a9fce3d02c5909cd05c6ec24545"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gaad048a9fce3d02c5909cd05c6ec24545">&#9670;&nbsp;</a></span>mi_new()</h2>
<div class="memitem">
<div class="memproto">
<table class="mlabels">
<tr>
<td class="mlabels-left">
<table class="memname">
<tr>
<td class="memname">void* mi_new </td>
<td>(</td>
<td class="paramtype">std::size_t&#160;</td>
<td class="paramname"><em>n</em></td><td>)</td>
<td></td>
</tr>
</table>
</td>
<td class="mlabels-right">
<span class="mlabels"><span class="mlabel">noexcept</span></span> </td>
</tr>
</table>
</div><div class="memdoc">
<p>raise <code>std::bad_alloc</code> exception on failure. </p>
</div>
</div>
<a id="gaef2c2bdb4f70857902d3c8903ac095f3"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gaef2c2bdb4f70857902d3c8903ac095f3">&#9670;&nbsp;</a></span>mi_new_aligned()</h2>
<div class="memitem">
<div class="memproto">
<table class="mlabels">
<tr>
<td class="mlabels-left">
<table class="memname">
<tr>
<td class="memname">void* mi_new_aligned </td>
<td>(</td>
<td class="paramtype">std::size_t&#160;</td>
<td class="paramname"><em>n</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">std::align_val_t&#160;</td>
<td class="paramname"><em>alignment</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</td>
<td class="mlabels-right">
<span class="mlabels"><span class="mlabel">noexcept</span></span> </td>
</tr>
</table>
</div><div class="memdoc">
<p>raise <code>std::bad_alloc</code> exception on failure. </p>
</div>
</div>
<a id="gab5e29558926d934c3f1cae8c815f942c"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gab5e29558926d934c3f1cae8c815f942c">&#9670;&nbsp;</a></span>mi_new_aligned_nothrow()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_new_aligned_nothrow </td>
<td>(</td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>n</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
<p>return <code>NULL</code> on failure. </p>
</div>
</div>
<a id="gaeaded64eda71ed6b1d569d3e723abc4a"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gaeaded64eda71ed6b1d569d3e723abc4a">&#9670;&nbsp;</a></span>mi_new_nothrow()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_new_nothrow </td>
<td>(</td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>n</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>return <code>NULL</code> on failure. </p>
</div> </div>
</div> </div>
<a id="gacff84f226ba9feb2031b8992e5579447"></a> <a id="gacff84f226ba9feb2031b8992e5579447"></a>

View file

@ -9,10 +9,6 @@ var group__posix =
[ "mi_malloc_size", "group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de", null ], [ "mi_malloc_size", "group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de", null ],
[ "mi_malloc_usable_size", "group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17", null ], [ "mi_malloc_usable_size", "group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17", null ],
[ "mi_memalign", "group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e", null ], [ "mi_memalign", "group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e", null ],
[ "mi_new", "group__posix.html#gaad048a9fce3d02c5909cd05c6ec24545", null ],
[ "mi_new_aligned", "group__posix.html#gaef2c2bdb4f70857902d3c8903ac095f3", null ],
[ "mi_new_aligned_nothrow", "group__posix.html#gab5e29558926d934c3f1cae8c815f942c", null ],
[ "mi_new_nothrow", "group__posix.html#gaeaded64eda71ed6b1d569d3e723abc4a", null ],
[ "mi_posix_memalign", "group__posix.html#gacff84f226ba9feb2031b8992e5579447", null ], [ "mi_posix_memalign", "group__posix.html#gacff84f226ba9feb2031b8992e5579447", null ],
[ "mi_pvalloc", "group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e", null ], [ "mi_pvalloc", "group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e", null ],
[ "mi_reallocarray", "group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088", null ], [ "mi_reallocarray", "group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088", null ],

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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

597
docs/group__zeroinit.html Normal file
View file

@ -0,0 +1,597 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>mi-malloc: Zero initialized re-allocation</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(initResizable);
/* @license-end */</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function() { init_search(); });
/* @license-end */
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="mimalloc-doxygen.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="mimalloc-logo.svg"/></td>
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">mi-malloc
&#160;<span id="projectnumber">1.4</span>
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.15 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('group__zeroinit.html','');});
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="header">
<div class="summary">
<a href="#func-members">Functions</a> </div>
<div class="headertitle">
<div class="title">Zero initialized re-allocation</div> </div>
</div><!--header-->
<div class="contents">
<p>The zero-initialized re-allocations are only valid on memory that was originally allocated with zero initialization too.
<a href="#details">More...</a></p>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
Functions</h2></td></tr>
<tr class="memitem:ga8c292e142110229a2980b37ab036dbc6"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6">mi_rezalloc</a> (void *p, size_t newsize)</td></tr>
<tr class="separator:ga8c292e142110229a2980b37ab036dbc6"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gacd71a7bce96aab38ae6de17af2eb2cf0"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0">mi_rezalloc_aligned</a> (void *p, size_t newsize, size_t alignment)</td></tr>
<tr class="separator:gacd71a7bce96aab38ae6de17af2eb2cf0"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gae8b358c417e61d5307da002702b0a8e1"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1">mi_rezalloc_aligned_at</a> (void *p, size_t newsize, size_t alignment, size_t offset)</td></tr>
<tr class="separator:gae8b358c417e61d5307da002702b0a8e1"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga3e7e5c291acf1c7fd7ffd9914a9f945f"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f">mi_recalloc_aligned</a> (void *p, size_t newcount, size_t size, size_t alignment)</td></tr>
<tr class="separator:ga3e7e5c291acf1c7fd7ffd9914a9f945f"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga4ff5e92ad73585418a072c9d059e5cf9"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9">mi_recalloc_aligned_at</a> (void *p, size_t newcount, size_t size, size_t alignment, size_t offset)</td></tr>
<tr class="separator:ga4ff5e92ad73585418a072c9d059e5cf9"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gacfad83f14eb5d6a42a497a898e19fc76"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76">mi_heap_rezalloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize)</td></tr>
<tr class="separator:gacfad83f14eb5d6a42a497a898e19fc76"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga8648c5fbb22a80f0262859099f06dfbd"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd">mi_heap_recalloc</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newcount, size_t size)</td></tr>
<tr class="separator:ga8648c5fbb22a80f0262859099f06dfbd"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga375fa8a611c51905e592d5d467c49664"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664">mi_heap_rezalloc_aligned</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize, size_t alignment)</td></tr>
<tr class="separator:ga375fa8a611c51905e592d5d467c49664"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gac90da54fa7e5d10bdc97ce0b51dce2eb"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb">mi_heap_rezalloc_aligned_at</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newsize, size_t alignment, size_t offset)</td></tr>
<tr class="separator:gac90da54fa7e5d10bdc97ce0b51dce2eb"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga9f3f999396c8f77ca5e80e7b40ac29e3"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3">mi_heap_recalloc_aligned</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newcount, size_t size, size_t alignment)</td></tr>
<tr class="separator:ga9f3f999396c8f77ca5e80e7b40ac29e3"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga496452c96f1de8c500be9fddf52edaf7"><td class="memItemLeft" align="right" valign="top">void *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7">mi_heap_recalloc_aligned_at</a> (<a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *heap, void *p, size_t newcount, size_t size, size_t alignment, size_t offset)</td></tr>
<tr class="separator:ga496452c96f1de8c500be9fddf52edaf7"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<p>The zero-initialized re-allocations are only valid on memory that was originally allocated with zero initialization too. </p>
<p>e.g. <code>mi_calloc</code>, <code>mi_zalloc</code>, <code>mi_zalloc_aligned</code> etc. see <a href="https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992">https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992</a> </p>
<h2 class="groupheader">Function Documentation</h2>
<a id="ga8648c5fbb22a80f0262859099f06dfbd"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga8648c5fbb22a80f0262859099f06dfbd">&#9670;&nbsp;</a></span>mi_heap_recalloc()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_heap_recalloc </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
<td class="paramname"><em>heap</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newcount</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>size</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="ga9f3f999396c8f77ca5e80e7b40ac29e3"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga9f3f999396c8f77ca5e80e7b40ac29e3">&#9670;&nbsp;</a></span>mi_heap_recalloc_aligned()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_heap_recalloc_aligned </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
<td class="paramname"><em>heap</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newcount</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>size</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="ga496452c96f1de8c500be9fddf52edaf7"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga496452c96f1de8c500be9fddf52edaf7">&#9670;&nbsp;</a></span>mi_heap_recalloc_aligned_at()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_heap_recalloc_aligned_at </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
<td class="paramname"><em>heap</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newcount</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>size</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>offset</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="gacfad83f14eb5d6a42a497a898e19fc76"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gacfad83f14eb5d6a42a497a898e19fc76">&#9670;&nbsp;</a></span>mi_heap_rezalloc()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_heap_rezalloc </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
<td class="paramname"><em>heap</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newsize</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="ga375fa8a611c51905e592d5d467c49664"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga375fa8a611c51905e592d5d467c49664">&#9670;&nbsp;</a></span>mi_heap_rezalloc_aligned()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_heap_rezalloc_aligned </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
<td class="paramname"><em>heap</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newsize</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="gac90da54fa7e5d10bdc97ce0b51dce2eb"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gac90da54fa7e5d10bdc97ce0b51dce2eb">&#9670;&nbsp;</a></span>mi_heap_rezalloc_aligned_at()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_heap_rezalloc_aligned_at </td>
<td>(</td>
<td class="paramtype"><a class="el" href="group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2">mi_heap_t</a> *&#160;</td>
<td class="paramname"><em>heap</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newsize</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>offset</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="ga3e7e5c291acf1c7fd7ffd9914a9f945f"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga3e7e5c291acf1c7fd7ffd9914a9f945f">&#9670;&nbsp;</a></span>mi_recalloc_aligned()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_recalloc_aligned </td>
<td>(</td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newcount</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>size</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="ga4ff5e92ad73585418a072c9d059e5cf9"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga4ff5e92ad73585418a072c9d059e5cf9">&#9670;&nbsp;</a></span>mi_recalloc_aligned_at()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_recalloc_aligned_at </td>
<td>(</td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newcount</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>size</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>offset</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="ga8c292e142110229a2980b37ab036dbc6"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ga8c292e142110229a2980b37ab036dbc6">&#9670;&nbsp;</a></span>mi_rezalloc()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_rezalloc </td>
<td>(</td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newsize</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="gacd71a7bce96aab38ae6de17af2eb2cf0"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gacd71a7bce96aab38ae6de17af2eb2cf0">&#9670;&nbsp;</a></span>mi_rezalloc_aligned()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_rezalloc_aligned </td>
<td>(</td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newsize</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
<a id="gae8b358c417e61d5307da002702b0a8e1"></a>
<h2 class="memtitle"><span class="permalink"><a href="#gae8b358c417e61d5307da002702b0a8e1">&#9670;&nbsp;</a></span>mi_rezalloc_aligned_at()</h2>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void* mi_rezalloc_aligned_at </td>
<td>(</td>
<td class="paramtype">void *&#160;</td>
<td class="paramname"><em>p</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>newsize</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>alignment</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">size_t&#160;</td>
<td class="paramname"><em>offset</em>&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td></td>
</tr>
</table>
</div><div class="memdoc">
</div>
</div>
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.15 </li>
</ul>
</div>
</body>
</html>

14
docs/group__zeroinit.js Normal file
View file

@ -0,0 +1,14 @@
var group__zeroinit =
[
[ "mi_heap_recalloc", "group__zeroinit.html#ga8648c5fbb22a80f0262859099f06dfbd", null ],
[ "mi_heap_recalloc_aligned", "group__zeroinit.html#ga9f3f999396c8f77ca5e80e7b40ac29e3", null ],
[ "mi_heap_recalloc_aligned_at", "group__zeroinit.html#ga496452c96f1de8c500be9fddf52edaf7", null ],
[ "mi_heap_rezalloc", "group__zeroinit.html#gacfad83f14eb5d6a42a497a898e19fc76", null ],
[ "mi_heap_rezalloc_aligned", "group__zeroinit.html#ga375fa8a611c51905e592d5d467c49664", null ],
[ "mi_heap_rezalloc_aligned_at", "group__zeroinit.html#gac90da54fa7e5d10bdc97ce0b51dce2eb", null ],
[ "mi_recalloc_aligned", "group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f", null ],
[ "mi_recalloc_aligned_at", "group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9", null ],
[ "mi_rezalloc", "group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6", null ],
[ "mi_rezalloc_aligned", "group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0", null ],
[ "mi_rezalloc_aligned_at", "group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1", null ]
];

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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -105,7 +105,7 @@ $(document).ready(function(){initNavTree('index.html','');});
<div class="textblock"><p>This is the API documentation of the <a href="https://github.com/microsoft/mimalloc">mimalloc</a> allocator (pronounced "me-malloc") &ndash; a general purpose allocator with excellent <a href="bench.html">performance</a> characteristics. Initially developed by Daan Leijen for the run-time systems of the <a href="https://github.com/koka-lang/koka">Koka</a> and <a href="https://github.com/leanprover/lean">Lean</a> languages.</p> <div class="textblock"><p>This is the API documentation of the <a href="https://github.com/microsoft/mimalloc">mimalloc</a> allocator (pronounced "me-malloc") &ndash; a general purpose allocator with excellent <a href="bench.html">performance</a> characteristics. Initially developed by Daan Leijen for the run-time systems of the <a href="https://github.com/koka-lang/koka">Koka</a> and <a href="https://github.com/leanprover/lean">Lean</a> languages.</p>
<p>It is a drop-in replacement for <code>malloc</code> and can be used in other programs without code changes, for example, on Unix you can use it as: </p><div class="fragment"><div class="line">&gt; LD_PRELOAD=/usr/bin/libmimalloc.so myprogram</div></div><!-- fragment --><p>Notable aspects of the design include:</p> <p>It is a drop-in replacement for <code>malloc</code> and can be used in other programs without code changes, for example, on Unix you can use it as: </p><div class="fragment"><div class="line">&gt; LD_PRELOAD=/usr/bin/libmimalloc.so myprogram</div></div><!-- fragment --><p>Notable aspects of the design include:</p>
<ul> <ul>
<li><b>small and consistent</b>: the library is less than 3500 LOC using simple and consistent data structures. This makes it very suitable to integrate and adapt in other projects. For runtime systems it provides hooks for a monotonic <em>heartbeat</em> and deferred freeing (for bounded worst-case times with reference counting).</li> <li><b>small and consistent</b>: the library is less than 6k LOC using simple and consistent data structures. This makes it very suitable to integrate and adapt in other projects. For runtime systems it provides hooks for a monotonic <em>heartbeat</em> and deferred freeing (for bounded worst-case times with reference counting).</li>
<li><b>free list sharding</b>: the big idea: instead of one big free list (per size class) we have many smaller lists per memory "page" which both reduces fragmentation and increases locality &ndash; things that are allocated close in time get allocated close in memory. (A memory "page" in <em>mimalloc</em> contains blocks of one size class and is usually 64KiB on a 64-bit system).</li> <li><b>free list sharding</b>: the big idea: instead of one big free list (per size class) we have many smaller lists per memory "page" which both reduces fragmentation and increases locality &ndash; things that are allocated close in time get allocated close in memory. (A memory "page" in <em>mimalloc</em> contains blocks of one size class and is usually 64KiB on a 64-bit system).</li>
<li><b>eager page reset</b>: when a "page" becomes empty (with increased chance due to free list sharding) the memory is marked to the OS as unused ("reset" or "purged") reducing (real) memory pressure and fragmentation, especially in long running programs.</li> <li><b>eager page reset</b>: when a "page" becomes empty (with increased chance due to free list sharding) the memory is marked to the OS as unused ("reset" or "purged") reducing (real) memory pressure and fragmentation, especially in long running programs.</li>
<li><b>secure</b>: <em>mimalloc</em> can be build in secure mode, adding guard pages, randomized allocation, encrypted free lists, etc. to protect against various heap vulnerabilities. The performance penalty is only around 3% on average over our benchmarks.</li> <li><b>secure</b>: <em>mimalloc</em> can be build in secure mode, adding guard pages, randomized allocation, encrypted free lists, etc. to protect against various heap vulnerabilities. The performance penalty is only around 3% on average over our benchmarks.</li>

File diff suppressed because one or more lines are too long

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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -113,6 +113,7 @@ $(document).ready(function(){initNavTree('modules.html','');});
<tr id="row_6_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__analysis.html" target="_self">Heap Introspection</a></td><td class="desc">Inspect the heap at runtime </td></tr> <tr id="row_6_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__analysis.html" target="_self">Heap Introspection</a></td><td class="desc">Inspect the heap at runtime </td></tr>
<tr id="row_7_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__options.html" target="_self">Runtime Options</a></td><td class="desc">Set runtime behavior </td></tr> <tr id="row_7_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__options.html" target="_self">Runtime Options</a></td><td class="desc">Set runtime behavior </td></tr>
<tr id="row_8_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__posix.html" target="_self">Posix</a></td><td class="desc"><code>mi_</code> prefixed implementations of various Posix, Unix, and C++ allocation functions </td></tr> <tr id="row_8_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__posix.html" target="_self">Posix</a></td><td class="desc"><code>mi_</code> prefixed implementations of various Posix, Unix, and C++ allocation functions </td></tr>
<tr id="row_9_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="group__cpp.html" target="_self">C++ wrappers</a></td><td class="desc"><code>mi_</code> prefixed implementations of various allocation functions that use C++ semantics on out-of-memory, generally calling <code>std::get_new_handler</code> and raising a <code>std::bad_alloc</code> exception on failure </td></tr>
</table> </table>
</div><!-- directory --> </div><!-- directory -->
</div><!-- contents --> </div><!-- contents -->

View file

@ -8,5 +8,6 @@ var modules =
[ "Typed Macros", "group__typed.html", "group__typed" ], [ "Typed Macros", "group__typed.html", "group__typed" ],
[ "Heap Introspection", "group__analysis.html", "group__analysis" ], [ "Heap Introspection", "group__analysis.html", "group__analysis" ],
[ "Runtime Options", "group__options.html", "group__options" ], [ "Runtime Options", "group__options.html", "group__options" ],
[ "Posix", "group__posix.html", "group__posix" ] [ "Posix", "group__posix.html", "group__posix" ],
[ "C++ wrappers", "group__cpp.html", "group__cpp" ]
]; ];

View file

@ -28,26 +28,39 @@ var NAVTREEINDEX0 =
"group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af":[5,6,4], "group__analysis.html#gaa862aa8ed8d57d84cae41fc1022d71af":[5,6,4],
"group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65":[5,6,1], "group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65":[5,6,1],
"group__analysis.html#structmi__heap__area__t":[5,6,0], "group__analysis.html#structmi__heap__area__t":[5,6,0],
"group__cpp.html":[5,9],
"group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907":[5,9,7],
"group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e":[5,9,6],
"group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545":[5,9,1],
"group__cpp.html#gab5e29558926d934c3f1cae8c815f942c":[5,9,3],
"group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81":[5,9,4],
"group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a":[5,9,5],
"group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3":[5,9,2],
"group__cpp.html#structmi__stl__allocator":[5,9,0],
"group__extended.html":[5,1], "group__extended.html":[5,1],
"group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee":[5,1,17], "group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee":[5,1,21],
"group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf":[5,1,14], "group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf":[5,1,18],
"group__extended.html#ga1ea64283508718d9d645c38efc2f4305":[5,1,0], "group__extended.html#ga1ea64283508718d9d645c38efc2f4305":[5,1,0],
"group__extended.html#ga220f29f40a44404b0061c15bc1c31152":[5,1,18], "group__extended.html#ga220f29f40a44404b0061c15bc1c31152":[5,1,22],
"group__extended.html#ga22213691c3ce5ab4d91b24aff1023529":[5,1,1], "group__extended.html#ga251d369cda3f1c2a955c555486ed90e5":[5,1,2],
"group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2":[5,1,8], "group__extended.html#ga256cc6f13a142deabbadd954a217e228":[5,1,16],
"group__extended.html#ga2664f36a2dd557741c429cb799f04641":[5,1,10], "group__extended.html#ga299dae78d25ce112e384a98b7309c5be":[5,1,1],
"group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f":[5,1,2], "group__extended.html#ga2d126e5c62d3badc35445e5d84166df2":[5,1,15],
"group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99":[5,1,13], "group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50":[5,1,13],
"group__extended.html#ga421430e2226d7d468529cec457396756":[5,1,3], "group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece":[5,1,9],
"group__extended.html#ga489670a15d1a257ab4639e645ee4612a":[5,1,16], "group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99":[5,1,17],
"group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6":[5,1,5], "group__extended.html#ga421430e2226d7d468529cec457396756":[5,1,4],
"group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99":[5,1,7], "group__extended.html#ga5f071b10d4df1c3658e04e7fd67a94e6":[5,1,6],
"group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5":[5,1,9], "group__extended.html#ga7136c2e55cb22c98ecf95d08d6debb99":[5,1,8],
"group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1":[5,1,11], "group__extended.html#ga7795a13d20087447281858d2c771cca1":[5,1,12],
"group__extended.html#ga8ca07ccff283956d71f48272f4fd5c01":[5,1,12], "group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1":[5,1,14],
"group__extended.html#gaad25050b19f30cd79397b227e0157a3f":[5,1,6], "group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45":[5,1,10],
"group__extended.html#gac057927cd06c854b45fe7847e921bd47":[5,1,4], "group__extended.html#gaad25050b19f30cd79397b227e0157a3f":[5,1,7],
"group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17":[5,1,15], "group__extended.html#gab1dac8476c46cb9eecab767eb40c1525":[5,1,20],
"group__extended.html#gac057927cd06c854b45fe7847e921bd47":[5,1,5],
"group__extended.html#gad823d23444a4b77a40f66bf075a98a0c":[5,1,3],
"group__extended.html#gae5b17ff027cd2150b43a33040250cf3f":[5,1,11],
"group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17":[5,1,19],
"group__heap.html":[5,3], "group__heap.html":[5,3],
"group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0":[5,3,20], "group__heap.html#ga00e95ba1e01acac3cfd95bb7a357a6f0":[5,3,20],
"group__heap.html#ga08ca6419a5c057a4d965868998eef487":[5,3,3], "group__heap.html#ga08ca6419a5c057a4d965868998eef487":[5,3,3],
@ -99,38 +112,35 @@ var NAVTREEINDEX0 =
"group__options.html#gaf84921c32375e25754dc2ee6a911fa60":[5,7,5], "group__options.html#gaf84921c32375e25754dc2ee6a911fa60":[5,7,5],
"group__options.html#gafebf7ed116adb38ae5218bc3ce06884c":[5,7,0], "group__options.html#gafebf7ed116adb38ae5218bc3ce06884c":[5,7,0],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda":[5,7,0,0], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda":[5,7,0,0],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c":[5,7,0,11], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74":[5,7,0,11],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5":[5,7,0,10],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c":[5,7,0,13],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b":[5,7,0,3], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b":[5,7,0,3],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1":[5,7,0,7], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1":[5,7,0,7],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad":[5,7,0,4], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad":[5,7,0,4],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e":[5,7,0,5], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4192d491200d0055df0554d4cf65054e":[5,7,0,5],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf":[5,7,0,13], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca4b74ae2a69e445de6c2361b73c1d14bf":[5,7,0,14],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a":[5,7,0,14], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca5b4357b74be0d87568036c32eb1a2e4a":[5,7,0,15],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777":[5,7,0,2], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777":[5,7,0,2],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07":[5,7,0,9], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536":[5,7,0,12],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536":[5,7,0,10],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2":[5,7,0,6], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2":[5,7,0,6],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968":[5,7,0,8], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968":[5,7,0,8],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d":[5,7,0,12], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d":[5,7,0,9],
"group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0":[5,7,0,1], "group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0":[5,7,0,1],
"group__posix.html":[5,8], "group__posix.html":[5,8],
"group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17":[5,8,7], "group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17":[5,8,7],
"group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9":[5,8,3], "group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9":[5,8,3],
"group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5":[5,8,1], "group__posix.html#ga1326d2e4388630b5f81ca7206318b8e5":[5,8,1],
"group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de":[5,8,6], "group__posix.html#ga4531c9e775bb3ae12db57c1ba8a5d7de":[5,8,6],
"group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088":[5,8,15], "group__posix.html#ga48fad8648a2f1dab9c87ea9448a52088":[5,8,11],
"group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7":[5,8,2], "group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7":[5,8,2],
"group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc":[5,8,5], "group__posix.html#ga72e9d7ffb5fe94d69bc722c8506e27bc":[5,8,5],
"group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b":[5,8,16], "group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b":[5,8,12],
"group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e":[5,8,8], "group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e":[5,8,8],
"group__posix.html#gaad048a9fce3d02c5909cd05c6ec24545":[5,8,9], "group__posix.html#gacff84f226ba9feb2031b8992e5579447":[5,8,9],
"group__posix.html#gab5e29558926d934c3f1cae8c815f942c":[5,8,11],
"group__posix.html#gacff84f226ba9feb2031b8992e5579447":[5,8,13],
"group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a":[5,8,0], "group__posix.html#gad5a69c8fea96aa2b7a7c818c2130090a":[5,8,0],
"group__posix.html#gae01389eedab8d67341ff52e2aad80ebb":[5,8,4], "group__posix.html#gae01389eedab8d67341ff52e2aad80ebb":[5,8,4],
"group__posix.html#gaeaded64eda71ed6b1d569d3e723abc4a":[5,8,12], "group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e":[5,8,10],
"group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e":[5,8,14],
"group__posix.html#gaef2c2bdb4f70857902d3c8903ac095f3":[5,8,10],
"group__typed.html":[5,5], "group__typed.html":[5,5],
"group__typed.html#ga0619a62c5fd886f1016030abe91f0557":[5,5,7], "group__typed.html#ga0619a62c5fd886f1016030abe91f0557":[5,5,7],
"group__typed.html#ga1158b49a55dfa81f58a4426a7578f523":[5,5,9], "group__typed.html#ga1158b49a55dfa81f58a4426a7578f523":[5,5,9],

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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -118,10 +118,10 @@ $(document).ready(function(){initNavTree('overrides.html','');});
<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: 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>
<h3>Windows</h3> <h3>Windows</h3>
<p>On Windows you need to 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 mimalloc DLL at runtime (as it as referred to by the mimalloc DLL). The redirection DLL's ensure all calls to the C runtime malloc API get redirected to mimalloc.</p> <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>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.</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 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 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 should be possible to patch existing executables that are linked with the dynamic C runtime (<code>ucrtbase.dll</code>) by just putting the mimalloc DLL 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 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>
<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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">

View file

@ -1,4 +1,5 @@
var searchData= var searchData=
[ [
['committed',['committed',['../group__analysis.html#ab47526df656d8837ec3e97f11b83f835',1,'mi_heap_area_t']]] ['committed',['committed',['../group__analysis.html#ab47526df656d8837ec3e97f11b83f835',1,'mi_heap_area_t']]],
['c_2b_2b_20wrappers',['C++ wrappers',['../group__cpp.html',1,'']]]
]; ];

View file

@ -10,7 +10,8 @@ var searchData=
['mi_5fcfree',['mi_cfree',['../group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7',1,'mimalloc-doc.h']]], ['mi_5fcfree',['mi_cfree',['../group__posix.html#ga705dc7a64bffacfeeb0141501a5c35d7',1,'mimalloc-doc.h']]],
['mi_5fcheck_5fowned',['mi_check_owned',['../group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5',1,'mimalloc-doc.h']]], ['mi_5fcheck_5fowned',['mi_check_owned',['../group__analysis.html#ga628c237489c2679af84a4d0d143b3dd5',1,'mimalloc-doc.h']]],
['mi_5fcollect',['mi_collect',['../group__extended.html#ga421430e2226d7d468529cec457396756',1,'mimalloc-doc.h']]], ['mi_5fcollect',['mi_collect',['../group__extended.html#ga421430e2226d7d468529cec457396756',1,'mimalloc-doc.h']]],
['mi_5fdeferred_5ffree_5ffun',['mi_deferred_free_fun',['../group__extended.html#ga22213691c3ce5ab4d91b24aff1023529',1,'mimalloc-doc.h']]], ['mi_5fdeferred_5ffree_5ffun',['mi_deferred_free_fun',['../group__extended.html#ga299dae78d25ce112e384a98b7309c5be',1,'mimalloc-doc.h']]],
['mi_5ferror_5ffun',['mi_error_fun',['../group__extended.html#ga251d369cda3f1c2a955c555486ed90e5',1,'mimalloc-doc.h']]],
['mi_5fexpand',['mi_expand',['../group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4',1,'mimalloc-doc.h']]], ['mi_5fexpand',['mi_expand',['../group__malloc.html#gaaee66a1d483c3e28f585525fb96707e4',1,'mimalloc-doc.h']]],
['mi_5ffree',['mi_free',['../group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95',1,'mimalloc-doc.h']]], ['mi_5ffree',['mi_free',['../group__malloc.html#gaf2c7b89c327d1f60f59e68b9ea644d95',1,'mimalloc-doc.h']]],
['mi_5ffree_5faligned',['mi_free_aligned',['../group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9',1,'mimalloc-doc.h']]], ['mi_5ffree_5faligned',['mi_free_aligned',['../group__posix.html#ga0d28d5cf61e6bfbb18c63092939fe5c9',1,'mimalloc-doc.h']]],
@ -72,11 +73,13 @@ var searchData=
['mi_5fmallocn',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]], ['mi_5fmallocn',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]],
['mi_5fmallocn_5ftp',['mi_mallocn_tp',['../group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b',1,'mimalloc-doc.h']]], ['mi_5fmallocn_5ftp',['mi_mallocn_tp',['../group__typed.html#gae5cb6e0fafc9f23169c5622e077afe8b',1,'mimalloc-doc.h']]],
['mi_5fmemalign',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]], ['mi_5fmemalign',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]],
['mi_5fnew',['mi_new',['../group__posix.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]], ['mi_5fnew',['mi_new',['../group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]],
['mi_5fnew_5faligned',['mi_new_aligned',['../group__posix.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]], ['mi_5fnew_5faligned',['mi_new_aligned',['../group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]],
['mi_5fnew_5faligned_5fnothrow',['mi_new_aligned_nothrow',['../group__posix.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]], ['mi_5fnew_5faligned_5fnothrow',['mi_new_aligned_nothrow',['../group__cpp.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]],
['mi_5fnew_5fnothrow',['mi_new_nothrow',['../group__posix.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]], ['mi_5fnew_5fn',['mi_new_n',['../group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81',1,'mimalloc-doc.h']]],
['mi_5foption_5fcache_5freset',['mi_option_cache_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07',1,'mimalloc-doc.h']]], ['mi_5fnew_5fnothrow',['mi_new_nothrow',['../group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
['mi_5fnew_5frealloc',['mi_new_realloc',['../group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e',1,'mimalloc-doc.h']]],
['mi_5fnew_5freallocn',['mi_new_reallocn',['../group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907',1,'mimalloc-doc.h']]],
['mi_5foption_5feager_5fcommit',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]], ['mi_5foption_5feager_5fcommit',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]],
['mi_5foption_5feager_5fcommit_5fdelay',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]], ['mi_5foption_5feager_5fcommit_5fdelay',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]],
['mi_5foption_5feager_5fregion_5fcommit',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]], ['mi_5foption_5feager_5fregion_5fcommit',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]],
@ -89,6 +92,7 @@ var searchData=
['mi_5foption_5fpage_5freset',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]], ['mi_5foption_5fpage_5freset',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]],
['mi_5foption_5freserve_5fhuge_5fos_5fpages',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]], ['mi_5foption_5freserve_5fhuge_5fos_5fpages',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]],
['mi_5foption_5freset_5fdecommits',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]], ['mi_5foption_5freset_5fdecommits',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
['mi_5foption_5freset_5fdelay',['mi_option_reset_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5',1,'mimalloc-doc.h']]],
['mi_5foption_5fsegment_5fcache',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]], ['mi_5foption_5fsegment_5fcache',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
['mi_5foption_5fsegment_5freset',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]], ['mi_5foption_5fsegment_5freset',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]],
['mi_5foption_5fset',['mi_option_set',['../group__options.html#gaf84921c32375e25754dc2ee6a911fa60',1,'mimalloc-doc.h']]], ['mi_5foption_5fset',['mi_option_set',['../group__options.html#gaf84921c32375e25754dc2ee6a911fa60',1,'mimalloc-doc.h']]],
@ -96,8 +100,9 @@ var searchData=
['mi_5foption_5fshow_5ferrors',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]], ['mi_5foption_5fshow_5ferrors',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]],
['mi_5foption_5fshow_5fstats',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]], ['mi_5foption_5fshow_5fstats',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]],
['mi_5foption_5ft',['mi_option_t',['../group__options.html#gafebf7ed116adb38ae5218bc3ce06884c',1,'mimalloc-doc.h']]], ['mi_5foption_5ft',['mi_option_t',['../group__options.html#gafebf7ed116adb38ae5218bc3ce06884c',1,'mimalloc-doc.h']]],
['mi_5foption_5fuse_5fnuma_5fnodes',['mi_option_use_numa_nodes',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74',1,'mimalloc-doc.h']]],
['mi_5foption_5fverbose',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]], ['mi_5foption_5fverbose',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]],
['mi_5foutput_5ffun',['mi_output_fun',['../group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f',1,'mimalloc-doc.h']]], ['mi_5foutput_5ffun',['mi_output_fun',['../group__extended.html#gad823d23444a4b77a40f66bf075a98a0c',1,'mimalloc-doc.h']]],
['mi_5fposix_5fmemalign',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]], ['mi_5fposix_5fmemalign',['mi_posix_memalign',['../group__posix.html#gacff84f226ba9feb2031b8992e5579447',1,'mimalloc-doc.h']]],
['mi_5fpvalloc',['mi_pvalloc',['../group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e',1,'mimalloc-doc.h']]], ['mi_5fpvalloc',['mi_pvalloc',['../group__posix.html#gaeb325c39b887d3b90d85d1eb1712fb1e',1,'mimalloc-doc.h']]],
['mi_5frealloc',['mi_realloc',['../group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6',1,'mimalloc-doc.h']]], ['mi_5frealloc',['mi_realloc',['../group__malloc.html#gaf11eb497da57bdfb2de65eb191c69db6',1,'mimalloc-doc.h']]],
@ -111,21 +116,24 @@ var searchData=
['mi_5frecalloc',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]], ['mi_5frecalloc',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]],
['mi_5frecalloc_5faligned',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]], ['mi_5frecalloc_5faligned',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]],
['mi_5frecalloc_5faligned_5fat',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]], ['mi_5frecalloc_5faligned_5fat',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]],
['mi_5fregister_5fdeferred_5ffree',['mi_register_deferred_free',['../group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2',1,'mimalloc-doc.h']]], ['mi_5fregister_5fdeferred_5ffree',['mi_register_deferred_free',['../group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece',1,'mimalloc-doc.h']]],
['mi_5fregister_5foutput',['mi_register_output',['../group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5',1,'mimalloc-doc.h']]], ['mi_5fregister_5ferror',['mi_register_error',['../group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45',1,'mimalloc-doc.h']]],
['mi_5freserve_5fhuge_5fos_5fpages',['mi_reserve_huge_os_pages',['../group__extended.html#ga2664f36a2dd557741c429cb799f04641',1,'mimalloc-doc.h']]], ['mi_5fregister_5foutput',['mi_register_output',['../group__extended.html#gae5b17ff027cd2150b43a33040250cf3f',1,'mimalloc-doc.h']]],
['mi_5freserve_5fhuge_5fos_5fpages_5fat',['mi_reserve_huge_os_pages_at',['../group__extended.html#ga7795a13d20087447281858d2c771cca1',1,'mimalloc-doc.h']]],
['mi_5freserve_5fhuge_5fos_5fpages_5finterleave',['mi_reserve_huge_os_pages_interleave',['../group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50',1,'mimalloc-doc.h']]],
['mi_5frezalloc',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]], ['mi_5frezalloc',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]],
['mi_5frezalloc_5faligned',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]], ['mi_5frezalloc_5faligned',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]],
['mi_5frezalloc_5faligned_5fat',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]], ['mi_5frezalloc_5faligned_5fat',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]],
['mi_5fsmall_5fsize_5fmax',['MI_SMALL_SIZE_MAX',['../group__extended.html#ga1ea64283508718d9d645c38efc2f4305',1,'mimalloc-doc.h']]], ['mi_5fsmall_5fsize_5fmax',['MI_SMALL_SIZE_MAX',['../group__extended.html#ga1ea64283508718d9d645c38efc2f4305',1,'mimalloc-doc.h']]],
['mi_5fstats_5fmerge',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]], ['mi_5fstats_5fmerge',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]],
['mi_5fstats_5fprint',['mi_stats_print',['../group__extended.html#ga8ca07ccff283956d71f48272f4fd5c01',1,'mimalloc-doc.h']]], ['mi_5fstats_5fprint',['mi_stats_print',['../group__extended.html#ga2d126e5c62d3badc35445e5d84166df2',1,'mi_stats_print(void *out):&#160;mimalloc-doc.h'],['../group__extended.html#ga256cc6f13a142deabbadd954a217e228',1,'mi_stats_print(mi_output_fun *out, void *arg):&#160;mimalloc-doc.h']]],
['mi_5fstats_5freset',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]], ['mi_5fstats_5freset',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]],
['mi_5fstl_5fallocator',['mi_stl_allocator',['../group__cpp.html#structmi__stl__allocator',1,'']]],
['mi_5fstrdup',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]], ['mi_5fstrdup',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
['mi_5fstrndup',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]], ['mi_5fstrndup',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]],
['mi_5fthread_5fdone',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]], ['mi_5fthread_5fdone',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]],
['mi_5fthread_5finit',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]], ['mi_5fthread_5finit',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
['mi_5fthread_5fstats_5fprint',['mi_thread_stats_print',['../group__extended.html#ga489670a15d1a257ab4639e645ee4612a',1,'mimalloc-doc.h']]], ['mi_5fthread_5fstats_5fprint_5fout',['mi_thread_stats_print_out',['../group__extended.html#gab1dac8476c46cb9eecab767eb40c1525',1,'mimalloc-doc.h']]],
['mi_5fusable_5fsize',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]], ['mi_5fusable_5fsize',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]],
['mi_5fvalloc',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]], ['mi_5fvalloc',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]],
['mi_5fzalloc',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]], ['mi_5fzalloc',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],

30
docs/search/all_c.html Normal file
View file

@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<link rel="stylesheet" type="text/css" href="search.css"/>
<script type="text/javascript" src="all_c.js"></script>
<script type="text/javascript" src="search.js"></script>
</head>
<body class="SRPage">
<div id="SRIndex">
<div class="SRStatus" id="Loading">Loading...</div>
<div id="SRResults"></div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
createResults();
/* @license-end */
--></script>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
document.getElementById("Loading").style.display="none";
document.getElementById("NoMatches").style.display="none";
var searchResults = new SearchResults("searchResults");
searchResults.Search();
/* @license-end */
--></script>
</div>
</body>
</html>

4
docs/search/all_c.js Normal file
View file

@ -0,0 +1,4 @@
var searchData=
[
['zero_20initialized_20re_2dallocation',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
];

30
docs/search/all_d.html Normal file
View file

@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<link rel="stylesheet" type="text/css" href="search.css"/>
<script type="text/javascript" src="all_d.js"></script>
<script type="text/javascript" src="search.js"></script>
</head>
<body class="SRPage">
<div id="SRIndex">
<div class="SRStatus" id="Loading">Loading...</div>
<div id="SRResults"></div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
createResults();
/* @license-end */
--></script>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
document.getElementById("Loading").style.display="none";
document.getElementById("NoMatches").style.display="none";
var searchResults = new SearchResults("searchResults");
searchResults.Search();
/* @license-end */
--></script>
</div>
</body>
</html>

4
docs/search/all_d.js Normal file
View file

@ -0,0 +1,4 @@
var searchData=
[
['zero_20initialized_20re_2dallocation',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
];

View file

@ -1,4 +1,5 @@
var searchData= var searchData=
[ [
['mi_5fheap_5farea_5ft',['mi_heap_area_t',['../group__analysis.html#structmi__heap__area__t',1,'']]] ['mi_5fheap_5farea_5ft',['mi_heap_area_t',['../group__analysis.html#structmi__heap__area__t',1,'']]],
['mi_5fstl_5fallocator',['mi_stl_allocator',['../group__cpp.html#structmi__stl__allocator',1,'']]]
]; ];

View file

@ -1,6 +1,5 @@
var searchData= var searchData=
[ [
['mi_5foption_5fcache_5freset',['mi_option_cache_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac2157a0cb79cd996c1db7d9f6a090c07',1,'mimalloc-doc.h']]],
['mi_5foption_5feager_5fcommit',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]], ['mi_5foption_5feager_5fcommit',['mi_option_eager_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca1e8de72c93da7ff22d91e1e27b52ac2b',1,'mimalloc-doc.h']]],
['mi_5foption_5feager_5fcommit_5fdelay',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]], ['mi_5foption_5feager_5fcommit_5fdelay',['mi_option_eager_commit_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca17a190c25be381142d87e0468c4c068c',1,'mimalloc-doc.h']]],
['mi_5foption_5feager_5fregion_5fcommit',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]], ['mi_5foption_5feager_5fregion_5fcommit',['mi_option_eager_region_commit',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca32ce97ece29f69e82579679cf8a307ad',1,'mimalloc-doc.h']]],
@ -9,9 +8,11 @@ var searchData=
['mi_5foption_5fpage_5freset',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]], ['mi_5foption_5fpage_5freset',['mi_option_page_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cada854dd272c66342f18a93ee254a2968',1,'mimalloc-doc.h']]],
['mi_5foption_5freserve_5fhuge_5fos_5fpages',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]], ['mi_5foption_5freserve_5fhuge_5fos_5fpages',['mi_option_reserve_huge_os_pages',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884caca7ed041be3b0b9d0b82432c7bf41af2',1,'mimalloc-doc.h']]],
['mi_5foption_5freset_5fdecommits',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]], ['mi_5foption_5freset_5fdecommits',['mi_option_reset_decommits',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cac81ee965b130fa81238913a3c239d536',1,'mimalloc-doc.h']]],
['mi_5foption_5freset_5fdelay',['mi_option_reset_delay',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca154fe170131d5212cff57e22b99523c5',1,'mimalloc-doc.h']]],
['mi_5foption_5fsegment_5fcache',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]], ['mi_5foption_5fsegment_5fcache',['mi_option_segment_cache',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca2ecbe7ef32f5c84de3739aa4f0b805a1',1,'mimalloc-doc.h']]],
['mi_5foption_5fsegment_5freset',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]], ['mi_5foption_5fsegment_5freset',['mi_option_segment_reset',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafb121d30d87591850d5410ccc3a95c6d',1,'mimalloc-doc.h']]],
['mi_5foption_5fshow_5ferrors',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]], ['mi_5foption_5fshow_5ferrors',['mi_option_show_errors',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884cafbf4822e5c00732c5984b32a032837f0',1,'mimalloc-doc.h']]],
['mi_5foption_5fshow_5fstats',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]], ['mi_5foption_5fshow_5fstats',['mi_option_show_stats',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0957ef73b2550764b4840edf48422fda',1,'mimalloc-doc.h']]],
['mi_5foption_5fuse_5fnuma_5fnodes',['mi_option_use_numa_nodes',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca0ac33a18f6b659fcfaf44efb0bab1b74',1,'mimalloc-doc.h']]],
['mi_5foption_5fverbose',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]] ['mi_5foption_5fverbose',['mi_option_verbose',['../group__options.html#ggafebf7ed116adb38ae5218bc3ce06884ca7c8b7bf5281c581bad64f5daa6442777',1,'mimalloc-doc.h']]]
]; ];

View file

@ -59,10 +59,13 @@ var searchData=
['mi_5fmalloc_5fusable_5fsize',['mi_malloc_usable_size',['../group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17',1,'mimalloc-doc.h']]], ['mi_5fmalloc_5fusable_5fsize',['mi_malloc_usable_size',['../group__posix.html#ga06d07cf357bbac5c73ba5d0c0c421e17',1,'mimalloc-doc.h']]],
['mi_5fmallocn',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]], ['mi_5fmallocn',['mi_mallocn',['../group__malloc.html#ga0b05e2bf0f73e7401ae08597ff782ac6',1,'mimalloc-doc.h']]],
['mi_5fmemalign',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]], ['mi_5fmemalign',['mi_memalign',['../group__posix.html#gaab7fa71ea93b96873f5d9883db57d40e',1,'mimalloc-doc.h']]],
['mi_5fnew',['mi_new',['../group__posix.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]], ['mi_5fnew',['mi_new',['../group__cpp.html#gaad048a9fce3d02c5909cd05c6ec24545',1,'mimalloc-doc.h']]],
['mi_5fnew_5faligned',['mi_new_aligned',['../group__posix.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]], ['mi_5fnew_5faligned',['mi_new_aligned',['../group__cpp.html#gaef2c2bdb4f70857902d3c8903ac095f3',1,'mimalloc-doc.h']]],
['mi_5fnew_5faligned_5fnothrow',['mi_new_aligned_nothrow',['../group__posix.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]], ['mi_5fnew_5faligned_5fnothrow',['mi_new_aligned_nothrow',['../group__cpp.html#gab5e29558926d934c3f1cae8c815f942c',1,'mimalloc-doc.h']]],
['mi_5fnew_5fnothrow',['mi_new_nothrow',['../group__posix.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]], ['mi_5fnew_5fn',['mi_new_n',['../group__cpp.html#gae7bc4f56cd57ed3359060ff4f38bda81',1,'mimalloc-doc.h']]],
['mi_5fnew_5fnothrow',['mi_new_nothrow',['../group__cpp.html#gaeaded64eda71ed6b1d569d3e723abc4a',1,'mimalloc-doc.h']]],
['mi_5fnew_5frealloc',['mi_new_realloc',['../group__cpp.html#gaab78a32f55149e9fbf432d5288e38e1e',1,'mimalloc-doc.h']]],
['mi_5fnew_5freallocn',['mi_new_reallocn',['../group__cpp.html#ga756f4b2bc6a7ecd0a90baea8e90c7907',1,'mimalloc-doc.h']]],
['mi_5foption_5fenable',['mi_option_enable',['../group__options.html#ga6d45a20a3131f18bc351b69763b38ce4',1,'mimalloc-doc.h']]], ['mi_5foption_5fenable',['mi_option_enable',['../group__options.html#ga6d45a20a3131f18bc351b69763b38ce4',1,'mimalloc-doc.h']]],
['mi_5foption_5fenable_5fdefault',['mi_option_enable_default',['../group__options.html#ga37988264b915a7db92530cc02d5494cb',1,'mimalloc-doc.h']]], ['mi_5foption_5fenable_5fdefault',['mi_option_enable_default',['../group__options.html#ga37988264b915a7db92530cc02d5494cb',1,'mimalloc-doc.h']]],
['mi_5foption_5fenabled',['mi_option_enabled',['../group__options.html#gacebe3f6d91b4a50b54eb84e2a1da1b30',1,'mimalloc-doc.h']]], ['mi_5foption_5fenabled',['mi_option_enabled',['../group__options.html#gacebe3f6d91b4a50b54eb84e2a1da1b30',1,'mimalloc-doc.h']]],
@ -81,20 +84,22 @@ var searchData=
['mi_5frecalloc',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]], ['mi_5frecalloc',['mi_recalloc',['../group__malloc.html#ga23a0fbb452b5dce8e31fab1a1958cacc',1,'mimalloc-doc.h']]],
['mi_5frecalloc_5faligned',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]], ['mi_5frecalloc_5faligned',['mi_recalloc_aligned',['../group__zeroinit.html#ga3e7e5c291acf1c7fd7ffd9914a9f945f',1,'mimalloc-doc.h']]],
['mi_5frecalloc_5faligned_5fat',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]], ['mi_5frecalloc_5faligned_5fat',['mi_recalloc_aligned_at',['../group__zeroinit.html#ga4ff5e92ad73585418a072c9d059e5cf9',1,'mimalloc-doc.h']]],
['mi_5fregister_5fdeferred_5ffree',['mi_register_deferred_free',['../group__extended.html#ga24dc9cc6fca8daa2aa30aa8025467ce2',1,'mimalloc-doc.h']]], ['mi_5fregister_5fdeferred_5ffree',['mi_register_deferred_free',['../group__extended.html#ga3460a6ca91af97be4058f523d3cb8ece',1,'mimalloc-doc.h']]],
['mi_5fregister_5foutput',['mi_register_output',['../group__extended.html#ga84a0c8b401e42eb5b1bce156852f44c5',1,'mimalloc-doc.h']]], ['mi_5fregister_5ferror',['mi_register_error',['../group__extended.html#gaa1d55e0e894be240827e5d87ec3a1f45',1,'mimalloc-doc.h']]],
['mi_5freserve_5fhuge_5fos_5fpages',['mi_reserve_huge_os_pages',['../group__extended.html#ga2664f36a2dd557741c429cb799f04641',1,'mimalloc-doc.h']]], ['mi_5fregister_5foutput',['mi_register_output',['../group__extended.html#gae5b17ff027cd2150b43a33040250cf3f',1,'mimalloc-doc.h']]],
['mi_5freserve_5fhuge_5fos_5fpages_5fat',['mi_reserve_huge_os_pages_at',['../group__extended.html#ga7795a13d20087447281858d2c771cca1',1,'mimalloc-doc.h']]],
['mi_5freserve_5fhuge_5fos_5fpages_5finterleave',['mi_reserve_huge_os_pages_interleave',['../group__extended.html#ga3132f521fb756fc0e8ec0b74fb58df50',1,'mimalloc-doc.h']]],
['mi_5frezalloc',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]], ['mi_5frezalloc',['mi_rezalloc',['../group__zeroinit.html#ga8c292e142110229a2980b37ab036dbc6',1,'mimalloc-doc.h']]],
['mi_5frezalloc_5faligned',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]], ['mi_5frezalloc_5faligned',['mi_rezalloc_aligned',['../group__zeroinit.html#gacd71a7bce96aab38ae6de17af2eb2cf0',1,'mimalloc-doc.h']]],
['mi_5frezalloc_5faligned_5fat',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]], ['mi_5frezalloc_5faligned_5fat',['mi_rezalloc_aligned_at',['../group__zeroinit.html#gae8b358c417e61d5307da002702b0a8e1',1,'mimalloc-doc.h']]],
['mi_5fstats_5fmerge',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]], ['mi_5fstats_5fmerge',['mi_stats_merge',['../group__extended.html#ga854b1de8cb067c7316286c28b2fcd3d1',1,'mimalloc-doc.h']]],
['mi_5fstats_5fprint',['mi_stats_print',['../group__extended.html#ga8ca07ccff283956d71f48272f4fd5c01',1,'mimalloc-doc.h']]], ['mi_5fstats_5fprint',['mi_stats_print',['../group__extended.html#ga2d126e5c62d3badc35445e5d84166df2',1,'mi_stats_print(void *out):&#160;mimalloc-doc.h'],['../group__extended.html#ga256cc6f13a142deabbadd954a217e228',1,'mi_stats_print(mi_output_fun *out, void *arg):&#160;mimalloc-doc.h']]],
['mi_5fstats_5freset',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]], ['mi_5fstats_5freset',['mi_stats_reset',['../group__extended.html#ga3bb8468b8cfcc6e2a61d98aee85c5f99',1,'mimalloc-doc.h']]],
['mi_5fstrdup',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]], ['mi_5fstrdup',['mi_strdup',['../group__malloc.html#gac7cffe13f1f458ed16789488bf92b9b2',1,'mimalloc-doc.h']]],
['mi_5fstrndup',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]], ['mi_5fstrndup',['mi_strndup',['../group__malloc.html#gaaabf971c2571891433477e2d21a35266',1,'mimalloc-doc.h']]],
['mi_5fthread_5fdone',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]], ['mi_5fthread_5fdone',['mi_thread_done',['../group__extended.html#ga0ae4581e85453456a0d658b2b98bf7bf',1,'mimalloc-doc.h']]],
['mi_5fthread_5finit',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]], ['mi_5fthread_5finit',['mi_thread_init',['../group__extended.html#gaf8e73efc2cbca9ebfdfb166983a04c17',1,'mimalloc-doc.h']]],
['mi_5fthread_5fstats_5fprint',['mi_thread_stats_print',['../group__extended.html#ga489670a15d1a257ab4639e645ee4612a',1,'mimalloc-doc.h']]], ['mi_5fthread_5fstats_5fprint_5fout',['mi_thread_stats_print_out',['../group__extended.html#gab1dac8476c46cb9eecab767eb40c1525',1,'mimalloc-doc.h']]],
['mi_5fusable_5fsize',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]], ['mi_5fusable_5fsize',['mi_usable_size',['../group__extended.html#ga089c859d9eddc5f9b4bd946cd53cebee',1,'mimalloc-doc.h']]],
['mi_5fvalloc',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]], ['mi_5fvalloc',['mi_valloc',['../group__posix.html#ga73baaf5951f5165ba0763d0c06b6a93b',1,'mimalloc-doc.h']]],
['mi_5fzalloc',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]], ['mi_5fzalloc',['mi_zalloc',['../group__malloc.html#gafdd9d8bb2986e668ba9884f28af38000',1,'mimalloc-doc.h']]],

View file

@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<link rel="stylesheet" type="text/css" href="search.css"/>
<script type="text/javascript" src="functions_1.js"></script>
<script type="text/javascript" src="search.js"></script>
</head>
<body class="SRPage">
<div id="SRIndex">
<div class="SRStatus" id="Loading">Loading...</div>
<div id="SRResults"></div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
createResults();
/* @license-end */
--></script>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
document.getElementById("Loading").style.display="none";
document.getElementById("NoMatches").style.display="none";
var searchResults = new SearchResults("searchResults");
searchResults.Search();
/* @license-end */
--></script>
</div>
</body>
</html>

View file

@ -0,0 +1,4 @@
var searchData=
[
['void',['void',['../group__extended.html#gadc49452cc1634aa03ac83ffe9b97a19c',1,'mimalloc-doc.h']]]
];

View file

@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['extended_20functions',['Extended Functions',['../group__extended.html',1,'']]] ['c_2b_2b_20wrappers',['C++ wrappers',['../group__cpp.html',1,'']]]
]; ];

View file

@ -1,5 +1,4 @@
var searchData= var searchData=
[ [
['heap_20introspection',['Heap Introspection',['../group__analysis.html',1,'']]], ['extended_20functions',['Extended Functions',['../group__extended.html',1,'']]]
['heap_20allocation',['Heap Allocation',['../group__heap.html',1,'']]]
]; ];

View file

@ -1,4 +1,5 @@
var searchData= var searchData=
[ [
['posix',['Posix',['../group__posix.html',1,'']]] ['heap_20introspection',['Heap Introspection',['../group__analysis.html',1,'']]],
['heap_20allocation',['Heap Allocation',['../group__heap.html',1,'']]]
]; ];

View file

@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['runtime_20options',['Runtime Options',['../group__options.html',1,'']]] ['posix',['Posix',['../group__posix.html',1,'']]]
]; ];

View file

@ -1,4 +1,4 @@
var searchData= var searchData=
[ [
['typed_20macros',['Typed Macros',['../group__typed.html',1,'']]] ['runtime_20options',['Runtime Options',['../group__options.html',1,'']]]
]; ];

30
docs/search/groups_7.html Normal file
View file

@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<link rel="stylesheet" type="text/css" href="search.css"/>
<script type="text/javascript" src="groups_7.js"></script>
<script type="text/javascript" src="search.js"></script>
</head>
<body class="SRPage">
<div id="SRIndex">
<div class="SRStatus" id="Loading">Loading...</div>
<div id="SRResults"></div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
createResults();
/* @license-end */
--></script>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
document.getElementById("Loading").style.display="none";
document.getElementById("NoMatches").style.display="none";
var searchResults = new SearchResults("searchResults");
searchResults.Search();
/* @license-end */
--></script>
</div>
</body>
</html>

4
docs/search/groups_7.js Normal file
View file

@ -0,0 +1,4 @@
var searchData=
[
['typed_20macros',['Typed Macros',['../group__typed.html',1,'']]]
];

30
docs/search/groups_8.html Normal file
View file

@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<link rel="stylesheet" type="text/css" href="search.css"/>
<script type="text/javascript" src="groups_8.js"></script>
<script type="text/javascript" src="search.js"></script>
</head>
<body class="SRPage">
<div id="SRIndex">
<div class="SRStatus" id="Loading">Loading...</div>
<div id="SRResults"></div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
createResults();
/* @license-end */
--></script>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
document.getElementById("Loading").style.display="none";
document.getElementById("NoMatches").style.display="none";
var searchResults = new SearchResults("searchResults");
searchResults.Search();
/* @license-end */
--></script>
</div>
</body>
</html>

4
docs/search/groups_8.js Normal file
View file

@ -0,0 +1,4 @@
var searchData=
[
['zero_20initialized_20re_2dallocation',['Zero initialized re-allocation',['../group__zeroinit.html',1,'']]]
];

30
docs/search/pages_4.html Normal file
View file

@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<link rel="stylesheet" type="text/css" href="search.css"/>
<script type="text/javascript" src="pages_4.js"></script>
<script type="text/javascript" src="search.js"></script>
</head>
<body class="SRPage">
<div id="SRIndex">
<div class="SRStatus" id="Loading">Loading...</div>
<div id="SRResults"></div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
createResults();
/* @license-end */
--></script>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
document.getElementById("Loading").style.display="none";
document.getElementById("NoMatches").style.display="none";
var searchResults = new SearchResults("searchResults");
searchResults.Search();
/* @license-end */
--></script>
</div>
</body>
</html>

4
docs/search/pages_4.js Normal file
View file

@ -0,0 +1,4 @@
var searchData=
[
['using_20the_20library',['Using the library',['../using.html',1,'']]]
];

View file

@ -7,7 +7,7 @@ var indexSectionsWithContent =
4: "m", 4: "m",
5: "m", 5: "m",
6: "_m", 6: "_m",
7: "abehprtz", 7: "abcehprtz",
8: "beopu" 8: "beopu"
}; };

View file

@ -1,7 +1,8 @@
var searchData= var searchData=
[ [
['mi_5fblock_5fvisit_5ffun',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]], ['mi_5fblock_5fvisit_5ffun',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
['mi_5fdeferred_5ffree_5ffun',['mi_deferred_free_fun',['../group__extended.html#ga22213691c3ce5ab4d91b24aff1023529',1,'mimalloc-doc.h']]], ['mi_5fdeferred_5ffree_5ffun',['mi_deferred_free_fun',['../group__extended.html#ga299dae78d25ce112e384a98b7309c5be',1,'mimalloc-doc.h']]],
['mi_5ferror_5ffun',['mi_error_fun',['../group__extended.html#ga251d369cda3f1c2a955c555486ed90e5',1,'mimalloc-doc.h']]],
['mi_5fheap_5ft',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]], ['mi_5fheap_5ft',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]],
['mi_5foutput_5ffun',['mi_output_fun',['../group__extended.html#ga2bed6d40b74591a67f81daea4b4a246f',1,'mimalloc-doc.h']]] ['mi_5foutput_5ffun',['mi_output_fun',['../group__extended.html#gad823d23444a4b77a40f66bf075a98a0c',1,'mimalloc-doc.h']]]
]; ];

View file

@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<link rel="stylesheet" type="text/css" href="search.css"/>
<script type="text/javascript" src="typedefs_1.js"></script>
<script type="text/javascript" src="search.js"></script>
</head>
<body class="SRPage">
<div id="SRIndex">
<div class="SRStatus" id="Loading">Loading...</div>
<div id="SRResults"></div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
createResults();
/* @license-end */
--></script>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
document.getElementById("Loading").style.display="none";
document.getElementById("NoMatches").style.display="none";
var searchResults = new SearchResults("searchResults");
searchResults.Search();
/* @license-end */
--></script>
</div>
</body>
</html>

View file

@ -0,0 +1,4 @@
var searchData=
[
['heartbeat',['heartbeat',['../group__extended.html#ga411f6e94394a2400aa460c796beff8d8',1,'mimalloc-doc.h']]]
];

View file

@ -0,0 +1,30 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html><head><title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.15"/>
<link rel="stylesheet" type="text/css" href="search.css"/>
<script type="text/javascript" src="typedefs_2.js"></script>
<script type="text/javascript" src="search.js"></script>
</head>
<body class="SRPage">
<div id="SRIndex">
<div class="SRStatus" id="Loading">Loading...</div>
<div id="SRResults"></div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
createResults();
/* @license-end */
--></script>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
<script type="text/javascript"><!--
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
document.getElementById("Loading").style.display="none";
document.getElementById("NoMatches").style.display="none";
var searchResults = new SearchResults("searchResults");
searchResults.Search();
/* @license-end */
--></script>
</div>
</body>
</html>

View file

@ -0,0 +1,5 @@
var searchData=
[
['mi_5fblock_5fvisit_5ffun',['mi_block_visit_fun',['../group__analysis.html#gadfa01e2900f0e5d515ad5506b26f6d65',1,'mimalloc-doc.h']]],
['mi_5fheap_5ft',['mi_heap_t',['../group__heap.html#ga34a47cde5a5b38c29f1aa3c5e76943c2',1,'mimalloc-doc.h']]]
];

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.0</span> &#160;<span id="projectnumber">1.4</span>
</div> </div>
</td> </td>
<td> <div id="MSearchBox" class="MSearchBoxInactive"> <td> <div id="MSearchBox" class="MSearchBoxInactive">
@ -102,7 +102,11 @@ $(document).ready(function(){initNavTree('using.html','');});
<div class="title">Using the library </div> </div> <div class="title">Using the library </div> </div>
</div><!--header--> </div><!--header-->
<div class="contents"> <div class="contents">
<div class="textblock"><p>The preferred usage is including <code>&lt;mimalloc.h&gt;</code>, linking with the shared- or static library, and using the <code>mi_malloc</code> API exclusively for allocation. For example, </p><div class="fragment"><div class="line">gcc -o myprogram -lmimalloc myfile.c</div></div><!-- fragment --><p>mimalloc uses only safe OS calls (<code>mmap</code> and <code>VirtualAlloc</code>) and can co-exist with other allocators linked to the same program. If you use <code>cmake</code>, you can simply use: </p><div class="fragment"><div class="line">find_package(mimalloc 1.0 REQUIRED)</div></div><!-- fragment --><p> in your <code>CMakeLists.txt</code> to find a locally installed mimalloc. Then use either: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc)</div></div><!-- fragment --><p> to link with the shared (dynamic) library, or: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc-<span class="keyword">static</span>)</div></div><!-- fragment --><p> to link with the static library. See <code>test\CMakeLists.txt</code> for an example.</p> <div class="textblock"><h3>Build</h3>
<p>The preferred usage is including <code>&lt;mimalloc.h&gt;</code>, linking with the shared- or static library, and using the <code>mi_malloc</code> API exclusively for allocation. For example, </p><div class="fragment"><div class="line">gcc -o myprogram -lmimalloc myfile.c</div></div><!-- fragment --><p>mimalloc uses only safe OS calls (<code>mmap</code> and <code>VirtualAlloc</code>) and can co-exist with other allocators linked to the same program. If you use <code>cmake</code>, you can simply use: </p><div class="fragment"><div class="line">find_package(mimalloc 1.0 REQUIRED)</div></div><!-- fragment --><p> in your <code>CMakeLists.txt</code> to find a locally installed mimalloc. Then use either: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc)</div></div><!-- fragment --><p> to link with the shared (dynamic) library, or: </p><div class="fragment"><div class="line">target_link_libraries(myapp PUBLIC mimalloc-<span class="keyword">static</span>)</div></div><!-- fragment --><p> to link with the static library. See <code>test\CMakeLists.txt</code> for an example.</p>
<h3>C++</h3>
<p>For best performance in C++ programs, it is also recommended to override the global <code>new</code> and <code>delete</code> operators. For convience, mimalloc provides <a href="https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h"><code>mimalloc-new-delete.h</code></a> which does this for you &ndash; just include it in a single(!) source file in your project.</p>
<p>In C++, mimalloc also provides the <code><a class="el" href="group__cpp.html#structmi__stl__allocator" title="std::allocator implementation for mimalloc for use in STL containers.">mi_stl_allocator</a></code> struct which implements the <code>std::allocator</code> interface. For example: </p><div class="fragment"><div class="line">std::vector&lt;some_struct, mi_stl_allocator&lt;some_struct&gt;&gt; vec;</div><div class="line">vec.push_back(some_struct());</div></div><!-- fragment --><h3>Statistics</h3>
<p>You can pass environment variables to print verbose messages (<code>MIMALLOC_VERBOSE=1</code>) and statistics (<code>MIMALLOC_SHOW_STATS=1</code>) (in the debug version): </p><div class="fragment"><div class="line">&gt; env MIMALLOC_SHOW_STATS=1 ./cfrac 175451865205073170563711388363</div><div class="line"></div><div class="line">175451865205073170563711388363 = 374456281610909315237213 * 468551</div><div class="line"></div><div class="line">heap stats: peak total freed unit</div><div class="line">normal 2: 16.4 kb 17.5 mb 17.5 mb 16 b ok</div><div class="line">normal 3: 16.3 kb 15.2 mb 15.2 mb 24 b ok</div><div class="line">normal 4: 64 b 4.6 kb 4.6 kb 32 b ok</div><div class="line">normal 5: 80 b 118.4 kb 118.4 kb 40 b ok</div><div class="line">normal 6: 48 b 48 b 48 b 48 b ok</div><div class="line">normal 17: 960 b 960 b 960 b 320 b ok</div><div class="line"></div><div class="line">heap stats: peak total freed unit</div><div class="line"> normal: 33.9 kb 32.8 mb 32.8 mb 1 b ok</div><div class="line"> huge: 0 b 0 b 0 b 1 b ok</div><div class="line"> total: 33.9 kb 32.8 mb 32.8 mb 1 b ok</div><div class="line">malloc requested: 32.8 mb</div><div class="line"></div><div class="line"> committed: 58.2 kb 58.2 kb 58.2 kb 1 b ok</div><div class="line"> reserved: 2.0 mb 2.0 mb 2.0 mb 1 b ok</div><div class="line"> reset: 0 b 0 b 0 b 1 b ok</div><div class="line"> segments: 1 1 1</div><div class="line">-abandoned: 0</div><div class="line"> pages: 6 6 6</div><div class="line">-abandoned: 0</div><div class="line"> mmaps: 3</div><div class="line"> mmap fast: 0</div><div class="line"> mmap slow: 1</div><div class="line"> threads: 0</div><div class="line"> elapsed: 2.022s</div><div class="line"> process: user: 1.781s, system: 0.016s, faults: 756, reclaims: 0, rss: 2.7 mb</div></div><!-- fragment --><p>The above model of using the <code>mi_</code> prefixed API is not always possible though in existing programs that already use the standard malloc interface, and another option is to override the standard malloc interface completely and redirect all calls to the <em>mimalloc</em> library instead.</p> <p>You can pass environment variables to print verbose messages (<code>MIMALLOC_VERBOSE=1</code>) and statistics (<code>MIMALLOC_SHOW_STATS=1</code>) (in the debug version): </p><div class="fragment"><div class="line">&gt; env MIMALLOC_SHOW_STATS=1 ./cfrac 175451865205073170563711388363</div><div class="line"></div><div class="line">175451865205073170563711388363 = 374456281610909315237213 * 468551</div><div class="line"></div><div class="line">heap stats: peak total freed unit</div><div class="line">normal 2: 16.4 kb 17.5 mb 17.5 mb 16 b ok</div><div class="line">normal 3: 16.3 kb 15.2 mb 15.2 mb 24 b ok</div><div class="line">normal 4: 64 b 4.6 kb 4.6 kb 32 b ok</div><div class="line">normal 5: 80 b 118.4 kb 118.4 kb 40 b ok</div><div class="line">normal 6: 48 b 48 b 48 b 48 b ok</div><div class="line">normal 17: 960 b 960 b 960 b 320 b ok</div><div class="line"></div><div class="line">heap stats: peak total freed unit</div><div class="line"> normal: 33.9 kb 32.8 mb 32.8 mb 1 b ok</div><div class="line"> huge: 0 b 0 b 0 b 1 b ok</div><div class="line"> total: 33.9 kb 32.8 mb 32.8 mb 1 b ok</div><div class="line">malloc requested: 32.8 mb</div><div class="line"></div><div class="line"> committed: 58.2 kb 58.2 kb 58.2 kb 1 b ok</div><div class="line"> reserved: 2.0 mb 2.0 mb 2.0 mb 1 b ok</div><div class="line"> reset: 0 b 0 b 0 b 1 b ok</div><div class="line"> segments: 1 1 1</div><div class="line">-abandoned: 0</div><div class="line"> pages: 6 6 6</div><div class="line">-abandoned: 0</div><div class="line"> mmaps: 3</div><div class="line"> mmap fast: 0</div><div class="line"> mmap slow: 1</div><div class="line"> threads: 0</div><div class="line"> elapsed: 2.022s</div><div class="line"> process: user: 1.781s, system: 0.016s, faults: 756, reclaims: 0, rss: 2.7 mb</div></div><!-- fragment --><p>The above model of using the <code>mi_</code> prefixed API is not always possible though in existing programs that already use the standard malloc interface, and another option is to override the standard malloc interface completely and redirect all calls to the <em>mimalloc</em> library instead.</p>
<p>See <a class="el" href="overrides.html">Overriding Malloc</a> for more info. </p> <p>See <a class="el" href="overrides.html">Overriding Malloc</a> for more info. </p>
</div></div><!-- PageDoc --> </div></div><!-- PageDoc -->

View file

@ -112,7 +112,7 @@
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling> <ExceptionHandling>Sync</ExceptionHandling>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
@ -95,7 +95,7 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -123,13 +123,13 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries> <IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries> </IgnoreSpecificDefaultLibraries>
<ModuleDefinitionFile> <ModuleDefinitionFile>
@ -152,7 +152,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput> <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation> <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<WholeProgramOptimization>false</WholeProgramOptimization> <WholeProgramOptimization>false</WholeProgramOptimization>
@ -184,7 +184,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput> <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation> <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<WholeProgramOptimization>false</WholeProgramOptimization> <WholeProgramOptimization>false</WholeProgramOptimization>
@ -195,7 +195,7 @@
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>$(ProjectDir)\..\..\bin\mimalloc-redirect.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile> <ModuleDefinitionFile>
</ModuleDefinitionFile> </ModuleDefinitionFile>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration> <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
@ -231,9 +231,10 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\alloc-posix.c" /> <ClCompile Include="..\..\src\alloc-posix.c" />
<ClCompile Include="..\..\src\alloc.c" /> <ClCompile Include="..\..\src\alloc.c" />
<ClCompile Include="..\..\src\arena.c" />
<ClCompile Include="..\..\src\heap.c" /> <ClCompile Include="..\..\src\heap.c" />
<ClCompile Include="..\..\src\init.c" /> <ClCompile Include="..\..\src\init.c" />
<ClCompile Include="..\..\src\memory.c" /> <ClCompile Include="..\..\src\region.c" />
<ClCompile Include="..\..\src\options.c" /> <ClCompile Include="..\..\src\options.c" />
<ClCompile Include="..\..\src\os.c" /> <ClCompile Include="..\..\src\os.c" />
<ClCompile Include="..\..\src\page-queue.c"> <ClCompile Include="..\..\src\page-queue.c">
@ -243,6 +244,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\page.c" /> <ClCompile Include="..\..\src\page.c" />
<ClCompile Include="..\..\src\random.c" />
<ClCompile Include="..\..\src\segment.c" /> <ClCompile Include="..\..\src\segment.c" />
<ClCompile Include="..\..\src\stats.c" /> <ClCompile Include="..\..\src\stats.c" />
</ItemGroup> </ItemGroup>

View file

@ -61,7 +61,7 @@
<ClCompile Include="..\..\src\init.c"> <ClCompile Include="..\..\src\init.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\memory.c"> <ClCompile Include="..\..\src\region.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\alloc-override.c"> <ClCompile Include="..\..\src\alloc-override.c">
@ -70,5 +70,11 @@
<ClCompile Include="..\..\src\alloc-posix.c"> <ClCompile Include="..\..\src\alloc-posix.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\arena.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\random.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -149,8 +149,8 @@
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="mimalloc-override.vcxproj"> <ProjectReference Include="mimalloc.vcxproj">
<Project>{abb5eae7-b3e6-432e-b636-333449892ea7}</Project> <Project>{abb5eae7-b3e6-432e-b636-333449892ea6}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
@ -90,6 +90,18 @@
<TargetExt>.lib</TargetExt> <TargetExt>.lib</TargetExt>
<TargetName>mimalloc-static</TargetName> <TargetName>mimalloc-static</TargetName>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="LLVM" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<UseLlvmLib>false</UseLlvmLib>
</PropertyGroup>
<PropertyGroup Label="LLVM" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<UseLlvmLib>false</UseLlvmLib>
</PropertyGroup>
<PropertyGroup Label="LLVM" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<UseLlvmLib>false</UseLlvmLib>
</PropertyGroup>
<PropertyGroup Label="LLVM" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<UseLlvmLib>false</UseLlvmLib>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
@ -97,7 +109,7 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
<CompileAs>CompileAsCpp</CompileAs> <CompileAs>CompileAsCpp</CompileAs>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
@ -111,12 +123,12 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
<CompileAs>CompileAsCpp</CompileAs> <CompileAs>CompileAsCpp</CompileAs>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
@ -143,7 +155,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput> <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation> <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<WholeProgramOptimization>false</WholeProgramOptimization> <WholeProgramOptimization>false</WholeProgramOptimization>
@ -165,12 +177,12 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization> <Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions> <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
<AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput> <AssemblerOutput>AssemblyAndSourceCode</AssemblerOutput>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation> <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<WholeProgramOptimization>false</WholeProgramOptimization> <WholeProgramOptimization>false</WholeProgramOptimization>
@ -217,9 +229,10 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\alloc-posix.c" /> <ClCompile Include="..\..\src\alloc-posix.c" />
<ClCompile Include="..\..\src\alloc.c" /> <ClCompile Include="..\..\src\alloc.c" />
<ClCompile Include="..\..\src\arena.c" />
<ClCompile Include="..\..\src\heap.c" /> <ClCompile Include="..\..\src\heap.c" />
<ClCompile Include="..\..\src\init.c" /> <ClCompile Include="..\..\src\init.c" />
<ClCompile Include="..\..\src\memory.c" /> <ClCompile Include="..\..\src\region.c" />
<ClCompile Include="..\..\src\options.c" /> <ClCompile Include="..\..\src\options.c" />
<ClCompile Include="..\..\src\page-queue.c"> <ClCompile Include="..\..\src\page-queue.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@ -228,6 +241,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\page.c" /> <ClCompile Include="..\..\src\page.c" />
<ClCompile Include="..\..\src\random.c" />
<ClCompile Include="..\..\src\segment.c" /> <ClCompile Include="..\..\src\segment.c" />
<ClCompile Include="..\..\src\os.c" /> <ClCompile Include="..\..\src\os.c" />
<ClCompile Include="..\..\src\stats.c" /> <ClCompile Include="..\..\src\stats.c" />

View file

@ -47,12 +47,18 @@
<ClCompile Include="..\..\src\init.c"> <ClCompile Include="..\..\src\init.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\memory.c"> <ClCompile Include="..\..\src\region.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\alloc-posix.c"> <ClCompile Include="..\..\src\alloc-posix.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\arena.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\random.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h"> <ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h">

View file

@ -90,7 +90,7 @@
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling> <ExceptionHandling>Sync</ExceptionHandling>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>
@ -112,7 +112,7 @@
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<ExceptionHandling>false</ExceptionHandling> <ExceptionHandling>Sync</ExceptionHandling>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
</ClCompile> </ClCompile>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
@ -123,7 +123,7 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);</PreprocessorDefinitions> <PreprocessorDefinitions>MI_DEBUG=3;MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
<CompileAs>Default</CompileAs> <CompileAs>Default</CompileAs>
@ -231,9 +231,13 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\alloc-posix.c" /> <ClCompile Include="..\..\src\alloc-posix.c" />
<ClCompile Include="..\..\src\alloc.c" /> <ClCompile Include="..\..\src\alloc.c" />
<ClCompile Include="..\..\src\arena.c" />
<ClCompile Include="..\..\src\bitmap.inc.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\heap.c" /> <ClCompile Include="..\..\src\heap.c" />
<ClCompile Include="..\..\src\init.c" /> <ClCompile Include="..\..\src\init.c" />
<ClCompile Include="..\..\src\memory.c" /> <ClCompile Include="..\..\src\region.c" />
<ClCompile Include="..\..\src\options.c" /> <ClCompile Include="..\..\src\options.c" />
<ClCompile Include="..\..\src\os.c" /> <ClCompile Include="..\..\src\os.c" />
<ClCompile Include="..\..\src\page-queue.c"> <ClCompile Include="..\..\src\page-queue.c">
@ -243,6 +247,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\page.c" /> <ClCompile Include="..\..\src\page.c" />
<ClCompile Include="..\..\src\random.c" />
<ClCompile Include="..\..\src\segment.c" /> <ClCompile Include="..\..\src\segment.c" />
<ClCompile Include="..\..\src\stats.c" /> <ClCompile Include="..\..\src\stats.c" />
</ItemGroup> </ItemGroup>

View file

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\..\src\alloc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\alloc-aligned.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\alloc-override.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\alloc-posix.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\heap.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\init.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\region.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\os.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\page.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\page-queue.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\segment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\stats.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\arena.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\bitmap.inc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\random.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\options.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\mimalloc-atomic.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-internal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\mimalloc-new-delete.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\mimalloc-override.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\mimalloc-types.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{f1fccf27-17b9-42dd-ba51-6070baff85c6}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{39cb7e38-69d0-43fb-8406-6a0f7cefc3b4}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View file

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{FFF7958F-750E-4C21-A04D-22707CC66878}</ProjectGuid>
<RootNamespace>mimalloc-test-api</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>mimalloc-test-api</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)..\..\out\msvc-$(Platform)\$(ProjectName)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\test\test-api.c">
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="mimalloc.vcxproj">
<Project>{abb5eae7-b3e6-432e-b636-333449892ea6}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -149,8 +149,8 @@
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="mimalloc-override.vcxproj"> <ProjectReference Include="mimalloc.vcxproj">
<Project>{abb5eae7-b3e6-432e-b636-333449892ea7}</Project> <Project>{abb5eae7-b3e6-432e-b636-333449892ea6}</Project>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View file

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.28010.2016 VisualStudioVersion = 16.0.29709.97
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc", "mimalloc.vcxproj", "{ABB5EAE7-B3E6-432E-B636-333449892EA6}"
EndProject EndProject
@ -13,6 +13,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-override-test", "m
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-stress", "mimalloc-test-stress.vcxproj", "{FEF7958F-750E-4C21-A04D-22707CC66878}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-stress", "mimalloc-test-stress.vcxproj", "{FEF7958F-750E-4C21-A04D-22707CC66878}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mimalloc-test-api", "mimalloc-test-api.vcxproj", "{FFF7958F-750E-4C21-A04D-22707CC66878}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
@ -61,6 +63,14 @@ Global
{FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64 {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64
{FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32 {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32
{FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32 {FEF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32
{FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.ActiveCfg = Debug|x64
{FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x64.Build.0 = Debug|x64
{FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.ActiveCfg = Debug|Win32
{FFF7958F-750E-4C21-A04D-22707CC66878}.Debug|x86.Build.0 = Debug|Win32
{FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.ActiveCfg = Release|x64
{FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x64.Build.0 = Release|x64
{FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.ActiveCfg = Release|Win32
{FFF7958F-750E-4C21-A04D-22707CC66878}.Release|x86.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
@ -100,7 +100,7 @@
<PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions> <PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
<CompileAs>CompileAsCpp</CompileAs> <CompileAs>CompileAsCpp</CompileAs>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>Default</LanguageStandard>
</ClCompile> </ClCompile>
<Lib> <Lib>
<AdditionalLibraryDirectories> <AdditionalLibraryDirectories>
@ -111,7 +111,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
@ -119,7 +119,7 @@
<PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions> <PreprocessorDefinitions>MI_DEBUG=3;%(PreprocessorDefinitions);</PreprocessorDefinitions>
<CompileAs>CompileAsCpp</CompileAs> <CompileAs>CompileAsCpp</CompileAs>
<SupportJustMyCode>false</SupportJustMyCode> <SupportJustMyCode>false</SupportJustMyCode>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>Default</LanguageStandard>
</ClCompile> </ClCompile>
<PostBuildEvent> <PostBuildEvent>
<Command> <Command>
@ -151,6 +151,7 @@
<InlineFunctionExpansion>Default</InlineFunctionExpansion> <InlineFunctionExpansion>Default</InlineFunctionExpansion>
<CompileAs>CompileAsCpp</CompileAs> <CompileAs>CompileAsCpp</CompileAs>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<LanguageStandard>Default</LanguageStandard>
</ClCompile> </ClCompile>
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
@ -178,6 +179,7 @@
<InlineFunctionExpansion>Default</InlineFunctionExpansion> <InlineFunctionExpansion>Default</InlineFunctionExpansion>
<CompileAs>CompileAsCpp</CompileAs> <CompileAs>CompileAsCpp</CompileAs>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<LanguageStandard>Default</LanguageStandard>
</ClCompile> </ClCompile>
<Link> <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
@ -217,9 +219,13 @@
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\alloc-posix.c" /> <ClCompile Include="..\..\src\alloc-posix.c" />
<ClCompile Include="..\..\src\alloc.c" /> <ClCompile Include="..\..\src\alloc.c" />
<ClCompile Include="..\..\src\arena.c" />
<ClCompile Include="..\..\src\bitmap.inc.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\heap.c" /> <ClCompile Include="..\..\src\heap.c" />
<ClCompile Include="..\..\src\init.c" /> <ClCompile Include="..\..\src\init.c" />
<ClCompile Include="..\..\src\memory.c" /> <ClCompile Include="..\..\src\region.c" />
<ClCompile Include="..\..\src\options.c" /> <ClCompile Include="..\..\src\options.c" />
<ClCompile Include="..\..\src\page-queue.c"> <ClCompile Include="..\..\src\page-queue.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@ -228,6 +234,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\page.c" /> <ClCompile Include="..\..\src\page.c" />
<ClCompile Include="..\..\src\random.c" />
<ClCompile Include="..\..\src\segment.c" /> <ClCompile Include="..\..\src\segment.c" />
<ClCompile Include="..\..\src\os.c" /> <ClCompile Include="..\..\src\os.c" />
<ClCompile Include="..\..\src\stats.c" /> <ClCompile Include="..\..\src\stats.c" />

View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\..\src\alloc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\alloc-aligned.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\alloc-override.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\alloc-override-osx.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\alloc-posix.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\heap.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\init.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\region.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\options.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\os.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\page.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\page-queue.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\segment.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\stats.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\arena.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\bitmap.inc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\src\random.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-atomic.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-internal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\mimalloc-new-delete.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-override.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(ProjectDir)..\..\include\mimalloc-types.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{2b556b10-f559-4b2d-896e-142652adbf0c}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{852a14ae-6dde-4e95-8077-ca705e97e5af}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View file

@ -23,18 +23,22 @@ terms of the MIT license. A copy of the license can be found in the file
#include <stdatomic.h> #include <stdatomic.h>
#endif #endif
#define mi_atomic_cast(tp,x) (volatile _Atomic(tp)*)(x)
// ------------------------------------------------------ // ------------------------------------------------------
// Atomic operations specialized for mimalloc // Atomic operations specialized for mimalloc
// ------------------------------------------------------ // ------------------------------------------------------
// Atomically add a 64-bit value; returns the previous value. // Atomically add a 64-bit value; returns the previous value.
// Note: not using _Atomic(int64_t) as it is only used for statistics. // Note: not using _Atomic(int64_t) as it is only used for statistics.
static inline void mi_atomic_add64(volatile int64_t* p, int64_t add); static inline void mi_atomic_addi64(volatile int64_t* p, int64_t add);
// Atomically add a value; returns the previous value. Memory ordering is relaxed. // Atomically add a value; returns the previous value. Memory ordering is relaxed.
static inline intptr_t mi_atomic_add(volatile _Atomic(intptr_t)* p, intptr_t add); static inline uintptr_t mi_atomic_add(volatile _Atomic(uintptr_t)* p, uintptr_t add);
// Atomically "and" a value; returns the previous value. Memory ordering is relaxed.
static inline uintptr_t mi_atomic_and(volatile _Atomic(uintptr_t)* p, uintptr_t x);
// Atomically "or" a value; returns the previous value. Memory ordering is relaxed.
static inline uintptr_t mi_atomic_or(volatile _Atomic(uintptr_t)* p, uintptr_t x);
// Atomically compare and exchange a value; returns `true` if successful. // Atomically compare and exchange a value; returns `true` if successful.
// May fail spuriously. Memory ordering as release on success, and relaxed on failure. // May fail spuriously. Memory ordering as release on success, and relaxed on failure.
@ -62,57 +66,57 @@ static inline void mi_atomic_write(volatile _Atomic(uintptr_t)* p, uintptr_t x);
static inline void mi_atomic_yield(void); static inline void mi_atomic_yield(void);
// Atomically add a value; returns the previous value.
static inline uintptr_t mi_atomic_addu(volatile _Atomic(uintptr_t)* p, uintptr_t add) {
return (uintptr_t)mi_atomic_add((volatile _Atomic(intptr_t)*)p, (intptr_t)add);
}
// Atomically subtract a value; returns the previous value. // Atomically subtract a value; returns the previous value.
static inline uintptr_t mi_atomic_subu(volatile _Atomic(uintptr_t)* p, uintptr_t sub) { static inline uintptr_t mi_atomic_sub(volatile _Atomic(uintptr_t)* p, uintptr_t sub) {
return (uintptr_t)mi_atomic_add((volatile _Atomic(intptr_t)*)p, -((intptr_t)sub)); return mi_atomic_add(p, (uintptr_t)(-((intptr_t)sub)));
} }
// Atomically increment a value; returns the incremented result. // Atomically increment a value; returns the incremented result.
static inline uintptr_t mi_atomic_increment(volatile _Atomic(uintptr_t)* p) { static inline uintptr_t mi_atomic_increment(volatile _Atomic(uintptr_t)* p) {
return mi_atomic_addu(p, 1); return mi_atomic_add(p, 1);
} }
// Atomically decrement a value; returns the decremented result. // Atomically decrement a value; returns the decremented result.
static inline uintptr_t mi_atomic_decrement(volatile _Atomic(uintptr_t)* p) { static inline uintptr_t mi_atomic_decrement(volatile _Atomic(uintptr_t)* p) {
return mi_atomic_subu(p, 1); return mi_atomic_sub(p, 1);
} }
// Atomically read a pointer; Memory order is relaxed. // Atomically add a signed value; returns the previous value.
static inline void* mi_atomic_read_ptr_relaxed(volatile _Atomic(void*) const * p) { static inline intptr_t mi_atomic_addi(volatile _Atomic(intptr_t)* p, intptr_t add) {
return (void*)mi_atomic_read_relaxed((const volatile _Atomic(uintptr_t)*)p); return (intptr_t)mi_atomic_add((volatile _Atomic(uintptr_t)*)p, (uintptr_t)add);
} }
// Atomically subtract a signed value; returns the previous value.
static inline intptr_t mi_atomic_subi(volatile _Atomic(intptr_t)* p, intptr_t sub) {
return (intptr_t)mi_atomic_addi(p,-sub);
}
// Atomically read a pointer; Memory order is relaxed (i.e. no fence, only atomic).
#define mi_atomic_read_ptr_relaxed(T,p) \
(T*)(mi_atomic_read_relaxed((const volatile _Atomic(uintptr_t)*)(p)))
// Atomically read a pointer; Memory order is acquire. // Atomically read a pointer; Memory order is acquire.
static inline void* mi_atomic_read_ptr(volatile _Atomic(void*) const * p) { #define mi_atomic_read_ptr(T,p) \
return (void*)mi_atomic_read((const volatile _Atomic(uintptr_t)*)p); (T*)(mi_atomic_read((const volatile _Atomic(uintptr_t)*)(p)))
}
// Atomically write a pointer // Atomically write a pointer; Memory order is acquire.
static inline void mi_atomic_write_ptr(volatile _Atomic(void*)* p, void* x) { #define mi_atomic_write_ptr(T,p,x) \
mi_atomic_write((volatile _Atomic(uintptr_t)*)p, (uintptr_t)x ); mi_atomic_write((volatile _Atomic(uintptr_t)*)(p), (uintptr_t)((T*)x))
}
// Atomically compare and exchange a pointer; returns `true` if successful. May fail spuriously. // Atomically compare and exchange a pointer; returns `true` if successful. May fail spuriously.
// Memory order is release. (like a write)
// (Note: expected and desired are in opposite order from atomic_compare_exchange) // (Note: expected and desired are in opposite order from atomic_compare_exchange)
static inline bool mi_atomic_cas_ptr_weak(volatile _Atomic(void*)* p, void* desired, void* expected) { #define mi_atomic_cas_ptr_weak(T,p,desired,expected) \
return mi_atomic_cas_weak((volatile _Atomic(uintptr_t)*)p, (uintptr_t)desired, (uintptr_t)expected); mi_atomic_cas_weak((volatile _Atomic(uintptr_t)*)(p), (uintptr_t)((T*)(desired)), (uintptr_t)((T*)(expected)))
}
// Atomically compare and exchange a pointer; returns `true` if successful. // Atomically compare and exchange a pointer; returns `true` if successful. Memory order is acquire_release.
// (Note: expected and desired are in opposite order from atomic_compare_exchange) // (Note: expected and desired are in opposite order from atomic_compare_exchange)
static inline bool mi_atomic_cas_ptr_strong(volatile _Atomic(void*)* p, void* desired, void* expected) { #define mi_atomic_cas_ptr_strong(T,p,desired,expected) \
return mi_atomic_cas_strong((volatile _Atomic(uintptr_t)*)p, (uintptr_t)desired, (uintptr_t)expected); mi_atomic_cas_strong((volatile _Atomic(uintptr_t)*)(p),(uintptr_t)((T*)(desired)), (uintptr_t)((T*)(expected)))
}
// Atomically exchange a pointer value. // Atomically exchange a pointer value.
static inline void* mi_atomic_exchange_ptr(volatile _Atomic(void*)* p, void* exchange) { #define mi_atomic_exchange_ptr(T,p,exchange) \
return (void*)mi_atomic_exchange((volatile _Atomic(uintptr_t)*)p, (uintptr_t)exchange); (T*)mi_atomic_exchange((volatile _Atomic(uintptr_t)*)(p), (uintptr_t)((T*)exchange))
}
#ifdef _MSC_VER #ifdef _MSC_VER
@ -121,38 +125,48 @@ static inline void* mi_atomic_exchange_ptr(volatile _Atomic(void*)* p, void* exc
#include <intrin.h> #include <intrin.h>
#ifdef _WIN64 #ifdef _WIN64
typedef LONG64 msc_intptr_t; typedef LONG64 msc_intptr_t;
#define RC64(f) f##64 #define MI_64(f) f##64
#else #else
typedef LONG msc_intptr_t; typedef LONG msc_intptr_t;
#define RC64(f) f #define MI_64(f) f
#endif #endif
static inline intptr_t mi_atomic_add(volatile _Atomic(intptr_t)* p, intptr_t add) { static inline uintptr_t mi_atomic_add(volatile _Atomic(uintptr_t)* p, uintptr_t add) {
return (intptr_t)RC64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, (msc_intptr_t)add); return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, (msc_intptr_t)add);
}
static inline uintptr_t mi_atomic_and(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
return (uintptr_t)MI_64(_InterlockedAnd)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
}
static inline uintptr_t mi_atomic_or(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
return (uintptr_t)MI_64(_InterlockedOr)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
} }
static inline bool mi_atomic_cas_strong(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) { static inline bool mi_atomic_cas_strong(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) {
return (expected == RC64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)expected)); return (expected == (uintptr_t)MI_64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)expected));
} }
static inline bool mi_atomic_cas_weak(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) { static inline bool mi_atomic_cas_weak(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) {
return mi_atomic_cas_strong(p,desired,expected); return mi_atomic_cas_strong(p,desired,expected);
} }
static inline uintptr_t mi_atomic_exchange(volatile _Atomic(uintptr_t)* p, uintptr_t exchange) { static inline uintptr_t mi_atomic_exchange(volatile _Atomic(uintptr_t)* p, uintptr_t exchange) {
return (uintptr_t)RC64(_InterlockedExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)exchange); return (uintptr_t)MI_64(_InterlockedExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)exchange);
} }
static inline uintptr_t mi_atomic_read(volatile _Atomic(uintptr_t) const* p) { static inline uintptr_t mi_atomic_read(volatile _Atomic(uintptr_t) const* p) {
return *p; return *p;
} }
static inline uintptr_t mi_atomic_read_relaxed(volatile _Atomic(uintptr_t) const* p) { static inline uintptr_t mi_atomic_read_relaxed(volatile _Atomic(uintptr_t) const* p) {
return mi_atomic_read(p); return *p;
} }
static inline void mi_atomic_write(volatile _Atomic(uintptr_t)* p, uintptr_t x) { static inline void mi_atomic_write(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
#if defined(_M_IX86) || defined(_M_X64)
*p = x;
#else
mi_atomic_exchange(p,x); mi_atomic_exchange(p,x);
#endif
} }
static inline void mi_atomic_yield(void) { static inline void mi_atomic_yield(void) {
YieldProcessor(); YieldProcessor();
} }
static inline void mi_atomic_add64(volatile _Atomic(int64_t)* p, int64_t add) { static inline void mi_atomic_addi64(volatile _Atomic(int64_t)* p, int64_t add) {
#ifdef _WIN64 #ifdef _WIN64
mi_atomic_add(p,add); mi_atomic_addi(p,add);
#else #else
int64_t current; int64_t current;
int64_t sum; int64_t sum;
@ -169,14 +183,22 @@ static inline void mi_atomic_add64(volatile _Atomic(int64_t)* p, int64_t add) {
#else #else
#define MI_USING_STD #define MI_USING_STD
#endif #endif
static inline void mi_atomic_add64(volatile int64_t* p, int64_t add) { static inline void mi_atomic_addi64(volatile int64_t* p, int64_t add) {
MI_USING_STD MI_USING_STD
atomic_fetch_add_explicit((volatile _Atomic(int64_t)*)p, add, memory_order_relaxed); atomic_fetch_add_explicit((volatile _Atomic(int64_t)*)p, add, memory_order_relaxed);
} }
static inline intptr_t mi_atomic_add(volatile _Atomic(intptr_t)* p, intptr_t add) { static inline uintptr_t mi_atomic_add(volatile _Atomic(uintptr_t)* p, uintptr_t add) {
MI_USING_STD MI_USING_STD
return atomic_fetch_add_explicit(p, add, memory_order_relaxed); return atomic_fetch_add_explicit(p, add, memory_order_relaxed);
} }
static inline uintptr_t mi_atomic_and(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
MI_USING_STD
return atomic_fetch_and_explicit(p, x, memory_order_relaxed);
}
static inline uintptr_t mi_atomic_or(volatile _Atomic(uintptr_t)* p, uintptr_t x) {
MI_USING_STD
return atomic_fetch_or_explicit(p, x, memory_order_relaxed);
}
static inline bool mi_atomic_cas_weak(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) { static inline bool mi_atomic_cas_weak(volatile _Atomic(uintptr_t)* p, uintptr_t desired, uintptr_t expected) {
MI_USING_STD MI_USING_STD
return atomic_compare_exchange_weak_explicit(p, &expected, desired, memory_order_release, memory_order_relaxed); return atomic_compare_exchange_weak_explicit(p, &expected, desired, memory_order_release, memory_order_relaxed);
@ -220,7 +242,7 @@ static inline void mi_atomic_write(volatile _Atomic(uintptr_t)* p, uintptr_t x)
#endif #endif
#elif defined(__wasi__) #elif defined(__wasi__)
#include <sched.h> #include <sched.h>
static inline void mi_atomic_yield() { static inline void mi_atomic_yield(void) {
sched_yield(); sched_yield();
} }
#else #else

View file

@ -0,0 +1,722 @@
/* ----------------------------------------------------------------------------
Copyright (c) 2019, Microsoft Research, Daan Leijen
This is free software; you can redistribute it and/or modify it under the
terms of the MIT license. A copy of the license can be found in the file
"LICENSE" at the root of this distribution.
-----------------------------------------------------------------------------*/
#pragma once
#ifndef MIMALLOC_INTERNAL_TLD_H
#define MIMALLOC_INTERNAL_TLD_H
#include "mimalloc-types.h"
#include "mimalloc-internal.h"
#define MI_TLD_DECL 1 // thread local declaration
#define MI_TLD_PTHREAD 2 // ptrhead_get/setspecific
#define MI_TLD_DECL_GUARD 3 // thread local + recursion guard at initial load
#define MI_TLD_PTHREAD_GUARD 4 // ptrhead_get/setspecific + recursion guard at initial load
#define MI_TLD_SLOT 5 // steal slot from OS thread local predefined slots
#define MI_TLD_PTHREAD_SLOT 6 // steal slot from pthread structure (usually `retval`)
#if !defined(MI_TLD)
#if defined(_MSC_VER) || defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
// on windows and linux/freeBSD/netBSD (with initial-exec) a __thread always works without recursion into malloc
#define MI_TLD MI_TLD_DECL
#elif !defined(MI_MIMALLOC_OVERRIDE)
// if not overriding, __thread declarations should be fine (use MI_TLD_PTHREAD if your OS does not have __thread)
#define MI_TLD MI_TLD_DECL
#elif // defined(MI_MALLOC_OVERRIDE)
// if overriding, some BSD variants allocate when accessing a thread local the first time
#if defined(__APPLE__)
#define MI_TLD MI_TLD_SLOT
#define MI_TLD_SLOT_NUM 89 // seems unused? (__PTK_FRAMEWORK_OLDGC_KEY9) see <https://github.com/rweichler/substrate/blob/master/include/pthread_machdep.h>
// possibly unused ones are 9, 29, __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 (94), __PTK_FRAMEWORK_GC_KEY9 (112) and __PTK_FRAMEWORK_OLDGC_KEY9 (89)
// #define MI_TLD MI_TLD_PTHREAD_SLOT
// #define MI_TLD_PTHREAD_SLOT_OFS (2*sizeof(void*) + sizeof(long) + 2*sizeof(void*) /*TAILQ*/) // offset `tl_exit_value` <https://github.com/apple/darwin-libpthread/blob/master/src/internal.h#L184>
#elif defined(__OpenBSD__)
#define MI_TLD MI_TLD_PTHREAD_SLOT
#define MI_TLD_PTHREAD_SLOT_OFS (6*sizeof(int) + 1*sizeof(void*)) // offset `retval` <https://github.com/openbsd/src/blob/master/lib/libc/include/thread_private.h#L371>
#elif defined(__DragonFly__)
#define MI_TLD MI_TLD_PTHREAD_SLOT
#define MI_TLD_PTHREAD_SLOT_OFS (4 + 1*sizeof(void*)) // offset `uniqueid` (also used by gdb?) <https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/lib/libthread_xu/thread/thr_private.h#L458>
#endif
#endif
#endif
#if (MI_DEBUG>0)
#define mi_trace_message(...) _mi_trace_message(__VA_ARGS__)
#else
#define mi_trace_message(...)
#endif
#define MI_CACHE_LINE 64
#if defined(_MSC_VER)
#pragma warning(disable:4127) // suppress constant conditional warning (due to MI_SECURE paths)
#define mi_decl_noinline __declspec(noinline)
#define mi_decl_thread __declspec(thread)
#define mi_decl_cache_align __declspec(align(MI_CACHE_LINE))
#elif (defined(__GNUC__) && (__GNUC__>=3)) // includes clang and icc
#define mi_decl_noinline __attribute__((noinline))
#define mi_decl_thread __thread
#define mi_decl_cache_align __attribute__((aligned(MI_CACHE_LINE)))
#else
#define mi_decl_noinline
#define mi_decl_thread __thread // hope for the best :-)
#define mi_decl_cache_align
#endif
// "options.c"
void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message);
void _mi_fprintf(mi_output_fun* out, void* arg, const char* fmt, ...);
void _mi_warning_message(const char* fmt, ...);
void _mi_verbose_message(const char* fmt, ...);
void _mi_trace_message(const char* fmt, ...);
void _mi_options_init(void);
void _mi_error_message(int err, const char* fmt, ...);
// random.c
void _mi_random_init(mi_random_ctx_t* ctx);
void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* new_ctx);
uintptr_t _mi_random_next(mi_random_ctx_t* ctx);
uintptr_t _mi_heap_random_next(mi_heap_t* heap);
uintptr_t _os_random_weak(uintptr_t extra_seed);
static inline uintptr_t _mi_random_shuffle(uintptr_t x);
// init.c
extern mi_stats_t _mi_stats_main;
extern const mi_page_t _mi_page_empty;
bool _mi_is_main_thread(void);
bool _mi_preloading(); // true while the C runtime is not ready
// os.c
size_t _mi_os_page_size(void);
void _mi_os_init(void); // called from process init
void* _mi_os_alloc(size_t size, mi_stats_t* stats); // to allocate thread local data
void _mi_os_free(void* p, size_t size, mi_stats_t* stats); // to free thread local data
size_t _mi_os_good_alloc_size(size_t size);
// memory.c
void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* id, mi_os_tld_t* tld);
void _mi_mem_free(void* p, size_t size, size_t id, bool fully_committed, bool any_reset, mi_os_tld_t* tld);
bool _mi_mem_reset(void* p, size_t size, mi_os_tld_t* tld);
bool _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld);
bool _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld);
bool _mi_mem_protect(void* addr, size_t size);
bool _mi_mem_unprotect(void* addr, size_t size);
void _mi_mem_collect(mi_os_tld_t* tld);
// "segment.c"
mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_wsize, mi_segments_tld_t* tld, mi_os_tld_t* os_tld);
void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld);
void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld);
uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size, size_t* pre_size); // page start for any page
void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block);
void _mi_segment_thread_collect(mi_segments_tld_t* tld);
void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld);
void _mi_abandoned_await_readers(void);
// "page.c"
void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc;
void _mi_page_retire(mi_page_t* page); // free the page if there are no other pages with many free blocks
void _mi_page_unfull(mi_page_t* page);
void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force); // free the page
void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq); // abandon the page, to be picked up by another thread...
void _mi_heap_delayed_free(mi_heap_t* heap);
void _mi_heap_collect_retired(mi_heap_t* heap, bool force);
void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never);
size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append);
void _mi_deferred_free(mi_heap_t* heap, bool force);
void _mi_page_free_collect(mi_page_t* page,bool force);
void _mi_page_reclaim(mi_heap_t* heap, mi_page_t* page); // callback from segments
size_t _mi_bin_size(uint8_t bin); // for stats
uint8_t _mi_bin(size_t size); // for stats
uint8_t _mi_bsr(uintptr_t x); // bit-scan-right, used on BSD in "os.c"
// "heap.c"
void _mi_heap_destroy_pages(mi_heap_t* heap);
void _mi_heap_collect_abandon(mi_heap_t* heap);
void _mi_heap_set_default_direct(mi_heap_t* heap);
// "stats.c"
void _mi_stats_done(mi_stats_t* stats);
mi_msecs_t _mi_clock_now(void);
mi_msecs_t _mi_clock_end(mi_msecs_t start);
mi_msecs_t _mi_clock_start(void);
// "alloc.c"
void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept; // called from `_mi_malloc_generic`
void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero);
void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero);
mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* page, const void* p);
bool _mi_free_delayed_block(mi_block_t* block);
void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size);
#if MI_DEBUG>1
bool _mi_page_is_valid(mi_page_t* page);
#endif
// ------------------------------------------------------
// Branches
// ------------------------------------------------------
#if defined(__GNUC__) || defined(__clang__)
#define mi_unlikely(x) __builtin_expect((x),0)
#define mi_likely(x) __builtin_expect((x),1)
#else
#define mi_unlikely(x) (x)
#define mi_likely(x) (x)
#endif
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
/* -----------------------------------------------------------
Error codes passed to `_mi_fatal_error`
All are recoverable but EFAULT is a serious error and aborts by default in secure mode.
For portability define undefined error codes using common Unix codes:
<https://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html>
----------------------------------------------------------- */
#include <errno.h>
#ifndef EAGAIN // double free
#define EAGAIN (11)
#endif
#ifndef ENOMEM // out of memory
#define ENOMEM (12)
#endif
#ifndef EFAULT // corrupted free-list or meta-data
#define EFAULT (14)
#endif
#ifndef EINVAL // trying to free an invalid pointer
#define EINVAL (22)
#endif
#ifndef EOVERFLOW // count*size overflow
#define EOVERFLOW (75)
#endif
/* -----------------------------------------------------------
Inlined definitions
----------------------------------------------------------- */
#define UNUSED(x) (void)(x)
#if (MI_DEBUG>0)
#define UNUSED_RELEASE(x)
#else
#define UNUSED_RELEASE(x) UNUSED(x)
#endif
#define MI_INIT4(x) x(),x(),x(),x()
#define MI_INIT8(x) MI_INIT4(x),MI_INIT4(x)
#define MI_INIT16(x) MI_INIT8(x),MI_INIT8(x)
#define MI_INIT32(x) MI_INIT16(x),MI_INIT16(x)
#define MI_INIT64(x) MI_INIT32(x),MI_INIT32(x)
#define MI_INIT128(x) MI_INIT64(x),MI_INIT64(x)
#define MI_INIT256(x) MI_INIT128(x),MI_INIT128(x)
// Is `x` a power of two? (0 is considered a power of two)
static inline bool _mi_is_power_of_two(uintptr_t x) {
return ((x & (x - 1)) == 0);
}
// Align upwards
static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) {
mi_assert_internal(alignment != 0);
uintptr_t mask = alignment - 1;
if ((alignment & mask) == 0) { // power of two?
return ((sz + mask) & ~mask);
}
else {
return (((sz + mask)/alignment)*alignment);
}
}
// Divide upwards: `s <= _mi_divide_up(s,d)*d < s+d`.
static inline uintptr_t _mi_divide_up(uintptr_t size, size_t divider) {
mi_assert_internal(divider != 0);
return (divider == 0 ? size : ((size + divider - 1) / divider));
}
// Is memory zero initialized?
static inline bool mi_mem_is_zero(void* p, size_t size) {
for (size_t i = 0; i < size; i++) {
if (((uint8_t*)p)[i] != 0) return false;
}
return true;
}
// Align a byte size to a size in _machine words_,
// i.e. byte size == `wsize*sizeof(void*)`.
static inline size_t _mi_wsize_from_size(size_t size) {
mi_assert_internal(size <= SIZE_MAX - sizeof(uintptr_t));
return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
}
// Overflow detecting multiply
static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) {
#if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5
#include <limits.h> // UINT_MAX, ULONG_MAX
#if (SIZE_MAX == UINT_MAX)
return __builtin_umul_overflow(count, size, total);
#elif (SIZE_MAX == ULONG_MAX)
return __builtin_umull_overflow(count, size, total);
#else
return __builtin_umulll_overflow(count, size, total);
#endif
#else /* __builtin_umul_overflow is unavailable */
#define MI_MUL_NO_OVERFLOW ((size_t)1 << (4*sizeof(size_t))) // sqrt(SIZE_MAX)
*total = count * size;
return ((size >= MI_MUL_NO_OVERFLOW || count >= MI_MUL_NO_OVERFLOW)
&& size > 0 && (SIZE_MAX / size) < count);
#endif
}
// Safe multiply `count*size` into `total`; return `true` on overflow.
static inline bool mi_count_size_overflow(size_t count, size_t size, size_t* total) {
if (count==1) { // quick check for the case where count is one (common for C++ allocators)
*total = size;
return false;
}
else if (mi_unlikely(mi_mul_overflow(count, size, total))) {
_mi_error_message(EOVERFLOW, "allocation request too large (%zu * %zu bytes)\n", count, size);
*total = SIZE_MAX;
return true;
}
else return false;
}
/* -----------------------------------------------------------
The thread local default heap
----------------------------------------------------------- */
extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap
extern mi_heap_t _mi_heap_main; // statically allocated main backing heap
extern bool _mi_process_is_initialized;
#if defined(MI_TLS_OSX_FAST)
#define MI_TLS_OSX_OFFSET (MI_TLS_OSX_SLOT*sizeof(void*))
static inline void* mi_tls_osx_fast_get(void) {
void* ret;
__asm__("mov %%gs:%1, %0" : "=r" (ret) : "m" (*(void**)(MI_TLS_OSX_OFFSET)));
return ret;
}
static inline void mi_tls_osx_fast_set(void* value) {
__asm__("movq %1,%%gs:%0" : "=m" (*(void**)(MI_TLS_OSX_OFFSET)) : "rn" (value));
}
#elif defined(MI_TLS_PTHREADS)
extern pthread_key_t _mi_heap_default_key;
#else
extern mi_decl_thread mi_heap_t* _mi_heap_default; // default heap to allocate from
#endif
static inline mi_heap_t* mi_get_default_heap(void) {
#if defined(MI_TLS_OSX_FAST)
// Use a fixed slot in the TSD on MacOSX to avoid recursion (since the loader calls malloc).
// We use slot 94 (__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4) <https://github.com/apportable/Foundation/blob/master/System/System/src/pthread_machdep.h>
// which seems unused except for the more recent Webkit <https://github.com/WebKit/webkit/blob/master/Source/WTF/wtf/FastTLS.h>
// Use with care.
mi_heap_t* heap = (mi_heap_t*)mi_tls_osx_fast_get();
return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap);
#elif defined(MI_TLS_PTHREADS)
// Use pthreads for TLS; this is used on macOSX with interpose as the loader calls `malloc`
// to allocate TLS storage leading to recursive calls if __thread declared variables are accessed.
// Using pthreads allows us to initialize without recursive calls. (performance seems still quite good).
mi_heap_t* heap = (mi_unlikely(_mi_heap_default_key == (pthread_key_t)(-1)) ? (mi_heap_t*)&_mi_heap_empty : (mi_heap_t*)pthread_getspecific(_mi_heap_default_key));
return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap);
#else
#if defined(MI_TLS_RECURSE_GUARD)
// On some BSD platforms, like openBSD, the dynamic loader calls `malloc`
// to initialize thread local data (before our module is loaded).
// To avoid recursion, we need to avoid accessing the thread local `_mi_default_heap`
// until our module is loaded and use the statically allocated main heap until that time.
// TODO: patch ourselves dynamically to avoid this check every time?
// if (mi_unlikely(!_mi_process_is_initialized)) return &_mi_heap_main;
#endif
return _mi_heap_default;
#endif
}
static inline bool mi_heap_is_default(const mi_heap_t* heap) {
return (heap == mi_get_default_heap());
}
static inline bool mi_heap_is_backing(const mi_heap_t* heap) {
return (heap->tld->heap_backing == heap);
}
static inline bool mi_heap_is_initialized(mi_heap_t* heap) {
mi_assert_internal(heap != NULL);
return (heap != &_mi_heap_empty);
}
static inline uintptr_t _mi_ptr_cookie(const void* p) {
mi_assert_internal(_mi_heap_main.cookie != 0);
return ((uintptr_t)p ^ _mi_heap_main.cookie);
}
/* -----------------------------------------------------------
Pages
----------------------------------------------------------- */
static inline mi_page_t* _mi_heap_get_free_small_page(mi_heap_t* heap, size_t size) {
mi_assert_internal(size <= (MI_SMALL_SIZE_MAX + MI_PADDING_SIZE));
const size_t idx = _mi_wsize_from_size(size);
mi_assert_internal(idx < MI_PAGES_DIRECT);
return heap->pages_free_direct[idx];
}
// Get the page belonging to a certain size class
static inline mi_page_t* _mi_get_free_small_page(size_t size) {
return _mi_heap_get_free_small_page(mi_get_default_heap(), size);
}
// Segment that contains the pointer
static inline mi_segment_t* _mi_ptr_segment(const void* p) {
// mi_assert_internal(p != NULL);
return (mi_segment_t*)((uintptr_t)p & ~MI_SEGMENT_MASK);
}
// Segment belonging to a page
static inline mi_segment_t* _mi_page_segment(const mi_page_t* page) {
mi_segment_t* segment = _mi_ptr_segment(page);
mi_assert_internal(segment == NULL || page == &segment->pages[page->segment_idx]);
return segment;
}
// used internally
static inline uintptr_t _mi_segment_page_idx_of(const mi_segment_t* segment, const void* p) {
// if (segment->page_size > MI_SEGMENT_SIZE) return &segment->pages[0]; // huge pages
ptrdiff_t diff = (uint8_t*)p - (uint8_t*)segment;
mi_assert_internal(diff >= 0 && (size_t)diff < MI_SEGMENT_SIZE);
uintptr_t idx = (uintptr_t)diff >> segment->page_shift;
mi_assert_internal(idx < segment->capacity);
mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM || idx == 0);
return idx;
}
// Get the page containing the pointer
static inline mi_page_t* _mi_segment_page_of(const mi_segment_t* segment, const void* p) {
uintptr_t idx = _mi_segment_page_idx_of(segment, p);
return &((mi_segment_t*)segment)->pages[idx];
}
// Quick page start for initialized pages
static inline uint8_t* _mi_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) {
const size_t bsize = page->xblock_size;
mi_assert_internal(bsize > 0 && (bsize%sizeof(void*)) == 0);
return _mi_segment_page_start(segment, page, bsize, page_size, NULL);
}
// Get the page containing the pointer
static inline mi_page_t* _mi_ptr_page(void* p) {
return _mi_segment_page_of(_mi_ptr_segment(p), p);
}
// Get the block size of a page (special cased for huge objects)
static inline size_t mi_page_block_size(const mi_page_t* page) {
const size_t bsize = page->xblock_size;
mi_assert_internal(bsize > 0);
if (mi_likely(bsize < MI_HUGE_BLOCK_SIZE)) {
return bsize;
}
else {
size_t psize;
_mi_segment_page_start(_mi_page_segment(page), page, bsize, &psize, NULL);
return psize;
}
}
// Get the usable block size of a page without fixed padding.
// This may still include internal padding due to alignment and rounding up size classes.
static inline size_t mi_page_usable_block_size(const mi_page_t* page) {
return mi_page_block_size(page) - MI_PADDING_SIZE;
}
// Thread free access
static inline mi_block_t* mi_page_thread_free(const mi_page_t* page) {
return (mi_block_t*)(mi_atomic_read_relaxed(&page->xthread_free) & ~3);
}
static inline mi_delayed_t mi_page_thread_free_flag(const mi_page_t* page) {
return (mi_delayed_t)(mi_atomic_read_relaxed(&page->xthread_free) & 3);
}
// Heap access
static inline mi_heap_t* mi_page_heap(const mi_page_t* page) {
return (mi_heap_t*)(mi_atomic_read_relaxed(&page->xheap));
}
static inline void mi_page_set_heap(mi_page_t* page, mi_heap_t* heap) {
mi_assert_internal(mi_page_thread_free_flag(page) != MI_DELAYED_FREEING);
mi_atomic_write(&page->xheap,(uintptr_t)heap);
}
// Thread free flag helpers
static inline mi_block_t* mi_tf_block(mi_thread_free_t tf) {
return (mi_block_t*)(tf & ~0x03);
}
static inline mi_delayed_t mi_tf_delayed(mi_thread_free_t tf) {
return (mi_delayed_t)(tf & 0x03);
}
static inline mi_thread_free_t mi_tf_make(mi_block_t* block, mi_delayed_t delayed) {
return (mi_thread_free_t)((uintptr_t)block | (uintptr_t)delayed);
}
static inline mi_thread_free_t mi_tf_set_delayed(mi_thread_free_t tf, mi_delayed_t delayed) {
return mi_tf_make(mi_tf_block(tf),delayed);
}
static inline mi_thread_free_t mi_tf_set_block(mi_thread_free_t tf, mi_block_t* block) {
return mi_tf_make(block, mi_tf_delayed(tf));
}
// are all blocks in a page freed?
// note: needs up-to-date used count, (as the `xthread_free` list may not be empty). see `_mi_page_collect_free`.
static inline bool mi_page_all_free(const mi_page_t* page) {
mi_assert_internal(page != NULL);
return (page->used == 0);
}
// are there any available blocks?
static inline bool mi_page_has_any_available(const mi_page_t* page) {
mi_assert_internal(page != NULL && page->reserved > 0);
return (page->used < page->reserved || (mi_page_thread_free(page) != NULL));
}
// are there immediately available blocks, i.e. blocks available on the free list.
static inline bool mi_page_immediate_available(const mi_page_t* page) {
mi_assert_internal(page != NULL);
return (page->free != NULL);
}
// is more than 7/8th of a page in use?
static inline bool mi_page_mostly_used(const mi_page_t* page) {
if (page==NULL) return true;
uint16_t frac = page->reserved / 8U;
return (page->reserved - page->used <= frac);
}
static inline mi_page_queue_t* mi_page_queue(const mi_heap_t* heap, size_t size) {
return &((mi_heap_t*)heap)->pages[_mi_bin(size)];
}
//-----------------------------------------------------------
// Page flags
//-----------------------------------------------------------
static inline bool mi_page_is_in_full(const mi_page_t* page) {
return page->flags.x.in_full;
}
static inline void mi_page_set_in_full(mi_page_t* page, bool in_full) {
page->flags.x.in_full = in_full;
}
static inline bool mi_page_has_aligned(const mi_page_t* page) {
return page->flags.x.has_aligned;
}
static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) {
page->flags.x.has_aligned = has_aligned;
}
/* -------------------------------------------------------------------
Encoding/Decoding the free list next pointers
This is to protect against buffer overflow exploits where the
free list is mutated. Many hardened allocators xor the next pointer `p`
with a secret key `k1`, as `p^k1`. This prevents overwriting with known
values but might be still too weak: if the attacker can guess
the pointer `p` this can reveal `k1` (since `p^k1^p == k1`).
Moreover, if multiple blocks can be read as well, the attacker can
xor both as `(p1^k1) ^ (p2^k1) == p1^p2` which may reveal a lot
about the pointers (and subsequently `k1`).
Instead mimalloc uses an extra key `k2` and encodes as `((p^k2)<<<k1)+k1`.
Since these operations are not associative, the above approaches do not
work so well any more even if the `p` can be guesstimated. For example,
for the read case we can subtract two entries to discard the `+k1` term,
but that leads to `((p1^k2)<<<k1) - ((p2^k2)<<<k1)` at best.
We include the left-rotation since xor and addition are otherwise linear
in the lowest bit. Finally, both keys are unique per page which reduces
the re-use of keys by a large factor.
We also pass a separate `null` value to be used as `NULL` or otherwise
`(k2<<<k1)+k1` would appear (too) often as a sentinel value.
------------------------------------------------------------------- */
static inline bool mi_is_in_same_segment(const void* p, const void* q) {
return (_mi_ptr_segment(p) == _mi_ptr_segment(q));
}
static inline bool mi_is_in_same_page(const void* p, const void* q) {
mi_segment_t* segmentp = _mi_ptr_segment(p);
mi_segment_t* segmentq = _mi_ptr_segment(q);
if (segmentp != segmentq) return false;
uintptr_t idxp = _mi_segment_page_idx_of(segmentp, p);
uintptr_t idxq = _mi_segment_page_idx_of(segmentq, q);
return (idxp == idxq);
}
static inline uintptr_t mi_rotl(uintptr_t x, uintptr_t shift) {
shift %= MI_INTPTR_BITS;
return ((x << shift) | (x >> (MI_INTPTR_BITS - shift)));
}
static inline uintptr_t mi_rotr(uintptr_t x, uintptr_t shift) {
shift %= MI_INTPTR_BITS;
return ((x >> shift) | (x << (MI_INTPTR_BITS - shift)));
}
static inline void* mi_ptr_decode(const void* null, const mi_encoded_t x, const uintptr_t* keys) {
void* p = (void*)(mi_rotr(x - keys[0], keys[0]) ^ keys[1]);
return (mi_unlikely(p==null) ? NULL : p);
}
static inline mi_encoded_t mi_ptr_encode(const void* null, const void* p, const uintptr_t* keys) {
uintptr_t x = (uintptr_t)(mi_unlikely(p==NULL) ? null : p);
return mi_rotl(x ^ keys[1], keys[0]) + keys[0];
}
static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* block, const uintptr_t* keys ) {
#ifdef MI_ENCODE_FREELIST
return (mi_block_t*)mi_ptr_decode(null, block->next, keys);
#else
UNUSED(keys); UNUSED(null);
return (mi_block_t*)block->next;
#endif
}
static inline void mi_block_set_nextx(const void* null, mi_block_t* block, const mi_block_t* next, const uintptr_t* keys) {
#ifdef MI_ENCODE_FREELIST
block->next = mi_ptr_encode(null, next, keys);
#else
UNUSED(keys); UNUSED(null);
block->next = (mi_encoded_t)next;
#endif
}
static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t* block) {
#ifdef MI_ENCODE_FREELIST
mi_block_t* next = mi_block_nextx(page,block,page->keys);
// check for free list corruption: is `next` at least in the same page?
// TODO: check if `next` is `page->block_size` aligned?
if (mi_unlikely(next!=NULL && !mi_is_in_same_page(block, next))) {
_mi_error_message(EFAULT, "corrupted free list entry of size %zub at %p: value 0x%zx\n", mi_page_block_size(page), block, (uintptr_t)next);
next = NULL;
}
return next;
#else
UNUSED(page);
return mi_block_nextx(page,block,NULL);
#endif
}
static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, const mi_block_t* next) {
#ifdef MI_ENCODE_FREELIST
mi_block_set_nextx(page,block,next, page->keys);
#else
UNUSED(page);
mi_block_set_nextx(page,block,next,NULL);
#endif
}
// -------------------------------------------------------------------
// Fast "random" shuffle
// -------------------------------------------------------------------
static inline uintptr_t _mi_random_shuffle(uintptr_t x) {
if (x==0) { x = 17; } // ensure we don't get stuck in generating zeros
#if (MI_INTPTR_SIZE==8)
// by Sebastiano Vigna, see: <http://xoshiro.di.unimi.it/splitmix64.c>
x ^= x >> 30;
x *= 0xbf58476d1ce4e5b9UL;
x ^= x >> 27;
x *= 0x94d049bb133111ebUL;
x ^= x >> 31;
#elif (MI_INTPTR_SIZE==4)
// by Chris Wellons, see: <https://nullprogram.com/blog/2018/07/31/>
x ^= x >> 16;
x *= 0x7feb352dUL;
x ^= x >> 15;
x *= 0x846ca68bUL;
x ^= x >> 16;
#endif
return x;
}
// -------------------------------------------------------------------
// Optimize numa node access for the common case (= one node)
// -------------------------------------------------------------------
int _mi_os_numa_node_get(mi_os_tld_t* tld);
size_t _mi_os_numa_node_count_get(void);
extern size_t _mi_numa_node_count;
static inline int _mi_os_numa_node(mi_os_tld_t* tld) {
if (mi_likely(_mi_numa_node_count == 1)) return 0;
else return _mi_os_numa_node_get(tld);
}
static inline size_t _mi_os_numa_node_count(void) {
if (mi_likely(_mi_numa_node_count>0)) return _mi_numa_node_count;
else return _mi_os_numa_node_count_get();
}
// -------------------------------------------------------------------
// Getting the thread id should be performant
// as it is called in the fast path of `_mi_free`,
// so we specialize for various platforms.
// -------------------------------------------------------------------
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
// Windows: works on Intel and ARM in both 32- and 64-bit
return (uintptr_t)NtCurrentTeb();
}
#elif (defined(__GNUC__) || defined(__clang__)) && \
(defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))
// TLS register on x86 is in the FS or GS register
// see: https://akkadia.org/drepper/tls.pdf
static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
uintptr_t tid;
#if defined(__i386__)
__asm__("movl %%gs:0, %0" : "=r" (tid) : : ); // 32-bit always uses GS
#elif defined(__MACH__)
__asm__("movq %%gs:0, %0" : "=r" (tid) : : ); // x86_64 macOS uses GS
#elif defined(__x86_64__)
__asm__("movq %%fs:0, %0" : "=r" (tid) : : ); // x86_64 Linux, BSD uses FS
#elif defined(__arm__)
asm volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (tid));
#elif defined(__aarch64__)
asm volatile ("mrs %0, tpidr_el0" : "=r" (tid));
#endif
return tid;
}
#else
// otherwise use standard C
static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
return (uintptr_t)&_mi_heap_default;
}
#endif
#endif

View file

@ -10,32 +10,50 @@ terms of the MIT license. A copy of the license can be found in the file
#include "mimalloc-types.h" #include "mimalloc-types.h"
#if defined(MI_MALLOC_OVERRIDE) && (defined(__APPLE__) || defined(__OpenBSD__))
#define MI_TLS_RECURSE_GUARD
#endif
#if (MI_DEBUG>0) #if (MI_DEBUG>0)
#define mi_trace_message(...) _mi_trace_message(__VA_ARGS__) #define mi_trace_message(...) _mi_trace_message(__VA_ARGS__)
#else #else
#define mi_trace_message(...) #define mi_trace_message(...)
#endif #endif
#define MI_CACHE_LINE 64
#if defined(_MSC_VER)
#pragma warning(disable:4127) // suppress constant conditional warning (due to MI_SECURE paths)
#define mi_decl_noinline __declspec(noinline)
#define mi_decl_thread __declspec(thread)
#define mi_decl_cache_align __declspec(align(MI_CACHE_LINE))
#elif (defined(__GNUC__) && (__GNUC__>=3)) // includes clang and icc
#define mi_decl_noinline __attribute__((noinline))
#define mi_decl_thread __thread
#define mi_decl_cache_align __attribute__((aligned(MI_CACHE_LINE)))
#else
#define mi_decl_noinline
#define mi_decl_thread __thread // hope for the best :-)
#define mi_decl_cache_align
#endif
// "options.c" // "options.c"
void _mi_fputs(mi_output_fun* out, const char* prefix, const char* message); void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message);
void _mi_fprintf(mi_output_fun* out, const char* fmt, ...); void _mi_fprintf(mi_output_fun* out, void* arg, const char* fmt, ...);
void _mi_error_message(const char* fmt, ...);
void _mi_warning_message(const char* fmt, ...); void _mi_warning_message(const char* fmt, ...);
void _mi_verbose_message(const char* fmt, ...); void _mi_verbose_message(const char* fmt, ...);
void _mi_trace_message(const char* fmt, ...); void _mi_trace_message(const char* fmt, ...);
void _mi_options_init(void); void _mi_options_init(void);
void _mi_error_message(int err, const char* fmt, ...);
// "init.c" // random.c
void _mi_random_init(mi_random_ctx_t* ctx);
void _mi_random_split(mi_random_ctx_t* ctx, mi_random_ctx_t* new_ctx);
uintptr_t _mi_random_next(mi_random_ctx_t* ctx);
uintptr_t _mi_heap_random_next(mi_heap_t* heap);
uintptr_t _os_random_weak(uintptr_t extra_seed);
static inline uintptr_t _mi_random_shuffle(uintptr_t x);
// init.c
extern mi_stats_t _mi_stats_main; extern mi_stats_t _mi_stats_main;
extern const mi_page_t _mi_page_empty; extern const mi_page_t _mi_page_empty;
bool _mi_is_main_thread(void); bool _mi_is_main_thread(void);
uintptr_t _mi_ptr_cookie(const void* p);
uintptr_t _mi_random_shuffle(uintptr_t x);
uintptr_t _mi_random_init(uintptr_t seed /* can be zero */);
bool _mi_preloading(); // true while the C runtime is not ready bool _mi_preloading(); // true while the C runtime is not ready
// os.c // os.c
@ -47,23 +65,28 @@ size_t _mi_os_good_alloc_size(size_t size);
// memory.c // memory.c
void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* id, mi_os_tld_t* tld); void* _mi_mem_alloc_aligned(size_t size, size_t alignment, bool* commit, bool* large, bool* is_zero, size_t* id, mi_os_tld_t* tld);
void _mi_mem_free(void* p, size_t size, size_t id, mi_stats_t* stats); void _mi_mem_free(void* p, size_t size, size_t id, bool fully_committed, bool any_reset, mi_os_tld_t* tld);
bool _mi_mem_reset(void* p, size_t size, mi_stats_t* stats); bool _mi_mem_reset(void* p, size_t size, mi_os_tld_t* tld);
bool _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_stats_t* stats); bool _mi_mem_unreset(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld);
bool _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_stats_t* stats); bool _mi_mem_commit(void* p, size_t size, bool* is_zero, mi_os_tld_t* tld);
bool _mi_mem_protect(void* addr, size_t size); bool _mi_mem_protect(void* addr, size_t size);
bool _mi_mem_unprotect(void* addr, size_t size); bool _mi_mem_unprotect(void* addr, size_t size);
void _mi_mem_collect(mi_stats_t* stats); void _mi_mem_collect(mi_os_tld_t* tld);
// "segment.c" // "segment.c"
mi_page_t* _mi_segment_page_alloc(size_t block_wsize, mi_segments_tld_t* tld, mi_os_tld_t* os_tld); mi_page_t* _mi_segment_page_alloc(mi_heap_t* heap, size_t block_wsize, mi_segments_tld_t* tld, mi_os_tld_t* os_tld);
void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld); void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld);
void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld); void _mi_segment_page_abandon(mi_page_t* page, mi_segments_tld_t* tld);
bool _mi_segment_try_reclaim_abandoned( mi_heap_t* heap, bool try_all, mi_segments_tld_t* tld); uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size, size_t* pre_size); // page start for any page
void _mi_segment_huge_page_free(mi_segment_t* segment, mi_page_t* page, mi_block_t* block);
void _mi_segment_thread_collect(mi_segments_tld_t* tld); void _mi_segment_thread_collect(mi_segments_tld_t* tld);
uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size); // page start for any page void _mi_abandoned_reclaim_all(mi_heap_t* heap, mi_segments_tld_t* tld);
void _mi_abandoned_await_readers(void);
// "page.c" // "page.c"
void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc; void* _mi_malloc_generic(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc;
@ -73,8 +96,9 @@ void _mi_page_unfull(mi_page_t* page);
void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force); // free the page void _mi_page_free(mi_page_t* page, mi_page_queue_t* pq, bool force); // free the page
void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq); // abandon the page, to be picked up by another thread... void _mi_page_abandon(mi_page_t* page, mi_page_queue_t* pq); // abandon the page, to be picked up by another thread...
void _mi_heap_delayed_free(mi_heap_t* heap); void _mi_heap_delayed_free(mi_heap_t* heap);
void _mi_heap_collect_retired(mi_heap_t* heap, bool force);
void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay); void _mi_page_use_delayed_free(mi_page_t* page, mi_delayed_t delay, bool override_never);
size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append); size_t _mi_page_queue_append(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_queue_t* append);
void _mi_deferred_free(mi_heap_t* heap, bool force); void _mi_deferred_free(mi_heap_t* heap, bool force);
@ -88,12 +112,14 @@ uint8_t _mi_bsr(uintptr_t x); // bit-scan-right, used on BSD i
// "heap.c" // "heap.c"
void _mi_heap_destroy_pages(mi_heap_t* heap); void _mi_heap_destroy_pages(mi_heap_t* heap);
void _mi_heap_collect_abandon(mi_heap_t* heap); void _mi_heap_collect_abandon(mi_heap_t* heap);
uintptr_t _mi_heap_random(mi_heap_t* heap); void _mi_heap_set_default_direct(mi_heap_t* heap);
// "stats.c" // "stats.c"
void _mi_stats_done(mi_stats_t* stats); void _mi_stats_done(mi_stats_t* stats);
double _mi_clock_end(double start);
double _mi_clock_start(void); mi_msecs_t _mi_clock_now(void);
mi_msecs_t _mi_clock_end(mi_msecs_t start);
mi_msecs_t _mi_clock_start(void);
// "alloc.c" // "alloc.c"
void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept; // called from `_mi_malloc_generic` void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept; // called from `_mi_malloc_generic`
@ -124,12 +150,28 @@ bool _mi_page_is_valid(mi_page_t* page);
#define __has_builtin(x) 0 #define __has_builtin(x) 0
#endif #endif
#if defined(_MSC_VER)
#define mi_decl_noinline __declspec(noinline) /* -----------------------------------------------------------
#elif defined(__GNUC__) || defined(__clang__) Error codes passed to `_mi_fatal_error`
#define mi_decl_noinline __attribute__((noinline)) All are recoverable but EFAULT is a serious error and aborts by default in secure mode.
#else For portability define undefined error codes using common Unix codes:
#define mi_decl_noinline <https://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html>
----------------------------------------------------------- */
#include <errno.h>
#ifndef EAGAIN // double free
#define EAGAIN (11)
#endif
#ifndef ENOMEM // out of memory
#define ENOMEM (12)
#endif
#ifndef EFAULT // corrupted free-list or meta-data
#define EFAULT (14)
#endif
#ifndef EINVAL // trying to free an invalid pointer
#define EINVAL (22)
#endif
#ifndef EOVERFLOW // count*size overflow
#define EOVERFLOW (75)
#endif #endif
@ -152,22 +194,6 @@ bool _mi_page_is_valid(mi_page_t* page);
#define MI_INIT256(x) MI_INIT128(x),MI_INIT128(x) #define MI_INIT256(x) MI_INIT128(x),MI_INIT128(x)
// Overflow detecting multiply
#define MI_MUL_NO_OVERFLOW ((size_t)1 << (4*sizeof(size_t))) // sqrt(SIZE_MAX)
static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) {
#if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5
#if (MI_INTPTR_SIZE == 4)
return __builtin_umul_overflow(count, size, total);
#else
return __builtin_umull_overflow(count, size, total);
#endif
#else /* __builtin_umul_overflow is unavailable */
*total = count * size;
return ((size >= MI_MUL_NO_OVERFLOW || count >= MI_MUL_NO_OVERFLOW)
&& size > 0 && (SIZE_MAX / size) < count);
#endif
}
// Is `x` a power of two? (0 is considered a power of two) // Is `x` a power of two? (0 is considered a power of two)
static inline bool _mi_is_power_of_two(uintptr_t x) { static inline bool _mi_is_power_of_two(uintptr_t x) {
return ((x & (x - 1)) == 0); return ((x & (x - 1)) == 0);
@ -175,6 +201,7 @@ static inline bool _mi_is_power_of_two(uintptr_t x) {
// Align upwards // Align upwards
static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) { static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) {
mi_assert_internal(alignment != 0);
uintptr_t mask = alignment - 1; uintptr_t mask = alignment - 1;
if ((alignment & mask) == 0) { // power of two? if ((alignment & mask) == 0) { // power of two?
return ((sz + mask) & ~mask); return ((sz + mask) & ~mask);
@ -184,6 +211,12 @@ static inline uintptr_t _mi_align_up(uintptr_t sz, size_t alignment) {
} }
} }
// Divide upwards: `s <= _mi_divide_up(s,d)*d < s+d`.
static inline uintptr_t _mi_divide_up(uintptr_t size, size_t divider) {
mi_assert_internal(divider != 0);
return (divider == 0 ? size : ((size + divider - 1) / divider));
}
// Is memory zero initialized? // Is memory zero initialized?
static inline bool mi_mem_is_zero(void* p, size_t size) { static inline bool mi_mem_is_zero(void* p, size_t size) {
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -199,27 +232,115 @@ static inline size_t _mi_wsize_from_size(size_t size) {
return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t); return (size + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
} }
// Does malloc satisfy the alignment constraints already?
static inline bool mi_malloc_satisfies_alignment(size_t alignment, size_t size) {
return (alignment == sizeof(void*) || (alignment == MI_MAX_ALIGN_SIZE && size > (MI_MAX_ALIGN_SIZE/2)));
}
/* ----------------------------------------------------------- // Overflow detecting multiply
The thread local default heap static inline bool mi_mul_overflow(size_t count, size_t size, size_t* total) {
----------------------------------------------------------- */ #if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5
#include <limits.h> // UINT_MAX, ULONG_MAX
#if (SIZE_MAX == UINT_MAX)
return __builtin_umul_overflow(count, size, total);
#elif (SIZE_MAX == ULONG_MAX)
return __builtin_umull_overflow(count, size, total);
#else
return __builtin_umulll_overflow(count, size, total);
#endif
#else /* __builtin_umul_overflow is unavailable */
#define MI_MUL_NO_OVERFLOW ((size_t)1 << (4*sizeof(size_t))) // sqrt(SIZE_MAX)
*total = count * size;
return ((size >= MI_MUL_NO_OVERFLOW || count >= MI_MUL_NO_OVERFLOW)
&& size > 0 && (SIZE_MAX / size) < count);
#endif
}
// Safe multiply `count*size` into `total`; return `true` on overflow.
static inline bool mi_count_size_overflow(size_t count, size_t size, size_t* total) {
if (count==1) { // quick check for the case where count is one (common for C++ allocators)
*total = size;
return false;
}
else if (mi_unlikely(mi_mul_overflow(count, size, total))) {
_mi_error_message(EOVERFLOW, "allocation request too large (%zu * %zu bytes)\n", count, size);
*total = SIZE_MAX;
return true;
}
else return false;
}
/* ----------------------------------------------------------------------------------------
The thread local default heap: `_mi_get_default_heap` returns the thread local heap.
On most platforms (Windows, Linux, FreeBSD, NetBSD, etc), this just returns a
__thread local variable (`_mi_heap_default`). With the initial-exec TLS model this ensures
that the storage will always be available (allocated on the thread stacks).
On some platforms though we cannot use that when overriding `malloc` since the underlying
TLS implementation (or the loader) will call itself `malloc` on a first access and recurse.
We try to circumvent this in an efficient way:
- macOSX : we use an unused TLS slot from the OS allocated slots (MI_TLS_SLOT). On OSX, the
loader itself calls `malloc` even before the modules are initialized.
- OpenBSD: we use an unused slot from the pthread block (MI_TLS_PTHREAD_SLOT_OFS).
- DragonFly: not yet working.
------------------------------------------------------------------------------------------- */
extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap extern const mi_heap_t _mi_heap_empty; // read-only empty heap, initial value of the thread local default heap
extern mi_heap_t _mi_heap_main; // statically allocated main backing heap
extern bool _mi_process_is_initialized; extern bool _mi_process_is_initialized;
mi_heap_t* _mi_heap_main_get(void); // statically allocated main backing heap
#if defined(MI_MALLOC_OVERRIDE)
#if defined(__MACH__) // OSX
#define MI_TLS_SLOT 89 // seems unused?
// other possible unused ones are 9, 29, __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY4 (94), __PTK_FRAMEWORK_GC_KEY9 (112) and __PTK_FRAMEWORK_OLDGC_KEY9 (89)
// see <https://github.com/rweichler/substrate/blob/master/include/pthread_machdep.h>
#elif defined(__OpenBSD__)
// use end bytes of a name; goes wrong if anyone uses names > 23 characters (ptrhread specifies 16)
// see <https://github.com/openbsd/src/blob/master/lib/libc/include/thread_private.h#L371>
#define MI_TLS_PTHREAD_SLOT_OFS (6*sizeof(int) + 4*sizeof(void*) + 24)
#elif defined(__DragonFly__)
#warning "mimalloc is not working correctly on DragonFly yet."
#define MI_TLS_PTHREAD_SLOT_OFS (4 + 1*sizeof(void*)) // offset `uniqueid` (also used by gdb?) <https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/lib/libthread_xu/thread/thr_private.h#L458>
#endif
#endif
#if defined(MI_TLS_SLOT)
static inline void* mi_tls_slot(size_t slot) mi_attr_noexcept; // forward declaration
#elif defined(MI_TLS_PTHREAD_SLOT_OFS)
#include <pthread.h>
static inline mi_heap_t** mi_tls_pthread_heap_slot(void) {
pthread_t self = pthread_self();
#if defined(__DragonFly__)
if (self==NULL) {
static mi_heap_t* pheap_main = _mi_heap_main_get();
return &pheap_main;
}
#endif
return (mi_heap_t**)((uint8_t*)self + MI_TLS_PTHREAD_SLOT_OFS);
}
#elif defined(MI_TLS_PTHREAD)
#include <pthread.h>
extern pthread_key_t _mi_heap_default_key;
#else
extern mi_decl_thread mi_heap_t* _mi_heap_default; // default heap to allocate from extern mi_decl_thread mi_heap_t* _mi_heap_default; // default heap to allocate from
#endif
static inline mi_heap_t* mi_get_default_heap(void) { static inline mi_heap_t* mi_get_default_heap(void) {
#ifdef MI_TLS_RECURSE_GUARD #if defined(MI_TLS_SLOT)
// on some platforms, like macOS, the dynamic loader calls `malloc` mi_heap_t* heap = (mi_heap_t*)mi_tls_slot(MI_TLS_SLOT);
// to initialize thread local data. To avoid recursion, we need to avoid return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap);
// accessing the thread local `_mi_default_heap` until our module is loaded #elif defined(MI_TLS_PTHREAD_SLOT_OFS)
// and use the statically allocated main heap until that time. mi_heap_t* heap = *mi_tls_pthread_heap_slot();
// TODO: patch ourselves dynamically to avoid this check every time? return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap);
if (!_mi_process_is_initialized) return &_mi_heap_main; #elif defined(MI_TLS_PTHREAD)
mi_heap_t* heap = (mi_unlikely(_mi_heap_default_key == (pthread_key_t)(-1)) ? _mi_heap_main_get() : (mi_heap_t*)pthread_getspecific(_mi_heap_default_key));
return (mi_unlikely(heap == NULL) ? (mi_heap_t*)&_mi_heap_empty : heap);
#else
#if defined(MI_TLS_RECURSE_GUARD)
if (mi_unlikely(!_mi_process_is_initialized)) return _mi_heap_main_get();
#endif #endif
return _mi_heap_default; return _mi_heap_default;
#endif
} }
static inline bool mi_heap_is_default(const mi_heap_t* heap) { static inline bool mi_heap_is_default(const mi_heap_t* heap) {
@ -235,13 +356,21 @@ static inline bool mi_heap_is_initialized(mi_heap_t* heap) {
return (heap != &_mi_heap_empty); return (heap != &_mi_heap_empty);
} }
static inline uintptr_t _mi_ptr_cookie(const void* p) {
extern mi_heap_t _mi_heap_main;
mi_assert_internal(_mi_heap_main.cookie != 0);
return ((uintptr_t)p ^ _mi_heap_main.cookie);
}
/* ----------------------------------------------------------- /* -----------------------------------------------------------
Pages Pages
----------------------------------------------------------- */ ----------------------------------------------------------- */
static inline mi_page_t* _mi_heap_get_free_small_page(mi_heap_t* heap, size_t size) { static inline mi_page_t* _mi_heap_get_free_small_page(mi_heap_t* heap, size_t size) {
mi_assert_internal(size <= MI_SMALL_SIZE_MAX); mi_assert_internal(size <= (MI_SMALL_SIZE_MAX + MI_PADDING_SIZE));
return heap->pages_free_direct[_mi_wsize_from_size(size)]; const size_t idx = _mi_wsize_from_size(size);
mi_assert_internal(idx < MI_PAGES_DIRECT);
return heap->pages_free_direct[idx];
} }
// Get the page belonging to a certain size class // Get the page belonging to a certain size class
@ -262,20 +391,28 @@ static inline mi_segment_t* _mi_page_segment(const mi_page_t* page) {
return segment; return segment;
} }
// Get the page containing the pointer // used internally
static inline mi_page_t* _mi_segment_page_of(const mi_segment_t* segment, const void* p) { static inline uintptr_t _mi_segment_page_idx_of(const mi_segment_t* segment, const void* p) {
// if (segment->page_size > MI_SEGMENT_SIZE) return &segment->pages[0]; // huge pages // if (segment->page_size > MI_SEGMENT_SIZE) return &segment->pages[0]; // huge pages
ptrdiff_t diff = (uint8_t*)p - (uint8_t*)segment; ptrdiff_t diff = (uint8_t*)p - (uint8_t*)segment;
mi_assert_internal(diff >= 0 && diff < MI_SEGMENT_SIZE); mi_assert_internal(diff >= 0 && (size_t)diff < MI_SEGMENT_SIZE);
uintptr_t idx = (uintptr_t)diff >> segment->page_shift; uintptr_t idx = (uintptr_t)diff >> segment->page_shift;
mi_assert_internal(idx < segment->capacity); mi_assert_internal(idx < segment->capacity);
mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM || idx == 0); mi_assert_internal(segment->page_kind <= MI_PAGE_MEDIUM || idx == 0);
return idx;
}
// Get the page containing the pointer
static inline mi_page_t* _mi_segment_page_of(const mi_segment_t* segment, const void* p) {
uintptr_t idx = _mi_segment_page_idx_of(segment, p);
return &((mi_segment_t*)segment)->pages[idx]; return &((mi_segment_t*)segment)->pages[idx];
} }
// Quick page start for initialized pages // Quick page start for initialized pages
static inline uint8_t* _mi_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) { static inline uint8_t* _mi_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t* page_size) {
return _mi_segment_page_start(segment, page, page->block_size, page_size); const size_t bsize = page->xblock_size;
mi_assert_internal(bsize > 0 && (bsize%sizeof(void*)) == 0);
return _mi_segment_page_start(segment, page, bsize, page_size, NULL);
} }
// Get the page containing the pointer // Get the page containing the pointer
@ -283,7 +420,47 @@ static inline mi_page_t* _mi_ptr_page(void* p) {
return _mi_segment_page_of(_mi_ptr_segment(p), p); return _mi_segment_page_of(_mi_ptr_segment(p), p);
} }
// Get the block size of a page (special cased for huge objects)
static inline size_t mi_page_block_size(const mi_page_t* page) {
const size_t bsize = page->xblock_size;
mi_assert_internal(bsize > 0);
if (mi_likely(bsize < MI_HUGE_BLOCK_SIZE)) {
return bsize;
}
else {
size_t psize;
_mi_segment_page_start(_mi_page_segment(page), page, bsize, &psize, NULL);
return psize;
}
}
// Get the usable block size of a page without fixed padding.
// This may still include internal padding due to alignment and rounding up size classes.
static inline size_t mi_page_usable_block_size(const mi_page_t* page) {
return mi_page_block_size(page) - MI_PADDING_SIZE;
}
// Thread free access // Thread free access
static inline mi_block_t* mi_page_thread_free(const mi_page_t* page) {
return (mi_block_t*)(mi_atomic_read_relaxed(&page->xthread_free) & ~3);
}
static inline mi_delayed_t mi_page_thread_free_flag(const mi_page_t* page) {
return (mi_delayed_t)(mi_atomic_read_relaxed(&page->xthread_free) & 3);
}
// Heap access
static inline mi_heap_t* mi_page_heap(const mi_page_t* page) {
return (mi_heap_t*)(mi_atomic_read_relaxed(&page->xheap));
}
static inline void mi_page_set_heap(mi_page_t* page, mi_heap_t* heap) {
mi_assert_internal(mi_page_thread_free_flag(page) != MI_DELAYED_FREEING);
mi_atomic_write(&page->xheap,(uintptr_t)heap);
}
// Thread free flag helpers
static inline mi_block_t* mi_tf_block(mi_thread_free_t tf) { static inline mi_block_t* mi_tf_block(mi_thread_free_t tf) {
return (mi_block_t*)(tf & ~0x03); return (mi_block_t*)(tf & ~0x03);
} }
@ -301,35 +478,29 @@ static inline mi_thread_free_t mi_tf_set_block(mi_thread_free_t tf, mi_block_t*
} }
// are all blocks in a page freed? // are all blocks in a page freed?
// note: needs up-to-date used count, (as the `xthread_free` list may not be empty). see `_mi_page_collect_free`.
static inline bool mi_page_all_free(const mi_page_t* page) { static inline bool mi_page_all_free(const mi_page_t* page) {
mi_assert_internal(page != NULL); mi_assert_internal(page != NULL);
return (page->used - page->thread_freed == 0); return (page->used == 0);
} }
// are there immediately available blocks // are there any available blocks?
static inline bool mi_page_has_any_available(const mi_page_t* page) {
mi_assert_internal(page != NULL && page->reserved > 0);
return (page->used < page->reserved || (mi_page_thread_free(page) != NULL));
}
// are there immediately available blocks, i.e. blocks available on the free list.
static inline bool mi_page_immediate_available(const mi_page_t* page) { static inline bool mi_page_immediate_available(const mi_page_t* page) {
mi_assert_internal(page != NULL); mi_assert_internal(page != NULL);
return (page->free != NULL); return (page->free != NULL);
} }
// are there free blocks in this page?
static inline bool mi_page_has_free(mi_page_t* page) {
mi_assert_internal(page != NULL);
bool hasfree = (mi_page_immediate_available(page) || page->local_free != NULL || (mi_tf_block(page->thread_free) != NULL));
mi_assert_internal(hasfree || page->used - page->thread_freed == page->capacity);
return hasfree;
}
// are all blocks in use?
static inline bool mi_page_all_used(mi_page_t* page) {
mi_assert_internal(page != NULL);
return !mi_page_has_free(page);
}
// is more than 7/8th of a page in use? // is more than 7/8th of a page in use?
static inline bool mi_page_mostly_used(const mi_page_t* page) { static inline bool mi_page_mostly_used(const mi_page_t* page) {
if (page==NULL) return true; if (page==NULL) return true;
uint16_t frac = page->reserved / 8U; uint16_t frac = page->reserved / 8U;
return (page->reserved - page->used + page->thread_freed <= frac); return (page->reserved - page->used <= frac);
} }
static inline mi_page_queue_t* mi_page_queue(const mi_heap_t* heap, size_t size) { static inline mi_page_queue_t* mi_page_queue(const mi_heap_t* heap, size_t size) {
@ -342,66 +513,167 @@ static inline mi_page_queue_t* mi_page_queue(const mi_heap_t* heap, size_t size)
// Page flags // Page flags
//----------------------------------------------------------- //-----------------------------------------------------------
static inline bool mi_page_is_in_full(const mi_page_t* page) { static inline bool mi_page_is_in_full(const mi_page_t* page) {
return page->flags.in_full; return page->flags.x.in_full;
} }
static inline void mi_page_set_in_full(mi_page_t* page, bool in_full) { static inline void mi_page_set_in_full(mi_page_t* page, bool in_full) {
page->flags.in_full = in_full; page->flags.x.in_full = in_full;
} }
static inline bool mi_page_has_aligned(const mi_page_t* page) { static inline bool mi_page_has_aligned(const mi_page_t* page) {
return page->flags.has_aligned; return page->flags.x.has_aligned;
} }
static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) { static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) {
page->flags.has_aligned = has_aligned; page->flags.x.has_aligned = has_aligned;
} }
// ------------------------------------------------------------------- /* -------------------------------------------------------------------
// Encoding/Decoding the free list next pointers Encoding/Decoding the free list next pointers
// -------------------------------------------------------------------
static inline mi_block_t* mi_block_nextx( uintptr_t cookie, mi_block_t* block ) { This is to protect against buffer overflow exploits where the
#if MI_SECURE free list is mutated. Many hardened allocators xor the next pointer `p`
return (mi_block_t*)(block->next ^ cookie); with a secret key `k1`, as `p^k1`. This prevents overwriting with known
values but might be still too weak: if the attacker can guess
the pointer `p` this can reveal `k1` (since `p^k1^p == k1`).
Moreover, if multiple blocks can be read as well, the attacker can
xor both as `(p1^k1) ^ (p2^k1) == p1^p2` which may reveal a lot
about the pointers (and subsequently `k1`).
Instead mimalloc uses an extra key `k2` and encodes as `((p^k2)<<<k1)+k1`.
Since these operations are not associative, the above approaches do not
work so well any more even if the `p` can be guesstimated. For example,
for the read case we can subtract two entries to discard the `+k1` term,
but that leads to `((p1^k2)<<<k1) - ((p2^k2)<<<k1)` at best.
We include the left-rotation since xor and addition are otherwise linear
in the lowest bit. Finally, both keys are unique per page which reduces
the re-use of keys by a large factor.
We also pass a separate `null` value to be used as `NULL` or otherwise
`(k2<<<k1)+k1` would appear (too) often as a sentinel value.
------------------------------------------------------------------- */
static inline bool mi_is_in_same_segment(const void* p, const void* q) {
return (_mi_ptr_segment(p) == _mi_ptr_segment(q));
}
static inline bool mi_is_in_same_page(const void* p, const void* q) {
mi_segment_t* segmentp = _mi_ptr_segment(p);
mi_segment_t* segmentq = _mi_ptr_segment(q);
if (segmentp != segmentq) return false;
uintptr_t idxp = _mi_segment_page_idx_of(segmentp, p);
uintptr_t idxq = _mi_segment_page_idx_of(segmentq, q);
return (idxp == idxq);
}
static inline uintptr_t mi_rotl(uintptr_t x, uintptr_t shift) {
shift %= MI_INTPTR_BITS;
return ((x << shift) | (x >> (MI_INTPTR_BITS - shift)));
}
static inline uintptr_t mi_rotr(uintptr_t x, uintptr_t shift) {
shift %= MI_INTPTR_BITS;
return ((x >> shift) | (x << (MI_INTPTR_BITS - shift)));
}
static inline void* mi_ptr_decode(const void* null, const mi_encoded_t x, const uintptr_t* keys) {
void* p = (void*)(mi_rotr(x - keys[0], keys[0]) ^ keys[1]);
return (mi_unlikely(p==null) ? NULL : p);
}
static inline mi_encoded_t mi_ptr_encode(const void* null, const void* p, const uintptr_t* keys) {
uintptr_t x = (uintptr_t)(mi_unlikely(p==NULL) ? null : p);
return mi_rotl(x ^ keys[1], keys[0]) + keys[0];
}
static inline mi_block_t* mi_block_nextx( const void* null, const mi_block_t* block, const uintptr_t* keys ) {
#ifdef MI_ENCODE_FREELIST
return (mi_block_t*)mi_ptr_decode(null, block->next, keys);
#else #else
UNUSED(cookie); UNUSED(keys); UNUSED(null);
return (mi_block_t*)block->next; return (mi_block_t*)block->next;
#endif #endif
} }
static inline void mi_block_set_nextx(uintptr_t cookie, mi_block_t* block, mi_block_t* next) { static inline void mi_block_set_nextx(const void* null, mi_block_t* block, const mi_block_t* next, const uintptr_t* keys) {
#if MI_SECURE #ifdef MI_ENCODE_FREELIST
block->next = (mi_encoded_t)next ^ cookie; block->next = mi_ptr_encode(null, next, keys);
#else #else
UNUSED(cookie); UNUSED(keys); UNUSED(null);
block->next = (mi_encoded_t)next; block->next = (mi_encoded_t)next;
#endif #endif
} }
static inline mi_block_t* mi_block_next(mi_page_t* page, mi_block_t* block) { static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t* block) {
#if MI_SECURE #ifdef MI_ENCODE_FREELIST
return mi_block_nextx(page->cookie,block); mi_block_t* next = mi_block_nextx(page,block,page->keys);
// check for free list corruption: is `next` at least in the same page?
// TODO: check if `next` is `page->block_size` aligned?
if (mi_unlikely(next!=NULL && !mi_is_in_same_page(block, next))) {
_mi_error_message(EFAULT, "corrupted free list entry of size %zub at %p: value 0x%zx\n", mi_page_block_size(page), block, (uintptr_t)next);
next = NULL;
}
return next;
#else #else
UNUSED(page); UNUSED(page);
return mi_block_nextx(0, block); return mi_block_nextx(page,block,NULL);
#endif #endif
} }
static inline void mi_block_set_next(mi_page_t* page, mi_block_t* block, mi_block_t* next) { static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, const mi_block_t* next) {
#if MI_SECURE #ifdef MI_ENCODE_FREELIST
mi_block_set_nextx(page->cookie,block,next); mi_block_set_nextx(page,block,next, page->keys);
#else #else
UNUSED(page); UNUSED(page);
mi_block_set_nextx(0, block, next); mi_block_set_nextx(page,block,next,NULL);
#endif #endif
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Getting the thread id should be performant // Fast "random" shuffle
// as it is called in the fast path of `_mi_free`, // -------------------------------------------------------------------
// so we specialize for various platforms.
static inline uintptr_t _mi_random_shuffle(uintptr_t x) {
if (x==0) { x = 17; } // ensure we don't get stuck in generating zeros
#if (MI_INTPTR_SIZE==8)
// by Sebastiano Vigna, see: <http://xoshiro.di.unimi.it/splitmix64.c>
x ^= x >> 30;
x *= 0xbf58476d1ce4e5b9UL;
x ^= x >> 27;
x *= 0x94d049bb133111ebUL;
x ^= x >> 31;
#elif (MI_INTPTR_SIZE==4)
// by Chris Wellons, see: <https://nullprogram.com/blog/2018/07/31/>
x ^= x >> 16;
x *= 0x7feb352dUL;
x ^= x >> 15;
x *= 0x846ca68bUL;
x ^= x >> 16;
#endif
return x;
}
// -------------------------------------------------------------------
// Optimize numa node access for the common case (= one node)
// -------------------------------------------------------------------
int _mi_os_numa_node_get(mi_os_tld_t* tld);
size_t _mi_os_numa_node_count_get(void);
extern size_t _mi_numa_node_count;
static inline int _mi_os_numa_node(mi_os_tld_t* tld) {
if (mi_likely(_mi_numa_node_count == 1)) return 0;
else return _mi_os_numa_node_get(tld);
}
static inline size_t _mi_os_numa_node_count(void) {
if (mi_likely(_mi_numa_node_count>0)) return _mi_numa_node_count;
else return _mi_os_numa_node_count_get();
}
// -------------------------------------------------------------------
// Getting the thread id should be performant as it is called in the
// fast path of `_mi_free` and we specialize for various platforms.
// ------------------------------------------------------------------- // -------------------------------------------------------------------
#if defined(_WIN32) #if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
@ -410,24 +682,55 @@ static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
// Windows: works on Intel and ARM in both 32- and 64-bit // Windows: works on Intel and ARM in both 32- and 64-bit
return (uintptr_t)NtCurrentTeb(); return (uintptr_t)NtCurrentTeb();
} }
#elif (defined(__GNUC__) || defined(__clang__)) && \
#elif defined(__GNUC__) && \
(defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)) (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))
// TLS register on x86 is in the FS or GS register
// see: https://akkadia.org/drepper/tls.pdf // TLS register on x86 is in the FS or GS register, see: https://akkadia.org/drepper/tls.pdf
static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept { static inline void* mi_tls_slot(size_t slot) mi_attr_noexcept {
uintptr_t tid; void* res;
const size_t ofs = (slot*sizeof(void*));
#if defined(__i386__) #if defined(__i386__)
__asm__("movl %%gs:0, %0" : "=r" (tid) : : ); // 32-bit always uses GS __asm__("movl %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // 32-bit always uses GS
#elif defined(__MACH__) #elif defined(__MACH__) && defined(__x86_64__)
__asm__("movq %%gs:0, %0" : "=r" (tid) : : ); // x86_64 macOS uses GS __asm__("movq %%gs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 macOSX uses GS
#elif defined(__x86_64__) #elif defined(__x86_64__)
__asm__("movq %%fs:0, %0" : "=r" (tid) : : ); // x86_64 Linux, BSD uses FS __asm__("movq %%fs:%1, %0" : "=r" (res) : "m" (*((void**)ofs)) : ); // x86_64 Linux, BSD uses FS
#elif defined(__arm__) #elif defined(__arm__)
asm volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (tid)); void** tcb; UNUSED(ofs);
asm volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb));
res = tcb[slot];
#elif defined(__aarch64__) #elif defined(__aarch64__)
asm volatile ("mrs %0, tpidr_el0" : "=r" (tid)); void** tcb; UNUSED(ofs);
asm volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
res = tcb[slot];
#endif #endif
return tid; return res;
}
// setting is only used on macOSX for now
static inline void mi_tls_slot_set(size_t slot, void* value) mi_attr_noexcept {
const size_t ofs = (slot*sizeof(void*));
#if defined(__i386__)
__asm__("movl %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // 32-bit always uses GS
#elif defined(__MACH__) && defined(__x86_64__)
__asm__("movq %1,%%gs:%0" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 macOSX uses GS
#elif defined(__x86_64__)
__asm__("movq %1,%%fs:%1" : "=m" (*((void**)ofs)) : "rn" (value) : ); // x86_64 Linux, BSD uses FS
#elif defined(__arm__)
void** tcb; UNUSED(ofs);
asm volatile ("mrc p15, 0, %0, c13, c0, 3\nbic %0, %0, #3" : "=r" (tcb));
tcb[slot] = value;
#elif defined(__aarch64__)
void** tcb; UNUSED(ofs);
asm volatile ("mrs %0, tpidr_el0" : "=r" (tcb));
tcb[slot] = value;
#endif
}
static inline uintptr_t _mi_thread_id(void) mi_attr_noexcept {
// in all our targets, slot 0 is the pointer to the thread control block
return (uintptr_t)mi_tls_slot(0);
} }
#else #else
// otherwise use standard C // otherwise use standard C

View file

@ -32,8 +32,8 @@ terms of the MIT license. A copy of the license can be found in the file
void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); } void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); }
#if (__cplusplus >= 201402L || _MSC_VER >= 1916) #if (__cplusplus >= 201402L || _MSC_VER >= 1916)
void operator delete (void* p, std::size_t n) { mi_free_size(p,n); }; void operator delete (void* p, std::size_t n) noexcept { mi_free_size(p,n); };
void operator delete[](void* p, std::size_t n) { mi_free_size(p,n); }; void operator delete[](void* p, std::size_t n) noexcept { mi_free_size(p,n); };
#endif #endif
#if (__cplusplus > 201402L || defined(__cpp_aligned_new)) #if (__cplusplus > 201402L || defined(__cpp_aligned_new))

View file

@ -12,6 +12,10 @@ terms of the MIT license. A copy of the license can be found in the file
#include <stdint.h> // uintptr_t, uint16_t, etc #include <stdint.h> // uintptr_t, uint16_t, etc
#include <mimalloc-atomic.h> // _Atomic #include <mimalloc-atomic.h> // _Atomic
// Minimal alignment necessary. On most platforms 16 bytes are needed
// due to SSE registers for example. This must be at least `MI_INTPTR_SIZE`
#define MI_MAX_ALIGN_SIZE 16 // sizeof(max_align_t)
// ------------------------------------------------------ // ------------------------------------------------------
// Variants // Variants
// ------------------------------------------------------ // ------------------------------------------------------
@ -22,30 +26,46 @@ terms of the MIT license. A copy of the license can be found in the file
// Define MI_STAT as 1 to maintain statistics; set it to 2 to have detailed statistics (but costs some performance). // Define MI_STAT as 1 to maintain statistics; set it to 2 to have detailed statistics (but costs some performance).
// #define MI_STAT 1 // #define MI_STAT 1
// Define MI_SECURE as 1 to encode free lists // Define MI_SECURE to enable security mitigations
// #define MI_SECURE 1 // #define MI_SECURE 1 // guard page around metadata
// #define MI_SECURE 2 // guard page around each mimalloc page
// #define MI_SECURE 3 // encode free lists (detect corrupted free list (buffer overflow), and invalid pointer free)
// #define MI_SECURE 4 // checks for double free. (may be more expensive)
#if !defined(MI_SECURE) #if !defined(MI_SECURE)
#define MI_SECURE 0 #define MI_SECURE 0
#endif #endif
// Define MI_DEBUG as 1 for basic assert checks and statistics // Define MI_DEBUG for debug mode
// set it to 2 to do internal asserts, // #define MI_DEBUG 1 // basic assertion checks and statistics, check double free, corrupted free list, and invalid pointer free.
// and to 3 to do extensive invariant checking. // #define MI_DEBUG 2 // + internal assertion checks
// #define MI_DEBUG 3 // + extensive internal invariant checking (cmake -DMI_DEBUG_FULL=ON)
#if !defined(MI_DEBUG) #if !defined(MI_DEBUG)
#if !defined(NDEBUG) || defined(_DEBUG) #if !defined(NDEBUG) || defined(_DEBUG)
#define MI_DEBUG 1 #define MI_DEBUG 2
#else #else
#define MI_DEBUG 0 #define MI_DEBUG 0
#endif #endif
#endif #endif
// Reserve extra padding at the end of each block to be more resilient against heap block overflows.
// The padding can detect byte-precise buffer overflow on free.
#if !defined(MI_PADDING) && (MI_DEBUG>=1)
#define MI_PADDING 1
#endif
// Encoded free lists allow detection of corrupted free lists
// and can detect buffer overflows, modify after free, and double `free`s.
#if (MI_SECURE>=3 || MI_DEBUG>=1 || defined(MI_PADDING))
#define MI_ENCODE_FREELIST 1
#endif
// ------------------------------------------------------ // ------------------------------------------------------
// Platform specific values // Platform specific values
// ------------------------------------------------------ // ------------------------------------------------------
// ------------------------------------------------------ // ------------------------------------------------------
// Size of a pointer. // Size of a pointer.
// We assume that `sizeof(void*)==sizeof(intptr_t)` // We assume that `sizeof(void*)==sizeof(intptr_t)`
@ -67,11 +87,13 @@ terms of the MIT license. A copy of the license can be found in the file
#endif #endif
#define MI_INTPTR_SIZE (1<<MI_INTPTR_SHIFT) #define MI_INTPTR_SIZE (1<<MI_INTPTR_SHIFT)
#define MI_INTPTR_BITS (MI_INTPTR_SIZE*8)
#define KiB ((size_t)1024) #define KiB ((size_t)1024)
#define MiB (KiB*KiB) #define MiB (KiB*KiB)
#define GiB (MiB*KiB) #define GiB (MiB*KiB)
// ------------------------------------------------------ // ------------------------------------------------------
// Main internal data-structures // Main internal data-structures
// ------------------------------------------------------ // ------------------------------------------------------
@ -84,12 +106,12 @@ terms of the MIT license. A copy of the license can be found in the file
#define MI_SEGMENT_SHIFT ( MI_LARGE_PAGE_SHIFT) // 4mb #define MI_SEGMENT_SHIFT ( MI_LARGE_PAGE_SHIFT) // 4mb
// Derived constants // Derived constants
#define MI_SEGMENT_SIZE (1<<MI_SEGMENT_SHIFT) #define MI_SEGMENT_SIZE (1UL<<MI_SEGMENT_SHIFT)
#define MI_SEGMENT_MASK ((uintptr_t)MI_SEGMENT_SIZE - 1) #define MI_SEGMENT_MASK ((uintptr_t)MI_SEGMENT_SIZE - 1)
#define MI_SMALL_PAGE_SIZE (1<<MI_SMALL_PAGE_SHIFT) #define MI_SMALL_PAGE_SIZE (1UL<<MI_SMALL_PAGE_SHIFT)
#define MI_MEDIUM_PAGE_SIZE (1<<MI_MEDIUM_PAGE_SHIFT) #define MI_MEDIUM_PAGE_SIZE (1UL<<MI_MEDIUM_PAGE_SHIFT)
#define MI_LARGE_PAGE_SIZE (1<<MI_LARGE_PAGE_SHIFT) #define MI_LARGE_PAGE_SIZE (1UL<<MI_LARGE_PAGE_SHIFT)
#define MI_SMALL_PAGES_PER_SEGMENT (MI_SEGMENT_SIZE/MI_SMALL_PAGE_SIZE) #define MI_SMALL_PAGES_PER_SEGMENT (MI_SEGMENT_SIZE/MI_SMALL_PAGE_SIZE)
#define MI_MEDIUM_PAGES_PER_SEGMENT (MI_SEGMENT_SIZE/MI_MEDIUM_PAGE_SIZE) #define MI_MEDIUM_PAGES_PER_SEGMENT (MI_SEGMENT_SIZE/MI_MEDIUM_PAGE_SIZE)
@ -103,10 +125,6 @@ terms of the MIT license. A copy of the license can be found in the file
#define MI_LARGE_OBJ_WSIZE_MAX (MI_LARGE_OBJ_SIZE_MAX/MI_INTPTR_SIZE) #define MI_LARGE_OBJ_WSIZE_MAX (MI_LARGE_OBJ_SIZE_MAX/MI_INTPTR_SIZE)
#define MI_HUGE_OBJ_SIZE_MAX (2*MI_INTPTR_SIZE*MI_SEGMENT_SIZE) // (must match MI_REGION_MAX_ALLOC_SIZE in memory.c) #define MI_HUGE_OBJ_SIZE_MAX (2*MI_INTPTR_SIZE*MI_SEGMENT_SIZE) // (must match MI_REGION_MAX_ALLOC_SIZE in memory.c)
// Minimal alignment necessary. On most platforms 16 bytes are needed
// due to SSE registers for example. This must be at least `MI_INTPTR_SIZE`
#define MI_MAX_ALIGN_SIZE 16 // sizeof(max_align_t)
// Maximum number of size classes. (spaced exponentially in 12.5% increments) // Maximum number of size classes. (spaced exponentially in 12.5% increments)
#define MI_BIN_HUGE (73U) #define MI_BIN_HUGE (73U)
@ -114,6 +132,11 @@ terms of the MIT license. A copy of the license can be found in the file
#error "define more bins" #error "define more bins"
#endif #endif
// Used as a special value to encode block sizes in 32 bits.
#define MI_HUGE_BLOCK_SIZE ((uint32_t)MI_HUGE_OBJ_SIZE_MAX)
// The free lists use encoded next fields
// (Only actually encodes when MI_ENCODED_FREELIST is defined.)
typedef uintptr_t mi_encoded_t; typedef uintptr_t mi_encoded_t;
// free lists contain blocks // free lists contain blocks
@ -122,24 +145,23 @@ typedef struct mi_block_s {
} mi_block_t; } mi_block_t;
// The delayed flags are used for efficient multi-threaded free-ing
typedef enum mi_delayed_e { typedef enum mi_delayed_e {
MI_NO_DELAYED_FREE = 0, MI_USE_DELAYED_FREE = 0, // push on the owning heap thread delayed list
MI_USE_DELAYED_FREE = 1, MI_DELAYED_FREEING = 1, // temporary: another thread is accessing the owning heap
MI_DELAYED_FREEING = 2, MI_NO_DELAYED_FREE = 2, // optimize: push on page local thread free queue if another block is already in the heap thread delayed free list
MI_NEVER_DELAYED_FREE = 3 MI_NEVER_DELAYED_FREE = 3 // sticky, only resets on page reclaim
} mi_delayed_t; } mi_delayed_t;
// The `in_full` and `has_aligned` page flags are put in a union to efficiently // The `in_full` and `has_aligned` page flags are put in a union to efficiently
// test if both are false (`value == 0`) in the `mi_free` routine. // test if both are false (`full_aligned == 0`) in the `mi_free` routine.
typedef union mi_page_flags_u { typedef union mi_page_flags_s {
uint16_t value;
uint8_t full_aligned; uint8_t full_aligned;
struct { struct {
bool in_full:1; uint8_t in_full : 1;
bool has_aligned:1; uint8_t has_aligned : 1;
bool is_zero; // `true` if the blocks in the free list are zero initialized } x;
};
} mi_page_flags_t; } mi_page_flags_t;
// Thread free list. // Thread free list.
@ -156,48 +178,56 @@ typedef uintptr_t mi_thread_free_t;
// implement a monotonic heartbeat. The `thread_free` list is needed for // implement a monotonic heartbeat. The `thread_free` list is needed for
// avoiding atomic operations in the common case. // avoiding atomic operations in the common case.
// //
// `used - thread_freed` == actual blocks that are in use (alive)
// `used - thread_freed + |free| + |local_free| == capacity`
// //
// note: we don't count `freed` (as |free|) instead of `used` to reduce // `used - |thread_free|` == actual blocks that are in use (alive)
// `used - |thread_free| + |free| + |local_free| == capacity`
//
// We don't count `freed` (as |free|) but use `used` to reduce
// the number of memory accesses in the `mi_page_all_free` function(s). // the number of memory accesses in the `mi_page_all_free` function(s).
// note: the funny layout here is due to: //
// - access is optimized for `mi_free` and `mi_page_alloc` // Notes:
// - using `uint16_t` does not seem to slow things down // - Access is optimized for `mi_free` and `mi_page_alloc` (in `alloc.c`)
// - Using `uint16_t` does not seem to slow things down
// - The size is 8 words on 64-bit which helps the page index calculations
// (and 10 words on 32-bit, and encoded free lists add 2 words. Sizes 10
// and 12 are still good for address calculation)
// - To limit the structure size, the `xblock_size` is 32-bits only; for
// blocks > MI_HUGE_BLOCK_SIZE the size is determined from the segment page size
// - `thread_free` uses the bottom bits as a delayed-free flags to optimize
// concurrent frees where only the first concurrent free adds to the owning
// heap `thread_delayed_free` list (see `alloc.c:mi_free_block_mt`).
// The invariant is that no-delayed-free is only set if there is
// at least one block that will be added, or as already been added, to
// the owning heap `thread_delayed_free` list. This guarantees that pages
// will be freed correctly even if only other threads free blocks.
typedef struct mi_page_s { typedef struct mi_page_s {
// "owned" by the segment // "owned" by the segment
uint8_t segment_idx; // index in the segment `pages` array, `page == &segment->pages[page->segment_idx]` uint8_t segment_idx; // index in the segment `pages` array, `page == &segment->pages[page->segment_idx]`
bool segment_in_use:1; // `true` if the segment allocated this page uint8_t segment_in_use:1; // `true` if the segment allocated this page
bool is_reset:1; // `true` if the page memory was reset uint8_t is_reset:1; // `true` if the page memory was reset
bool is_committed:1; // `true` if the page virtual memory is committed uint8_t is_committed:1; // `true` if the page virtual memory is committed
bool is_zero_init:1; // `true` if the page was zero initialized uint8_t is_zero_init:1; // `true` if the page was zero initialized
// layout like this to optimize access in `mi_malloc` and `mi_free` // layout like this to optimize access in `mi_malloc` and `mi_free`
uint16_t capacity; // number of blocks committed, must be the first field, see `segment.c:page_clear` uint16_t capacity; // number of blocks committed, must be the first field, see `segment.c:page_clear`
uint16_t reserved; // number of blocks reserved in memory uint16_t reserved; // number of blocks reserved in memory
mi_page_flags_t flags; // `in_full` and `has_aligned` flags (16 bits) mi_page_flags_t flags; // `in_full` and `has_aligned` flags (8 bits)
uint8_t is_zero:1; // `true` if the blocks in the free list are zero initialized
uint8_t retire_expire:7; // expiration count for retired blocks
mi_block_t* free; // list of available free blocks (`malloc` allocates from this list) mi_block_t* free; // list of available free blocks (`malloc` allocates from this list)
#if MI_SECURE #ifdef MI_ENCODE_FREELIST
uintptr_t cookie; // random cookie to encode the free lists uintptr_t keys[2]; // two random keys to encode the free lists (see `_mi_block_next`)
#endif #endif
size_t used; // number of blocks in use (including blocks in `local_free` and `thread_free`) uint32_t used; // number of blocks in use (including blocks in `local_free` and `thread_free`)
uint32_t xblock_size; // size available in each block (always `>0`)
mi_block_t* local_free; // list of deferred free blocks by this thread (migrates to `free`) mi_block_t* local_free; // list of deferred free blocks by this thread (migrates to `free`)
volatile _Atomic(uintptr_t) thread_freed; // at least this number of blocks are in `thread_free` volatile _Atomic(mi_thread_free_t) xthread_free; // list of deferred free blocks freed by other threads
volatile _Atomic(mi_thread_free_t) thread_free; // list of deferred free blocks freed by other threads volatile _Atomic(uintptr_t) xheap;
// less accessed info
size_t block_size; // size available in each block (always `>0`)
mi_heap_t* heap; // the owning heap
struct mi_page_s* next; // next page owned by this thread with the same `block_size` struct mi_page_s* next; // next page owned by this thread with the same `block_size`
struct mi_page_s* prev; // previous page owned by this thread with the same `block_size` struct mi_page_s* prev; // previous page owned by this thread with the same `block_size`
// improve page index calculation
// without padding: 10 words on 64-bit, 11 on 32-bit. Secure adds one word
#if (MI_INTPTR_SIZE==8 && MI_SECURE>0) || (MI_INTPTR_SIZE==4 && MI_SECURE==0)
void* padding[1]; // 12 words on 64-bit in secure mode, 12 words on 32-bit plain
#endif
} mi_page_t; } mi_page_t;
@ -221,13 +251,15 @@ typedef struct mi_segment_s {
// segment fields // segment fields
struct mi_segment_s* next; // must be the first segment field -- see `segment.c:segment_alloc` struct mi_segment_s* next; // must be the first segment field -- see `segment.c:segment_alloc`
struct mi_segment_s* prev; struct mi_segment_s* prev;
volatile _Atomic(struct mi_segment_s*) abandoned_next; struct mi_segment_s* abandoned_next;
size_t abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`) size_t abandoned; // abandoned pages (i.e. the original owning thread stopped) (`abandoned <= used`)
size_t abandoned_visits; // count how often this segment is visited in the abandoned list (to force reclaim it it is too long)
size_t used; // count of pages in use (`used <= capacity`) size_t used; // count of pages in use (`used <= capacity`)
size_t capacity; // count of available pages (`#free + used`) size_t capacity; // count of available pages (`#free + used`)
size_t segment_size;// for huge pages this may be different from `MI_SEGMENT_SIZE` size_t segment_size;// for huge pages this may be different from `MI_SEGMENT_SIZE`
size_t segment_info_size; // space we are using from the first page for segment meta-data and possible guard pages. size_t segment_info_size; // space we are using from the first page for segment meta-data and possible guard pages.
uintptr_t cookie; // verify addresses in debug mode: `mi_ptr_cookie(segment) == segment->cookie` uintptr_t cookie; // verify addresses in secure mode: `_mi_ptr_cookie(segment) == segment->cookie`
// layout like this to optimize access in `mi_free` // layout like this to optimize access in `mi_free`
size_t page_shift; // `1 << page_shift` == the page sizes == `page->block_size * page->reserved` (unless the first page, then `-segment_info_size`). size_t page_shift; // `1 << page_shift` == the page sizes == `page->block_size * page->reserved` (unless the first page, then `-segment_info_size`).
@ -262,16 +294,42 @@ typedef struct mi_page_queue_s {
#define MI_BIN_FULL (MI_BIN_HUGE+1) #define MI_BIN_FULL (MI_BIN_HUGE+1)
// Random context
typedef struct mi_random_cxt_s {
uint32_t input[16];
uint32_t output[16];
int output_available;
} mi_random_ctx_t;
// In debug mode there is a padding stucture at the end of the blocks to check for buffer overflows
#if defined(MI_PADDING)
typedef struct mi_padding_s {
uint32_t canary; // encoded block value to check validity of the padding (in case of overflow)
uint32_t delta; // padding bytes before the block. (mi_usable_size(p) - delta == exact allocated bytes)
} mi_padding_t;
#define MI_PADDING_SIZE (sizeof(mi_padding_t))
#define MI_PADDING_WSIZE ((MI_PADDING_SIZE + MI_INTPTR_SIZE - 1) / MI_INTPTR_SIZE)
#else
#define MI_PADDING_SIZE 0
#define MI_PADDING_WSIZE 0
#endif
#define MI_PAGES_DIRECT (MI_SMALL_WSIZE_MAX + MI_PADDING_WSIZE + 1)
// A heap owns a set of pages. // A heap owns a set of pages.
struct mi_heap_s { struct mi_heap_s {
mi_tld_t* tld; mi_tld_t* tld;
mi_page_t* pages_free_direct[MI_SMALL_WSIZE_MAX + 2]; // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size. mi_page_t* pages_free_direct[MI_PAGES_DIRECT]; // optimize: array where every entry points a page with possibly free blocks in the corresponding queue for that size.
mi_page_queue_t pages[MI_BIN_FULL + 1]; // queue of pages for each size class (or "bin") mi_page_queue_t pages[MI_BIN_FULL + 1]; // queue of pages for each size class (or "bin")
volatile _Atomic(mi_block_t*) thread_delayed_free; volatile _Atomic(mi_block_t*) thread_delayed_free;
uintptr_t thread_id; // thread this heap belongs too uintptr_t thread_id; // thread this heap belongs too
uintptr_t cookie; uintptr_t cookie; // random cookie to verify pointers (see `_mi_ptr_cookie`)
uintptr_t random; // random number used for secure allocation uintptr_t keys[2]; // two random keys used to encode the `thread_delayed_free` list
mi_random_ctx_t random; // random number context used for secure allocation
size_t page_count; // total number of pages in the `pages` queues. size_t page_count; // total number of pages in the `pages` queues.
mi_heap_t* next; // list of heaps per thread
bool no_reclaim; // `true` if this heap should not reclaim abandoned pages bool no_reclaim; // `true` if this heap should not reclaim abandoned pages
}; };
@ -283,7 +341,7 @@ struct mi_heap_s {
#define MI_DEBUG_UNINIT (0xD0) #define MI_DEBUG_UNINIT (0xD0)
#define MI_DEBUG_FREED (0xDF) #define MI_DEBUG_FREED (0xDF)
#define MI_DEBUG_PADDING (0xDE)
#if (MI_DEBUG) #if (MI_DEBUG)
// use our own assertion to print without memory allocation // use our own assertion to print without memory allocation
@ -338,14 +396,14 @@ typedef struct mi_stats_s {
mi_stat_count_t page_committed; mi_stat_count_t page_committed;
mi_stat_count_t segments_abandoned; mi_stat_count_t segments_abandoned;
mi_stat_count_t pages_abandoned; mi_stat_count_t pages_abandoned;
mi_stat_count_t pages_extended;
mi_stat_count_t mmap_calls;
mi_stat_count_t commit_calls;
mi_stat_count_t threads; mi_stat_count_t threads;
mi_stat_count_t huge; mi_stat_count_t huge;
mi_stat_count_t giant; mi_stat_count_t giant;
mi_stat_count_t malloc; mi_stat_count_t malloc;
mi_stat_count_t segments_cache; mi_stat_count_t segments_cache;
mi_stat_counter_t pages_extended;
mi_stat_counter_t mmap_calls;
mi_stat_counter_t commit_calls;
mi_stat_counter_t page_no_retire; mi_stat_counter_t page_no_retire;
mi_stat_counter_t searches; mi_stat_counter_t searches;
mi_stat_counter_t huge_count; mi_stat_counter_t huge_count;
@ -373,22 +431,29 @@ void _mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount);
#define mi_heap_stat_increase(heap,stat,amount) mi_stat_increase( (heap)->tld->stats.stat, amount) #define mi_heap_stat_increase(heap,stat,amount) mi_stat_increase( (heap)->tld->stats.stat, amount)
#define mi_heap_stat_decrease(heap,stat,amount) mi_stat_decrease( (heap)->tld->stats.stat, amount) #define mi_heap_stat_decrease(heap,stat,amount) mi_stat_decrease( (heap)->tld->stats.stat, amount)
// ------------------------------------------------------ // ------------------------------------------------------
// Thread Local data // Thread Local data
// ------------------------------------------------------ // ------------------------------------------------------
typedef int64_t mi_msecs_t;
// Queue of segments // Queue of segments
typedef struct mi_segment_queue_s { typedef struct mi_segment_queue_s {
mi_segment_t* first; mi_segment_t* first;
mi_segment_t* last; mi_segment_t* last;
} mi_segment_queue_t; } mi_segment_queue_t;
// OS thread local data
typedef struct mi_os_tld_s {
size_t region_idx; // start point for next allocation
mi_stats_t* stats; // points to tld stats
} mi_os_tld_t;
// Segments thread local data // Segments thread local data
typedef struct mi_segments_tld_s { typedef struct mi_segments_tld_s {
mi_segment_queue_t small_free; // queue of segments with free small pages mi_segment_queue_t small_free; // queue of segments with free small pages
mi_segment_queue_t medium_free; // queue of segments with free medium pages mi_segment_queue_t medium_free; // queue of segments with free medium pages
mi_page_queue_t pages_reset; // queue of freed pages that can be reset
size_t count; // current number of segments; size_t count; // current number of segments;
size_t peak_count; // peak number of segments size_t peak_count; // peak number of segments
size_t current_size; // current size of all segments size_t current_size; // current size of all segments
@ -397,19 +462,15 @@ typedef struct mi_segments_tld_s {
size_t cache_size; // total size of all segments in the cache size_t cache_size; // total size of all segments in the cache
mi_segment_t* cache; // (small) cache of segments mi_segment_t* cache; // (small) cache of segments
mi_stats_t* stats; // points to tld stats mi_stats_t* stats; // points to tld stats
mi_os_tld_t* os; // points to os stats
} mi_segments_tld_t; } mi_segments_tld_t;
// OS thread local data
typedef struct mi_os_tld_s {
size_t region_idx; // start point for next allocation
mi_stats_t* stats; // points to tld stats
} mi_os_tld_t;
// Thread local data // Thread local data
struct mi_tld_s { struct mi_tld_s {
unsigned long long heartbeat; // monotonic heartbeat count unsigned long long heartbeat; // monotonic heartbeat count
bool recurse; // true if deferred was called; used to prevent infinite recursion. bool recurse; // true if deferred was called; used to prevent infinite recursion.
mi_heap_t* heap_backing; // backing heap of this thread (cannot be deleted) mi_heap_t* heap_backing; // backing heap of this thread (cannot be deleted)
mi_heap_t* heaps; // list of heaps in this thread (so we can abandon all when the thread terminates)
mi_segments_tld_t segments; // segment tld mi_segments_tld_t segments; // segment tld
mi_os_tld_t os; // os tld mi_os_tld_t os; // os tld
mi_stats_t stats; // statistics mi_stats_t stats; // statistics

View file

@ -8,22 +8,32 @@ 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 110 // major + 2 digits minor #define MI_MALLOC_VERSION 161 // major + 2 digits minor
// ------------------------------------------------------ // ------------------------------------------------------
// Compiler specific attributes // Compiler specific attributes
// ------------------------------------------------------ // ------------------------------------------------------
#ifdef __cplusplus #ifdef __cplusplus
#if (__GNUC__ <= 5) || (_MSC_VER <= 1900) #if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
#define mi_attr_noexcept throw()
#else
#define mi_attr_noexcept noexcept #define mi_attr_noexcept noexcept
#else
#define mi_attr_noexcept throw()
#endif #endif
#else #else
#define mi_attr_noexcept #define mi_attr_noexcept
#endif #endif
#if (__cplusplus >= 201703)
#define mi_decl_nodiscard [[nodiscard]]
#elif (__GNUC__ >= 4) || defined(__clang__) // includes clang, icc, and clang-cl
#define mi_decl_nodiscard __attribute__((warn_unused_result))
#elif (_MSC_VER >= 1700)
#define mi_decl_nodiscard _Check_return_
#else
#define mi_decl_nodiscard
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#if !defined(MI_SHARED_LIB) #if !defined(MI_SHARED_LIB)
#define mi_decl_export #define mi_decl_export
@ -33,36 +43,41 @@ terms of the MIT license. A copy of the license can be found in the file
#define mi_decl_export __declspec(dllimport) #define mi_decl_export __declspec(dllimport)
#endif #endif
#if (_MSC_VER >= 1900) && !defined(__EDG__) #if (_MSC_VER >= 1900) && !defined(__EDG__)
#define mi_decl_allocator __declspec(allocator) __declspec(restrict) #define mi_decl_restrict __declspec(allocator) __declspec(restrict)
#else #else
#define mi_decl_allocator __declspec(restrict) #define mi_decl_restrict __declspec(restrict)
#endif #endif
#define mi_decl_thread __declspec(thread) #define mi_cdecl __cdecl
#define mi_attr_malloc #define mi_attr_malloc
#define mi_attr_alloc_size(s) #define mi_attr_alloc_size(s)
#define mi_attr_alloc_size2(s1,s2) #define mi_attr_alloc_size2(s1,s2)
#define mi_cdecl __cdecl #define mi_attr_alloc_align(p)
#elif defined(__GNUC__) || defined(__clang__) #elif defined(__GNUC__) // includes clang and icc
#define mi_decl_thread __thread #define mi_cdecl // leads to warnings... __attribute__((cdecl))
#define mi_decl_export __attribute__((visibility("default"))) #define mi_decl_export __attribute__((visibility("default")))
#define mi_decl_allocator #define mi_decl_restrict
#define mi_attr_malloc __attribute__((malloc)) #define mi_attr_malloc __attribute__((malloc))
#if defined(__clang_major__) && (__clang_major__ < 4) #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5)
#define mi_attr_alloc_size(s) #define mi_attr_alloc_size(s)
#define mi_attr_alloc_size2(s1,s2) #define mi_attr_alloc_size2(s1,s2)
#define mi_attr_alloc_align(p)
#elif defined(__INTEL_COMPILER)
#define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
#define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
#define mi_attr_alloc_align(p)
#else #else
#define mi_attr_alloc_size(s) __attribute__((alloc_size(s))) #define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
#define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2))) #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
#define mi_attr_alloc_align(p) __attribute__((alloc_align(p)))
#endif #endif
#define mi_cdecl // leads to warnings... __attribute__((cdecl))
#else #else
#define mi_decl_thread __thread #define mi_cdecl
#define mi_decl_export #define mi_decl_export
#define mi_decl_allocator #define mi_decl_restrict
#define mi_attr_malloc #define mi_attr_malloc
#define mi_attr_alloc_size(s) #define mi_attr_alloc_size(s)
#define mi_attr_alloc_size2(s1,s2) #define mi_attr_alloc_size2(s1,s2)
#define mi_cdecl #define mi_attr_alloc_align(p)
#endif #endif
// ------------------------------------------------------ // ------------------------------------------------------
@ -80,15 +95,15 @@ extern "C" {
// Standard malloc interface // Standard malloc interface
// ------------------------------------------------------ // ------------------------------------------------------
mi_decl_export mi_decl_allocator void* mi_malloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_export mi_decl_allocator void* mi_calloc(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
mi_decl_export mi_decl_allocator void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
mi_decl_export mi_decl_allocator void* mi_expand(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_export void* mi_expand(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
mi_decl_export void mi_free(void* p) mi_attr_noexcept; mi_decl_export void mi_free(void* p) mi_attr_noexcept;
mi_decl_export char* mi_strdup(const char* s) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept mi_attr_malloc;
mi_decl_export char* mi_strndup(const char* s, size_t n) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept mi_attr_malloc;
mi_decl_export char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc;
// ------------------------------------------------------ // ------------------------------------------------------
// Extended functionality // Extended functionality
@ -96,34 +111,42 @@ mi_decl_export char* mi_realpath(const char* fname, char* resolved_name) mi_attr
#define MI_SMALL_WSIZE_MAX (128) #define MI_SMALL_WSIZE_MAX (128)
#define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*)) #define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*))
mi_decl_export mi_decl_allocator void* mi_malloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_export mi_decl_allocator void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_export mi_decl_allocator void* mi_zalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_export mi_decl_allocator void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
mi_decl_export mi_decl_allocator void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3); mi_decl_nodiscard mi_decl_export void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3);
mi_decl_export mi_decl_allocator void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
mi_decl_nodiscard mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept;
mi_decl_nodiscard mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept;
mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept; // ------------------------------------------------------
mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept; // Internals
// ------------------------------------------------------
typedef void (mi_deferred_free_fun)(bool force, unsigned long long heartbeat); typedef void (mi_cdecl mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg);
mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free) mi_attr_noexcept; mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg) mi_attr_noexcept;
typedef void (mi_output_fun)(const char* msg); typedef void (mi_cdecl mi_output_fun)(const char* msg, void* arg);
mi_decl_export void mi_register_output(mi_output_fun* out) mi_attr_noexcept; mi_decl_export void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept;
typedef void (mi_cdecl mi_error_fun)(int err, void* arg);
mi_decl_export void mi_register_error(mi_error_fun* fun, void* arg);
mi_decl_export void mi_collect(bool force) mi_attr_noexcept; mi_decl_export void mi_collect(bool force) mi_attr_noexcept;
mi_decl_export int mi_version(void) mi_attr_noexcept; mi_decl_export int mi_version(void) mi_attr_noexcept;
mi_decl_export void mi_stats_reset(void) mi_attr_noexcept; mi_decl_export void mi_stats_reset(void) mi_attr_noexcept;
mi_decl_export void mi_stats_merge(void) mi_attr_noexcept; mi_decl_export void mi_stats_merge(void) mi_attr_noexcept;
mi_decl_export void mi_stats_print(mi_output_fun* out) mi_attr_noexcept; mi_decl_export void mi_stats_print(void* out) mi_attr_noexcept; // backward compatibility: `out` is ignored and should be NULL
mi_decl_export void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
mi_decl_export void mi_process_init(void) mi_attr_noexcept; mi_decl_export void mi_process_init(void) mi_attr_noexcept;
mi_decl_export void mi_thread_init(void) mi_attr_noexcept; mi_decl_export void mi_thread_init(void) mi_attr_noexcept;
mi_decl_export void mi_thread_done(void) mi_attr_noexcept; mi_decl_export void mi_thread_done(void) mi_attr_noexcept;
mi_decl_export void mi_thread_stats_print(mi_output_fun* out) mi_attr_noexcept; mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
@ -132,23 +155,24 @@ mi_decl_export void mi_thread_stats_print(mi_output_fun* out) mi_attr_noexcept;
// allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`. // allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
mi_decl_export mi_decl_allocator void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
mi_decl_export mi_decl_allocator void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_export mi_decl_allocator void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
mi_decl_export mi_decl_allocator void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_export mi_decl_allocator void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2) mi_attr_alloc_align(3);
mi_decl_export mi_decl_allocator void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
mi_decl_export mi_decl_allocator void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3);
mi_decl_export mi_decl_allocator void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2);
// ------------------------------------------------------ // -------------------------------------------------------------------------------------
// Heaps // Heaps: first-class, but can only allocate from the same thread that created it.
// ------------------------------------------------------ // -------------------------------------------------------------------------------------
struct mi_heap_s; struct mi_heap_s;
typedef struct mi_heap_s mi_heap_t; typedef struct mi_heap_s mi_heap_t;
mi_decl_export mi_heap_t* mi_heap_new(void); mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new(void);
mi_decl_export void mi_heap_delete(mi_heap_t* heap); mi_decl_export void mi_heap_delete(mi_heap_t* heap);
mi_decl_export void mi_heap_destroy(mi_heap_t* heap); mi_decl_export void mi_heap_destroy(mi_heap_t* heap);
mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap); mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap);
@ -156,28 +180,28 @@ mi_decl_export mi_heap_t* mi_heap_get_default(void);
mi_decl_export mi_heap_t* mi_heap_get_backing(void); mi_decl_export mi_heap_t* mi_heap_get_backing(void);
mi_decl_export void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept; mi_decl_export void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept;
mi_decl_export mi_decl_allocator void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
mi_decl_export mi_decl_allocator void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
mi_decl_export mi_decl_allocator void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3);
mi_decl_export mi_decl_allocator void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3);
mi_decl_export mi_decl_allocator void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
mi_decl_export mi_decl_allocator void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3); mi_decl_nodiscard mi_decl_export void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3);
mi_decl_export mi_decl_allocator void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4);;
mi_decl_export mi_decl_allocator void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3); mi_decl_nodiscard mi_decl_export void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3);
mi_decl_export char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept mi_attr_malloc;
mi_decl_export char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept mi_attr_malloc;
mi_decl_export char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc;
mi_decl_export mi_decl_allocator void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3);
mi_decl_export mi_decl_allocator void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
mi_decl_export mi_decl_allocator void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(3);
mi_decl_export mi_decl_allocator void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2);
mi_decl_export mi_decl_allocator void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3) mi_attr_alloc_align(4);
mi_decl_export mi_decl_allocator void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3);
mi_decl_export mi_decl_allocator void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3); mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4);
mi_decl_export mi_decl_allocator void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3); mi_decl_nodiscard mi_decl_export void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3);
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
@ -187,21 +211,21 @@ mi_decl_export mi_decl_allocator void* mi_heap_realloc_aligned_at(mi_heap_t* hea
// see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992> // see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
mi_decl_export mi_decl_allocator void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
mi_decl_export mi_decl_allocator void* mi_recalloc(void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3); mi_decl_nodiscard mi_decl_export void* mi_recalloc(void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3);
mi_decl_export mi_decl_allocator void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(2) mi_attr_alloc_align(3);
mi_decl_export mi_decl_allocator void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(2);
mi_decl_export mi_decl_allocator void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3); mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(2,3) mi_attr_alloc_align(4);
mi_decl_export mi_decl_allocator void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3); mi_decl_nodiscard mi_decl_export void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(2,3);
mi_decl_export mi_decl_allocator void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3); mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(3);
mi_decl_export mi_decl_allocator void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(3,4); mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t newcount, size_t size) mi_attr_noexcept mi_attr_alloc_size2(3,4);
mi_decl_export mi_decl_allocator void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3); mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept mi_attr_alloc_size(3) mi_attr_alloc_align(4);
mi_decl_export mi_decl_allocator void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(3); mi_decl_nodiscard mi_decl_export void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size(3);
mi_decl_export mi_decl_allocator void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(3,4); mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept mi_attr_alloc_size2(3,4) mi_attr_alloc_align(5);
mi_decl_export mi_decl_allocator void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(3,4); mi_decl_nodiscard mi_decl_export void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept mi_attr_alloc_size2(3,4);
// ------------------------------------------------------ // ------------------------------------------------------
@ -209,7 +233,6 @@ mi_decl_export mi_decl_allocator void* mi_heap_recalloc_aligned_at(mi_heap_t* he
// ------------------------------------------------------ // ------------------------------------------------------
mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p); mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p);
mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p); mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p);
mi_decl_export bool mi_check_owned(const void* p); mi_decl_export bool mi_check_owned(const void* p);
@ -227,9 +250,15 @@ typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_
mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg); mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
// Experimental // Experimental
mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept;
mi_decl_nodiscard mi_decl_export bool mi_is_redirected() mi_attr_noexcept;
mi_decl_export int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept;
mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept;
// deprecated
mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept; mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
mi_decl_export bool mi_is_redirected() mi_attr_noexcept;
// ------------------------------------------------------ // ------------------------------------------------------
// Convenience // Convenience
@ -262,26 +291,30 @@ typedef enum mi_option_e {
// the following options are experimental // the following options are experimental
mi_option_eager_commit, mi_option_eager_commit,
mi_option_eager_region_commit, mi_option_eager_region_commit,
mi_option_reset_decommits,
mi_option_large_os_pages, // implies eager commit mi_option_large_os_pages, // implies eager commit
mi_option_reserve_huge_os_pages, mi_option_reserve_huge_os_pages,
mi_option_segment_cache, mi_option_segment_cache,
mi_option_page_reset, mi_option_page_reset,
mi_option_cache_reset, mi_option_abandoned_page_reset,
mi_option_reset_decommits,
mi_option_eager_commit_delay,
mi_option_segment_reset, mi_option_segment_reset,
mi_option_eager_commit_delay,
mi_option_reset_delay,
mi_option_use_numa_nodes,
mi_option_os_tag, mi_option_os_tag,
_mi_option_last mi_option_max_errors,
_mi_option_last,
mi_option_eager_page_commit = mi_option_eager_commit
} mi_option_t; } mi_option_t;
mi_decl_export bool mi_option_is_enabled(mi_option_t option); mi_decl_nodiscard mi_decl_export bool mi_option_is_enabled(mi_option_t option);
mi_decl_export void mi_option_enable(mi_option_t option); mi_decl_export void mi_option_enable(mi_option_t option);
mi_decl_export void mi_option_disable(mi_option_t option); mi_decl_export void mi_option_disable(mi_option_t option);
mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable); mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable);
mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable); mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable);
mi_decl_export long mi_option_get(mi_option_t option); mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option);
mi_decl_export void mi_option_set(mi_option_t option, long value); mi_decl_export void mi_option_set(mi_option_t option, long value);
mi_decl_export void mi_option_set_default(mi_option_t option, long value); mi_decl_export void mi_option_set_default(mi_option_t option, long value);
@ -289,26 +322,26 @@ mi_decl_export void mi_option_set_default(mi_option_t option, long value);
// ------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------
// "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions. // "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions.
// (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.) // (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.)
// note: we use `mi_cfree` as "checked free" and it checks if the pointer is in our heap before free-ing.
// ------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------
mi_decl_export size_t mi_malloc_size(const void* p) mi_attr_noexcept;
mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept;
mi_decl_export void mi_cfree(void* p) mi_attr_noexcept; mi_decl_export void mi_cfree(void* p) mi_attr_noexcept;
mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept; mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept;
mi_decl_nodiscard mi_decl_export size_t mi_malloc_size(const void* p) mi_attr_noexcept;
mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept;
mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept; mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept;
mi_decl_export void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1);
mi_decl_export void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2) mi_attr_alloc_align(1);
mi_decl_export void* mi_pvalloc(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_alloc_size2(2,3);
mi_decl_export void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept;
mi_decl_export void* mi_reallocarray(void* p, size_t count, size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2,3); mi_decl_nodiscard mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept;
mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept mi_attr_malloc;
mi_decl_export void* mi_aligned_offset_recalloc(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept; mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept mi_attr_malloc;
mi_decl_export unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept;
mi_decl_export unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept;
mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept; mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept;
mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept; mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept;
@ -316,14 +349,74 @@ mi_decl_export void mi_free_size(void* p, size_t size) mi_attr_noexcept;
mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept; mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept;
mi_decl_export void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept; mi_decl_export void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept;
mi_decl_export void* mi_new(size_t n) mi_attr_malloc mi_attr_alloc_size(1); // The `mi_new` wrappers implement C++ semantics on out-of-memory instead of directly returning `NULL`.
mi_decl_export void* mi_new_aligned(size_t n, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1); // (and call `std::get_new_handler` and potentially raise a `std::bad_alloc` exception).
mi_decl_export void* mi_new_nothrow(size_t n) mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new(size_t size) mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_export void* mi_new_aligned_nothrow(size_t n, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1); mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_nothrow(size_t size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new_n(size_t count, size_t size) mi_attr_malloc mi_attr_alloc_size2(1, 2);
mi_decl_nodiscard mi_decl_export void* mi_new_realloc(void* p, size_t newsize) mi_attr_alloc_size(2);
mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount, size_t size) mi_attr_alloc_size2(2, 3);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
// ---------------------------------------------------------------------------------------------
// Implement the C++ std::allocator interface for use in STL containers.
// (note: see `mimalloc-new-delete.h` for overriding the new/delete operators globally)
// ---------------------------------------------------------------------------------------------
#ifdef __cplusplus
#include <cstdint> // PTRDIFF_MAX
#if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
#include <type_traits> // std::true_type
#include <utility> // std::forward
#endif
template<class T> struct mi_stl_allocator {
typedef T value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef value_type& reference;
typedef value_type const& const_reference;
typedef value_type* pointer;
typedef value_type const* const_pointer;
template <class U> struct rebind { typedef mi_stl_allocator<U> other; };
mi_stl_allocator() mi_attr_noexcept = default;
mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept = default;
template<class U> mi_stl_allocator(const mi_stl_allocator<U>&) mi_attr_noexcept { }
mi_stl_allocator select_on_container_copy_construction() const { return *this; }
void deallocate(T* p, size_type) { mi_free(p); }
#if (__cplusplus >= 201703L) // C++17
mi_decl_nodiscard T* allocate(size_type count) { return static_cast<T*>(mi_new_n(count, sizeof(T))); }
mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); }
#else
mi_decl_nodiscard pointer allocate(size_type count, const void* = 0) { return static_cast<pointer>(mi_new_n(count, sizeof(value_type))); }
#endif
#if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11
using propagate_on_container_copy_assignment = std::true_type;
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
using is_always_equal = std::true_type;
template <class U, class ...Args> void construct(U* p, Args&& ...args) { ::new(p) U(std::forward<Args>(args)...); }
template <class U> void destroy(U* p) mi_attr_noexcept { p->~U(); }
#else
void construct(pointer p, value_type const& val) { ::new(p) value_type(val); }
void destroy(pointer p) { p->~value_type(); }
#endif
size_type max_size() const mi_attr_noexcept { return (PTRDIFF_MAX/sizeof(value_type)); }
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
};
template<class T1,class T2> bool operator==(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return true; }
template<class T1,class T2> bool operator!=(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return false; }
#endif // __cplusplus
#endif #endif

303
readme.md
View file

@ -1,7 +1,7 @@
<img align="left" width="100" height="100" src="doc/mimalloc-logo.png"/> <img align="left" width="100" height="100" src="doc/mimalloc-logo.png"/>
[<img align="right" src="https://dev.azure.com/Daan0324/mimalloc/_apis/build/status/microsoft.mimalloc?branchName=master"/>](https://dev.azure.com/Daan0324/mimalloc/_build?definitionId=1&_a=summary) [<img align="right" src="https://dev.azure.com/Daan0324/mimalloc/_apis/build/status/microsoft.mimalloc?branchName=dev"/>](https://dev.azure.com/Daan0324/mimalloc/_build?definitionId=1&_a=summary)
# mimalloc # mimalloc
@ -11,14 +11,14 @@ 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).
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:
``` ```
> LD_PRELOAD=/usr/bin/libmimalloc.so myprogram > LD_PRELOAD=/usr/bin/libmimalloc.so myprogram
``` ```
It also has an easy way to override the allocator in [Windows](#override_on_windows). Notable aspects of the design include:
Notable aspects of the design include:
- __small and consistent__: the library is about 6k LOC using simple and - __small and consistent__: the library is about 6k LOC using simple and
consistent data structures. This makes it very suitable consistent data structures. This makes it very suitable
@ -37,7 +37,7 @@ Notable aspects of the design include:
programs. programs.
- __secure__: _mimalloc_ can be built in secure mode, adding guard pages, - __secure__: _mimalloc_ can be built in secure mode, adding guard pages,
randomized allocation, encrypted free lists, etc. to protect against various randomized allocation, encrypted free lists, etc. to protect against various
heap vulnerabilities. The performance penalty is only around 3% on average heap vulnerabilities. The performance penalty is usually around 10% on average
over our benchmarks. over our benchmarks.
- __first-class heaps__: efficiently create and use multiple heaps to allocate across different regions. - __first-class heaps__: efficiently create and use multiple heaps to allocate across different regions.
A heap can be destroyed at once instead of deallocating each object separately. A heap can be destroyed at once instead of deallocating each object separately.
@ -45,9 +45,10 @@ Notable aspects of the design include:
times (_wcat_), bounded space overhead (~0.2% meta-data, with at most 12.5% waste in allocation sizes), times (_wcat_), bounded space overhead (~0.2% meta-data, with at most 12.5% waste in allocation sizes),
and has no internal points of contention using only atomic operations. and has no internal points of contention using only atomic operations.
- __fast__: In our benchmarks (see [below](#performance)), - __fast__: In our benchmarks (see [below](#performance)),
_mimalloc_ always outperforms all other leading allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc), _mimalloc_ outperforms other leading allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc),
and usually uses less memory (up to 25% more in the worst case). A nice property and usually uses less memory (up to 25% more in the worst case). A nice property
is that it does consistently well over a wide range of benchmarks. is that it does consistently well over a wide range of benchmarks. There is also good huge OS page
support for larger server programs.
The [documentation](https://microsoft.github.io/mimalloc) gives a full overview of the API. The [documentation](https://microsoft.github.io/mimalloc) gives a full overview of the API.
You can read more on the design of _mimalloc_ in the [technical report](https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action) which also has detailed benchmark results. You can read more on the design of _mimalloc_ in the [technical report](https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action) which also has detailed benchmark results.
@ -56,6 +57,20 @@ Enjoy!
### Releases ### Releases
* 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
and thread local support on FreeBSD, NetBSD, DragonFly, and macOSX. New byte-precise
heap block overflow detection in debug mode (besides the double-free detection and free-list
corruption detection). Add `nodiscard` attribute to most allocation functions.
Enable `MIMALLOC_PAGE_RESET` by default. New reclamation strategy for abandoned heap pages
for better memory footprint.
* 2020-02-09, `v1.5.0`: stable release 1.5: improved free performance, small bug fixes.
* 2020-01-22, `v1.4.0`: stable release 1.4: improved performance for delayed OS page reset,
more eager concurrent free, addition of STL allocator, fixed potential memory leak.
* 2020-01-15, `v1.3.0`: stable release 1.3: bug fixes, improved randomness and [stronger
free list encoding](https://github.com/microsoft/mimalloc/blob/783e3377f79ee82af43a0793910a9f2d01ac7863/include/mimalloc-internal.h#L396) in secure mode.
* 2019-12-22, `v1.2.2`: stable release 1.2: minor updates.
* 2019-11-22, `v1.2.0`: stable release 1.2: bug fixes, improved secure mode (free list corruption checks, double free mitigation). Improved dynamic overriding on Windows.
* 2019-10-07, `v1.1.0`: stable release 1.1. * 2019-10-07, `v1.1.0`: stable release 1.1.
* 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.
@ -64,7 +79,7 @@ Enjoy!
## Windows ## Windows
Open `ide/vs2017/mimalloc.sln` in Visual Studio 2017 and build. Open `ide/vs2019/mimalloc.sln` in Visual Studio 2019 and build (or `ide/vs2017/mimalloc.sln`).
The `mimalloc` project builds a static library (in `out/msvc-x64`), while the The `mimalloc` project builds a static library (in `out/msvc-x64`), while the
`mimalloc-override` project builds a DLL for overriding malloc `mimalloc-override` project builds a DLL for overriding malloc
in the entire program. in the entire program.
@ -97,7 +112,7 @@ maintains detailed statistics as:
This will name the shared library as `libmimalloc-debug.so`. This will name the shared library as `libmimalloc-debug.so`.
Finally, you can build a _secure_ version that uses guard pages, encrypted Finally, you can build a _secure_ version that uses guard pages, encrypted
free lists, etc, as: free lists, etc., as:
``` ```
> mkdir -p out/secure > mkdir -p out/secure
> cd out/secure > cd out/secure
@ -126,7 +141,7 @@ mimalloc uses only safe OS calls (`mmap` and `VirtualAlloc`) and can co-exist
with other allocators linked to the same program. with other allocators linked to the same program.
If you use `cmake`, you can simply use: If you use `cmake`, you can simply use:
``` ```
find_package(mimalloc 1.0 REQUIRED) find_package(mimalloc 1.4 REQUIRED)
``` ```
in your `CMakeLists.txt` to find a locally installed mimalloc. Then use either: in your `CMakeLists.txt` to find a locally installed mimalloc. Then use either:
``` ```
@ -138,6 +153,11 @@ target_link_libraries(myapp PUBLIC mimalloc-static)
``` ```
to link with the static library. See `test\CMakeLists.txt` for an example. to link with the static library. See `test\CMakeLists.txt` for an example.
For best performance in C++ programs, it is also recommended to override the
global `new` and `delete` operators. For convience, mimalloc provides
[`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-new-delete.h) which does this for you -- just include it in a single(!) source file in your project.
In C++, mimalloc also provides the `mi_stl_allocator` struct which implements the `std::allocator`
interface.
You can pass environment variables to print verbose messages (`MIMALLOC_VERBOSE=1`) You can pass environment variables to print verbose messages (`MIMALLOC_VERBOSE=1`)
and statistics (`MIMALLOC_SHOW_STATS=1`) (in the debug version): and statistics (`MIMALLOC_SHOW_STATS=1`) (in the debug version):
@ -188,23 +208,35 @@ 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
memory fragmentation in long running (server) programs. If performance is impacted,
`MIMALLOC_RESET_DELAY=`<msecs> can be set higher (100ms by default) to make the page
reset occur less frequently.
- `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages when available; for some workloads this can significantly - `MIMALLOC_LARGE_OS_PAGES=1`: use large OS pages 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. 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_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, in reality it is always better turned off by default on Windows as it looks not good in the task manager. However, turning it on has no
to turn it on as it improves performance and has no other drawbacks. 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 performance improvement on long running workloads. Usually it is better to not use startup and can give quite a (latency) 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. Still experimental. 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
`MIMALLOC_EAGER_COMMIT_DELAY=N` (with usually `N` as 1) to delay the initial `N` 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).
[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
# Overriding Malloc # Overriding Malloc
Overriding the standard `malloc` can be done either _dynamically_ or _statically_. Overriding the standard `malloc` can be done either _dynamically_ or _statically_.
@ -213,7 +245,7 @@ Overriding the standard `malloc` can be done either _dynamically_ or _statically
This is the recommended way to override the standard malloc interface. This is the recommended way to override the standard malloc interface.
### Linux, BSD ### Override on Linux, BSD
On these ELF-based systems we preload the mimalloc shared On these ELF-based systems we preload the mimalloc shared
library so all calls to the standard `malloc` interface are library so all calls to the standard `malloc` interface are
@ -232,7 +264,7 @@ or run with the debug version to get detailed statistics:
> env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram > env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram
``` ```
### MacOS ### Override on MacOS
On macOS we can also preload the mimalloc shared On macOS we can also preload the mimalloc shared
library so all calls to the standard `malloc` interface are library so all calls to the standard `malloc` interface are
@ -244,28 +276,29 @@ 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 ### Override on Windows
On Windows you need to link your program explicitly with the mimalloc <span id="override_on_windows">Overriding on Windows</span> is robust but requires that you link your program explicitly with
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 Moreover, you need to ensure the `mimalloc-redirect.dll` (or `mimalloc-redirect32.dll`) is available
in the same folder as the mimalloc DLL at runtime (as it as referred to by the mimalloc DLL). in the same folder as the main `mimalloc-override.dll` at runtime (as it is a dependency).
The redirection DLL's ensure all calls to the C runtime malloc API get redirected to mimalloc. The redirection DLL ensures that all calls to the C runtime malloc API get redirected to
mimalloc (in `mimalloc-override.dll`).
To ensure the mimalloc DLL is loaded at run-time it is easiest to insert some 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 an example on how to use this. For best performance on Windows with C++, it
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).
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 successfully redirected. overriding at run-time. Use `MIMALLOC_VERBOSE=1` to check if mimalloc was successfully redirected.
(Note: in principle, it should be possible to patch existing executables (Note: in principle, it is possible to patch existing executables
that are linked with the dynamic C runtime (`ucrtbase.dll`) by just putting the mimalloc DLL into 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)
the import table (and putting `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)).
@ -282,71 +315,80 @@ object file. For example:
> gcc -o myprogram mimalloc-override.o myfile1.c ... > gcc -o myprogram mimalloc-override.o myfile1.c ...
``` ```
Another way to override statically that works on all platforms, is to
link statically to mimalloc (as shown in the introduction) and include a
header file in each source file that re-defines `malloc` etc. to `mi_malloc`.
This is provided by [`mimalloc-override.h`](https://github.com/microsoft/mimalloc/blob/master/include/mimalloc-override.h). This only works reliably though if all sources are
under your control or otherwise mixing of pointers from different heaps may occur!
# Performance # Performance
Last update: 2020-01-20
We tested _mimalloc_ against many other top allocators over a wide We tested _mimalloc_ against many other top allocators over a wide
range of benchmarks, ranging from various real world programs to range of benchmarks, ranging from various real world programs to
synthetic benchmarks that see how the allocator behaves under more synthetic benchmarks that see how the allocator behaves under more
extreme circumstances. extreme circumstances. In our benchmark suite, _mimalloc_ outperforms other leading
allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc), and has a similar memory footprint. A nice property is that it
does consistently well over the wide range of benchmarks.
In our benchmarks, _mimalloc_ always outperforms all other leading General memory allocators are interesting as there exists no algorithm that is
allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc), and usually uses less
memory (up to 25% more in the worst case). A nice property is that it
does *consistently* well over the wide range of benchmarks.
Allocators are interesting as there exists no algorithm that is generally
optimal -- for a given allocator one can usually construct a workload optimal -- for a given allocator one can usually construct a workload
where it does not do so well. The goal is thus to find an allocation where it does not do so well. The goal is thus to find an allocation
strategy that performs well over a wide range of benchmarks without strategy that performs well over a wide range of benchmarks without
suffering from underperformance in less common situations (which is what suffering from (too much) underperformance in less common situations.
the second half of our benchmark set tests for).
We show here only the results on an AMD EPYC system (Apr 2019) -- for As always, interpret these results with care since some benchmarks test synthetic
specific details and further benchmarks we refer to the [technical report](https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action). or uncommon situations that may never apply to your workloads. For example, most
allocators do not do well on `xmalloc-testN` but that includes the best
industrial allocators like _jemalloc_ and _tcmalloc_ that are used in some of
the world's largest systems (like Chrome or FreeBSD).
The benchmark suite is scripted and available separately We show here only an overview -- for
more specific details and further benchmarks we refer to the
[technical report](https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action).
The benchmark suite is automated and available separately
as [mimalloc-bench](https://github.com/daanx/mimalloc-bench). as [mimalloc-bench](https://github.com/daanx/mimalloc-bench).
## Benchmark Results ## Benchmark Results on 36-core Intel
Testing on a big Amazon EC2 instance ([r5a.4xlarge](https://aws.amazon.com/ec2/instance-types/)) Testing on a big Amazon EC2 compute instance
consisting of a 16-core AMD EPYC 7000 at 2.5GHz ([c5.18xlarge](https://aws.amazon.com/ec2/instance-types/#Compute_Optimized))
with 128GB ECC memory, running Ubuntu 18.04.1 with LibC 2.27 and GCC 7.3.0. consisting of a 72 processor Intel Xeon at 3GHz
The measured allocators are _mimalloc_ (mi), with 144GiB ECC memory, running Ubuntu 18.04.1 with LibC 2.27 and GCC 7.4.0.
Google's [_tcmalloc_](https://github.com/gperftools/gperftools) (tc) used in Chrome, The measured allocators are _mimalloc_ (xmi, tag:v1.4.0, page reset enabled)
[_jemalloc_](https://github.com/jemalloc/jemalloc) (je) by Jason Evans used in Firefox and FreeBSD, and its secure build as _smi_,
[_snmalloc_](https://github.com/microsoft/snmalloc) (sn) by Liétar et al. \[8], [_rpmalloc_](https://github.com/rampantpixels/rpmalloc) (rp) by Mattias Jansson at Rampant Pixels, Google's [_tcmalloc_](https://github.com/gperftools/gperftools) (tc, tag:gperftools-2.7) used in Chrome,
[_Hoard_](https://github.com/emeryberger/Hoard) by Emery Berger \[1], Facebook's [_jemalloc_](https://github.com/jemalloc/jemalloc) (je, tag:5.2.1) by Jason Evans used in Firefox and FreeBSD,
the system allocator (glibc) (based on _PtMalloc2_), and the Intel thread the Intel thread building blocks [allocator](https://github.com/intel/tbb) (tbb, tag:2020),
building blocks [allocator](https://github.com/intel/tbb) (tbb). [rpmalloc](https://github.com/mjansson/rpmalloc) (rp,tag:1.4.0) by Mattias Jansson,
the original scalable [_Hoard_](https://github.com/emeryberger/Hoard) (tag:3.13) allocator by Emery Berger \[1],
the memory compacting [_Mesh_](https://github.com/plasma-umass/Mesh) (git:51222e7) allocator by
Bobby Powers _et al_ \[8],
and finally the default system allocator (glibc, 2.7.0) (based on _PtMalloc2_).
![bench-r5a-1](doc/bench-r5a-1.svg) <img width="90%" src="doc/bench-c5-18xlarge-2020-01-20-a.svg"/>
![bench-r5a-2](doc/bench-r5a-2.svg) <img width="90%" src="doc/bench-c5-18xlarge-2020-01-20-b.svg"/>
Memory usage: Any benchmarks ending in `N` run on all processors in parallel.
Results are averaged over 10 runs and reported relative
to mimalloc (where 1.2 means it took 1.2&times; longer to run).
The legend also contains the _overall relative score_ between the
allocators where 100 points is the maximum if an allocator is fastest on
all benchmarks.
![bench-r5a-rss-1](doc/bench-r5a-rss-1.svg) The single threaded _cfrac_ benchmark by Dave Barrett is an implementation of
![bench-r5a-rss-1](doc/bench-r5a-rss-2.svg) continued fraction factorization which uses many small short-lived allocations.
All allocators do well on such common usage, where _mimalloc_ is just a tad
faster than _tcmalloc_ and
_jemalloc_.
(note: the _xmalloc-testN_ memory usage should be disregarded as it The _leanN_ program is interesting as a large realistic and
allocates more the faster the program runs). concurrent workload of the [Lean](https://github.com/leanprover/lean)
theorem prover compiling its own standard library, and there is a 7%
In the first five benchmarks we can see _mimalloc_ outperforms the other speedup over _tcmalloc_. This is
allocators moderately, but we also see that all these modern allocators
perform well -- the times of large performance differences in regular
workloads are over :-).
In _cfrac_ and _espresso_, _mimalloc_ is a tad faster than _tcmalloc_ and
_jemalloc_, but a solid 10\% faster than all other allocators on
_espresso_. The _tbb_ allocator does not do so well here and lags more than
20\% behind _mimalloc_. The _cfrac_ and _espresso_ programs do not use much
memory (~1.5MB) so it does not matter too much, but still _mimalloc_ uses
about half the resident memory of _tcmalloc_.
The _leanN_ program is most interesting as a large realistic and
concurrent workload of the [Lean](https://github.com/leanprover/lean) theorem prover
compiling its own standard library, and there is a 8% speedup over _tcmalloc_. This is
quite significant: if Lean spends 20% of its time in the quite significant: if Lean spends 20% of its time in the
allocator that means that _mimalloc_ is 1.3&times; faster than _tcmalloc_ allocator that means that _mimalloc_ is 1.3&times; faster than _tcmalloc_
here. (This is surprising as that is not measured in a pure here. (This is surprising as that is not measured in a pure
@ -355,19 +397,23 @@ outsized improvement here because _mimalloc_ has better locality in
the allocation which improves performance for the *other* computations the allocation which improves performance for the *other* computations
in a program as well). in a program as well).
The _redis_ benchmark shows more differences between the allocators where The single threaded _redis_ benchmark again show that most allocators do well on such workloads where _tcmalloc_
_mimalloc_ is 14\% faster than _jemalloc_. On this benchmark _tbb_ (and _Hoard_) do did best this time.
not do well and are over 40\% slower.
The _larson_ server workload allocates and frees objects between The _larsonN_ server benchmark by Larson and Krishnan \[2] allocates and frees between threads. They observed this
many threads. Larson and Krishnan \[2] observe this behavior (which they call _bleeding_) in actual server applications, and the benchmark simulates this.
behavior (which they call _bleeding_) in actual server applications, and the Here, _mimalloc_ is quite a bit faster than _tcmalloc_ and _jemalloc_ probably due to the object migration between different threads.
benchmark simulates this.
Here, _mimalloc_ is more than 2.5&times; faster than _tcmalloc_ and _jemalloc_
due to the object migration between different threads. This is a difficult
benchmark for other allocators too where _mimalloc_ is still 48% faster than the next
fastest (_snmalloc_).
The _mstressN_ workload performs many allocations and re-allocations,
and migrates objects between threads (as in _larsonN_). However, it also
creates and destroys the _N_ worker threads a few times keeping some objects
alive beyond the life time of the allocating thread. We observed this
behavior in many larger server applications.
The [_rptestN_](https://github.com/mjansson/rpmalloc-benchmark) benchmark
by Mattias Jansson is a allocator test originally designed
for _rpmalloc_, and tries to simulate realistic allocation patterns over
multiple threads. Here the differences between allocators become more apparent.
The second benchmark set tests specific aspects of the allocators and The second benchmark set tests specific aspects of the allocators and
shows even more extreme differences between them. shows even more extreme differences between them.
@ -376,46 +422,62 @@ The _alloc-test_, by
[OLogN Technologies AG](http://ithare.com/testing-memory-allocators-ptmalloc2-tcmalloc-hoard-jemalloc-while-trying-to-simulate-real-world-loads/), is a very allocation intensive benchmark doing millions of [OLogN Technologies AG](http://ithare.com/testing-memory-allocators-ptmalloc2-tcmalloc-hoard-jemalloc-while-trying-to-simulate-real-world-loads/), is a very allocation intensive benchmark doing millions of
allocations in various size classes. The test is scaled such that when an allocations in various size classes. The test is scaled such that when an
allocator performs almost identically on _alloc-test1_ as _alloc-testN_ it allocator performs almost identically on _alloc-test1_ as _alloc-testN_ it
means that it scales linearly. Here, _tcmalloc_, _snmalloc_, and means that it scales linearly. Here, _tcmalloc_, and
_Hoard_ seem to scale less well and do more than 10% worse on the _Hoard_ seem to scale less well and do more than 10% worse on the multi-core version. Even the best industrial
multi-core version. Even the best allocators (_tcmalloc_ and _jemalloc_) are allocators (_tcmalloc_, _jemalloc_, and _tbb_) are more than 10% slower as _mimalloc_ here.
more than 10% slower as _mimalloc_ here.
The _sh6bench_ and _sh8bench_ benchmarks are The _sh6bench_ and _sh8bench_ benchmarks are
developed by [MicroQuill](http://www.microquill.com/) as part of SmartHeap. developed by [MicroQuill](http://www.microquill.com/) as part of SmartHeap.
In _sh6bench_ _mimalloc_ does much In _sh6bench_ _mimalloc_ does much
better than the others (more than 2&times; faster than _jemalloc_). better than the others (more than 1.5&times; faster than _jemalloc_).
We cannot explain this well but believe it is We cannot explain this well but believe it is
caused in part by the "reverse" free-ing pattern in _sh6bench_. caused in part by the "reverse" free-ing pattern in _sh6bench_.
Again in _sh8bench_ the _mimalloc_ allocator handles object migration The _sh8bench_ is a variation with object migration
between threads much better and is over 36% faster than the next best between threads; whereas _tcmalloc_ did well on _sh6bench_, the addition of object migration causes it to be 10&times; slower than before.
allocator, _snmalloc_. Whereas _tcmalloc_ did well on _sh6bench_, the
addition of object migration caused it to be almost 3 times slower
than before.
The _xmalloc-testN_ benchmark by Lever and Boreham \[5] and Christian Eder, The _xmalloc-testN_ benchmark by Lever and Boreham \[5] and Christian Eder, simulates an asymmetric workload where
simulates an asymmetric workload where some threads only allocate, and others only free -- they observed this pattern in
some threads only allocate, and others only free. The _snmalloc_ larger server applications. Here we see that
allocator was especially developed to handle this case well as it
often occurs in concurrent message passing systems (like the [Pony] language
for which _snmalloc_ was initially developed). Here we see that
the _mimalloc_ technique of having non-contended sharded thread free the _mimalloc_ technique of having non-contended sharded thread free
lists pays off as it even outperforms _snmalloc_ here. lists pays off as it outperforms others by a very large margin. Only _rpmalloc_ and _tbb_ also scale well on this benchmark.
Only _jemalloc_ also handles this reasonably well, while the
others underperform by a large margin.
The _cache-scratch_ benchmark by Emery Berger \[1], and introduced with the Hoard The _cache-scratch_ benchmark by Emery Berger \[1], and introduced with
allocator to test for _passive-false_ sharing of cache lines. With a single thread they all the Hoard allocator to test for _passive-false_ sharing of cache lines.
With a single thread they all
perform the same, but when running with multiple threads the potential allocator perform the same, but when running with multiple threads the potential allocator
induced false sharing of the cache lines causes large run-time induced false sharing of the cache lines can cause large run-time differences.
differences, where _mimalloc_ is more than 18&times; faster than _jemalloc_ and Crundal \[6] describes in detail why the false cache line sharing occurs in the _tcmalloc_ design, and also discusses how this
_tcmalloc_! Crundal \[6] describes in detail why the false cache line
sharing occurs in the _tcmalloc_ design, and also discusses how this
can be avoided with some small implementation changes. can be avoided with some small implementation changes.
Only _snmalloc_ and _tbb_ also avoid the Only the _tbb_, _rpmalloc_ and _mesh_ allocators also avoid the
cache line sharing like _mimalloc_. Kukanov and Voss \[7] describe in detail cache line sharing completely, while _Hoard_ and _glibc_ seem to mitigate
the effects. Kukanov and Voss \[7] describe in detail
how the design of _tbb_ avoids the false cache line sharing. how the design of _tbb_ avoids the false cache line sharing.
## On 24-core AMD Epyc
For completeness, here are the results on a
[r5a.12xlarge](https://aws.amazon.com/ec2/instance-types/#Memory_Optimized) instance
having a 48 processor AMD Epyc 7000 at 2.5GHz with 384GiB of memory.
The results are similar to the Intel results but it is interesting to
see the differences in the _larsonN_, _mstressN_, and _xmalloc-testN_ benchmarks.
<img width="90%" src="doc/bench-r5a-12xlarge-2020-01-16-a.svg"/>
<img width="90%" src="doc/bench-r5a-12xlarge-2020-01-16-b.svg"/>
## Peak Working Set
The following figure shows the peak working set (rss) of the allocators
on the benchmarks (on the c5.18xlarge instance).
<img width="90%" src="doc/bench-c5-18xlarge-2020-01-20-rss-a.svg"/>
<img width="90%" src="doc/bench-c5-18xlarge-2020-01-20-rss-b.svg"/>
Note that the _xmalloc-testN_ memory usage should be disregarded as it
allocates more the faster the program runs. Similarly, memory usage of
_mstressN_, _rptestN_ and _sh8bench_ can vary depending on scheduling and
speed. Nevertheless, even though _mimalloc_ is fast on these benchmarks we
believe the memory usage is too high and hope to improve.
# References # References
@ -425,14 +487,12 @@ how the design of _tbb_ avoids the false cache line sharing.
the Ninth International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS-IX). Cambridge, MA, November 2000. the Ninth International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS-IX). Cambridge, MA, November 2000.
[pdf](http://www.cs.utexas.edu/users/mckinley/papers/asplos-2000.pdf) [pdf](http://www.cs.utexas.edu/users/mckinley/papers/asplos-2000.pdf)
- \[2] P. Larson and M. Krishnan. _Memory allocation for long-running server applications_.
- \[2] P. Larson and M. Krishnan. _Memory allocation for long-running server applications_. In ISMM, Vancouver, B.C., Canada, 1998. In ISMM, Vancouver, B.C., Canada, 1998. [pdf](http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.45.1947&rep=rep1&type=pdf)
[pdf](http://citeseer.ist.psu.edu/viewdoc/download;jsessionid=5F0BFB4F57832AEB6C11BF8257271088?doi=10.1.1.45.1947&rep=rep1&type=pdf)
- \[3] D. Grunwald, B. Zorn, and R. Henderson. - \[3] D. Grunwald, B. Zorn, and R. Henderson.
_Improving the cache locality of memory allocation_. In R. Cartwright, editor, _Improving the cache locality of memory allocation_. In R. Cartwright, editor,
Proceedings of the Conference on Programming Language Design and Implementation, pages 177186, New York, NY, USA, June 1993. Proceedings of the Conference on Programming Language Design and Implementation, pages 177186, New York, NY, USA, June 1993. [pdf](http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.43.6621&rep=rep1&type=pdf)
[pdf](http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.43.6621&rep=rep1&type=pdf)
- \[4] J. Barnes and P. Hut. _A hierarchical O(n*log(n)) force-calculation algorithm_. Nature, 324:446-449, 1986. - \[4] J. Barnes and P. Hut. _A hierarchical O(n*log(n)) force-calculation algorithm_. Nature, 324:446-449, 1986.
@ -440,17 +500,22 @@ how the design of _tbb_ avoids the false cache line sharing.
In USENIX Annual Technical Conference, Freenix Session. San Diego, CA. Jun. 2000. In USENIX Annual Technical Conference, Freenix Session. San Diego, CA. Jun. 2000.
Available at <https://github.com/kuszmaul/SuperMalloc/tree/master/tests> Available at <https://github.com/kuszmaul/SuperMalloc/tree/master/tests>
- \[6] Timothy Crundal. _Reducing Active-False Sharing in TCMalloc._ - \[6] Timothy Crundal. _Reducing Active-False Sharing in TCMalloc_. 2016. CS16S1 project at the Australian National University. [pdf](http://courses.cecs.anu.edu.au/courses/CSPROJECTS/16S1/Reports/Timothy_Crundal_Report.pdf)
2016. <http://courses.cecs.anu.edu.au/courses/CSPROJECTS/16S1/Reports/Timothy_Crundal_Report.pdf>. CS16S1 project at the Australian National University.
- \[7] Alexey Kukanov, and Michael J Voss. - \[7] Alexey Kukanov, and Michael J Voss.
_The Foundations for Scalable Multi-Core Software in Intel Threading Building Blocks._ _The Foundations for Scalable Multi-Core Software in Intel Threading Building Blocks._
Intel Technology Journal 11 (4). 2007 Intel Technology Journal 11 (4). 2007
- \[8] Paul Liétar, Theodore Butler, Sylvan Clebsch, Sophia Drossopoulou, Juliana Franco, Matthew J Parkinson, - \[8] Bobby Powers, David Tench, Emery D. Berger, and Andrew McGregor.
_Mesh: Compacting Memory Management for C/C++_
In Proceedings of the 40th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI'19), June 2019, pages 333-346.
<!--
- \[9] Paul Liétar, Theodore Butler, Sylvan Clebsch, Sophia Drossopoulou, Juliana Franco, Matthew J Parkinson,
Alex Shamis, Christoph M Wintersteiger, and David Chisnall. Alex Shamis, Christoph M Wintersteiger, and David Chisnall.
_Snmalloc: A Message Passing Allocator._ _Snmalloc: A Message Passing Allocator._
In Proceedings of the 2019 ACM SIGPLAN International Symposium on Memory Management, 122135. ACM. 2019. In Proceedings of the 2019 ACM SIGPLAN International Symposium on Memory Management, 122135. ACM. 2019.
-->
# Contributing # Contributing

View file

@ -18,20 +18,22 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t
// note: we don't require `size > offset`, we just guarantee that // note: we don't require `size > offset`, we just guarantee that
// the address at offset is aligned regardless of the allocated size. // the address at offset is aligned regardless of the allocated size.
mi_assert(alignment > 0 && alignment % sizeof(void*) == 0); mi_assert(alignment > 0 && alignment % sizeof(void*) == 0);
if (mi_unlikely(size > PTRDIFF_MAX)) return NULL; // we don't allocate more than PTRDIFF_MAX (see <https://sourceware.org/ml/libc-announce/2019/msg00001.html>) if (mi_unlikely(size > PTRDIFF_MAX)) return NULL; // we don't allocate more than PTRDIFF_MAX (see <https://sourceware.org/ml/libc-announce/2019/msg00001.html>)
if (mi_unlikely(alignment==0 || !_mi_is_power_of_two(alignment))) return NULL; // require power-of-two (see <https://en.cppreference.com/w/c/memory/aligned_alloc>) if (mi_unlikely(alignment==0 || !_mi_is_power_of_two(alignment))) return NULL; // require power-of-two (see <https://en.cppreference.com/w/c/memory/aligned_alloc>)
const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)` const uintptr_t align_mask = alignment-1; // for any x, `(x & align_mask) == (x % alignment)`
// try if there is a small block available with just the right alignment // try if there is a small block available with just the right alignment
if (mi_likely(size <= MI_SMALL_SIZE_MAX)) { const size_t padsize = size + MI_PADDING_SIZE;
mi_page_t* page = _mi_heap_get_free_small_page(heap,size); if (mi_likely(padsize <= MI_SMALL_SIZE_MAX)) {
mi_page_t* page = _mi_heap_get_free_small_page(heap,padsize);
const bool is_aligned = (((uintptr_t)page->free+offset) & align_mask)==0; const bool is_aligned = (((uintptr_t)page->free+offset) & align_mask)==0;
if (mi_likely(page->free != NULL && is_aligned)) if (mi_likely(page->free != NULL && is_aligned))
{ {
#if MI_STAT>1 #if MI_STAT>1
mi_heap_stat_increase( heap, malloc, size); mi_heap_stat_increase( heap, malloc, size);
#endif #endif
void* p = _mi_page_malloc(heap,page,size); // TODO: inline _mi_page_malloc void* p = _mi_page_malloc(heap,page,padsize); // TODO: inline _mi_page_malloc
mi_assert_internal(p != NULL); mi_assert_internal(p != NULL);
mi_assert_internal(((uintptr_t)p + offset) % alignment == 0); mi_assert_internal(((uintptr_t)p + offset) % alignment == 0);
if (zero) _mi_block_zero_init(page,p,size); if (zero) _mi_block_zero_init(page,p,size);
@ -40,7 +42,7 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t
} }
// use regular allocation if it is guaranteed to fit the alignment constraints // use regular allocation if it is guaranteed to fit the alignment constraints
if (offset==0 && alignment<=size && size<=MI_MEDIUM_OBJ_SIZE_MAX && (size&align_mask)==0) { if (offset==0 && alignment<=padsize && padsize<=MI_MEDIUM_OBJ_SIZE_MAX && (padsize&align_mask)==0) {
void* p = _mi_heap_malloc_zero(heap, size, zero); void* p = _mi_heap_malloc_zero(heap, size, zero);
mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0); mi_assert_internal(p == NULL || ((uintptr_t)p % alignment) == 0);
return p; return p;
@ -61,53 +63,53 @@ static void* mi_heap_malloc_zero_aligned_at(mi_heap_t* const heap, const size_t
} }
void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, false); return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, false);
} }
void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept {
return mi_heap_malloc_aligned_at(heap, size, alignment, 0); return mi_heap_malloc_aligned_at(heap, size, alignment, 0);
} }
void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { mi_decl_restrict void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, true); return mi_heap_malloc_zero_aligned_at(heap, size, alignment, offset, true);
} }
void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { mi_decl_restrict void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept {
return mi_heap_zalloc_aligned_at(heap, size, alignment, 0); return mi_heap_zalloc_aligned_at(heap, size, alignment, 0);
} }
void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { mi_decl_restrict void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
size_t total; size_t total;
if (mi_mul_overflow(count, size, &total)) return NULL; if (mi_count_size_overflow(count, size, &total)) return NULL;
return mi_heap_zalloc_aligned_at(heap, total, alignment, offset); return mi_heap_zalloc_aligned_at(heap, total, alignment, offset);
} }
void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept { mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept {
return mi_heap_calloc_aligned_at(heap,count,size,alignment,0); return mi_heap_calloc_aligned_at(heap,count,size,alignment,0);
} }
void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { mi_decl_restrict void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
return mi_heap_malloc_aligned_at(mi_get_default_heap(), size, alignment, offset); return mi_heap_malloc_aligned_at(mi_get_default_heap(), size, alignment, offset);
} }
void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { mi_decl_restrict void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept {
return mi_heap_malloc_aligned(mi_get_default_heap(), size, alignment); return mi_heap_malloc_aligned(mi_get_default_heap(), size, alignment);
} }
void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { mi_decl_restrict void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
return mi_heap_zalloc_aligned_at(mi_get_default_heap(), size, alignment, offset); return mi_heap_zalloc_aligned_at(mi_get_default_heap(), size, alignment, offset);
} }
void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { mi_decl_restrict void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept {
return mi_heap_zalloc_aligned(mi_get_default_heap(), size, alignment); return mi_heap_zalloc_aligned(mi_get_default_heap(), size, alignment);
} }
void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { mi_decl_restrict void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
return mi_heap_calloc_aligned_at(mi_get_default_heap(), count, size, alignment, offset); return mi_heap_calloc_aligned_at(mi_get_default_heap(), count, size, alignment, offset);
} }
void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept { mi_decl_restrict void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept {
return mi_heap_calloc_aligned(mi_get_default_heap(), count, size, alignment); return mi_heap_calloc_aligned(mi_get_default_heap(), count, size, alignment);
} }
@ -126,7 +128,7 @@ static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t ne
if (newp != NULL) { if (newp != NULL) {
if (zero && newsize > size) { if (zero && newsize > size) {
const mi_page_t* page = _mi_ptr_page(newp); const mi_page_t* page = _mi_ptr_page(newp);
if (page->flags.is_zero) { if (page->is_zero) {
// already zero initialized // already zero initialized
mi_assert_expensive(mi_mem_is_zero(newp,newsize)); mi_assert_expensive(mi_mem_is_zero(newp,newsize));
} }
@ -168,13 +170,13 @@ void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t
void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept {
size_t total; size_t total;
if (mi_mul_overflow(newcount, size, &total)) return NULL; if (mi_count_size_overflow(newcount, size, &total)) return NULL;
return mi_heap_rezalloc_aligned_at(heap, p, total, alignment, offset); return mi_heap_rezalloc_aligned_at(heap, p, total, alignment, offset);
} }
void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept {
size_t total; size_t total;
if (mi_mul_overflow(newcount, size, &total)) return NULL; if (mi_count_size_overflow(newcount, size, &total)) return NULL;
return mi_heap_rezalloc_aligned(heap, p, total, alignment); return mi_heap_rezalloc_aligned(heap, p, total, alignment);
} }

View file

@ -17,6 +17,12 @@ terms of the MIT license. A copy of the license can be found in the file
/* ------------------------------------------------------ /* ------------------------------------------------------
Override system malloc on macOS Override system malloc on macOS
This is done through the malloc zone interface. This is done through the malloc zone interface.
It seems we also need to interpose (see `alloc-override.c`)
or otherwise we get zone errors as there are usually
already allocations done by the time we take over the
zone. Unfortunately, that means we need to replace
the `free` with a checked free (`cfree`) impacting
performance.
------------------------------------------------------ */ ------------------------------------------------------ */
#include <AvailabilityMacros.h> #include <AvailabilityMacros.h>
@ -35,34 +41,42 @@ 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);
return 0; // as we cannot guarantee that `p` comes from us, just return 0 return 0; // as we cannot guarantee that `p` comes from us, just return 0
} }
static void* zone_malloc(malloc_zone_t* zone, size_t size) { static void* zone_malloc(malloc_zone_t* zone, size_t size) {
UNUSED(zone);
return mi_malloc(size); return mi_malloc(size);
} }
static void* zone_calloc(malloc_zone_t* zone, size_t count, size_t size) { static void* zone_calloc(malloc_zone_t* zone, size_t count, size_t size) {
UNUSED(zone);
return mi_calloc(count, size); return mi_calloc(count, size);
} }
static void* zone_valloc(malloc_zone_t* zone, size_t size) { static void* zone_valloc(malloc_zone_t* zone, size_t size) {
UNUSED(zone);
return mi_malloc_aligned(size, _mi_os_page_size()); return mi_malloc_aligned(size, _mi_os_page_size());
} }
static void zone_free(malloc_zone_t* zone, void* p) { static void zone_free(malloc_zone_t* zone, void* p) {
UNUSED(zone);
return mi_free(p); return mi_free(p);
} }
static void* zone_realloc(malloc_zone_t* zone, void* p, size_t newsize) { static void* zone_realloc(malloc_zone_t* zone, void* p, size_t newsize) {
UNUSED(zone);
return mi_realloc(p, newsize); return mi_realloc(p, newsize);
} }
static void* zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size) { static void* zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size) {
UNUSED(zone);
return mi_malloc_aligned(size,alignment); return mi_malloc_aligned(size,alignment);
} }
static void zone_destroy(malloc_zone_t* zone) { static void zone_destroy(malloc_zone_t* zone) {
UNUSED(zone);
// todo: ignore for now? // todo: ignore for now?
} }
@ -83,11 +97,13 @@ static void zone_batch_free(malloc_zone_t* zone, void** ps, unsigned count) {
} }
static size_t zone_pressure_relief(malloc_zone_t* zone, size_t size) { static size_t zone_pressure_relief(malloc_zone_t* zone, size_t size) {
UNUSED(zone); UNUSED(size);
mi_collect(false); mi_collect(false);
return 0; return 0;
} }
static void zone_free_definite_size(malloc_zone_t* zone, void* p, size_t size) { static void zone_free_definite_size(malloc_zone_t* zone, void* p, size_t size) {
UNUSED(size);
zone_free(zone,p); zone_free(zone,p);
} }
@ -102,34 +118,43 @@ static kern_return_t intro_enumerator(task_t task, void* p,
vm_range_recorder_t recorder) vm_range_recorder_t recorder)
{ {
// todo: enumerate all memory // todo: enumerate all memory
UNUSED(task); UNUSED(p); UNUSED(type_mask); UNUSED(zone_address);
UNUSED(reader); UNUSED(recorder);
return KERN_SUCCESS; return KERN_SUCCESS;
} }
static size_t intro_good_size(malloc_zone_t* zone, size_t size) { static size_t intro_good_size(malloc_zone_t* zone, size_t size) {
UNUSED(zone);
return mi_good_size(size); return mi_good_size(size);
} }
static boolean_t intro_check(malloc_zone_t* zone) { static boolean_t intro_check(malloc_zone_t* zone) {
UNUSED(zone);
return true; return true;
} }
static void intro_print(malloc_zone_t* zone, boolean_t verbose) { static void intro_print(malloc_zone_t* zone, boolean_t verbose) {
UNUSED(zone); UNUSED(verbose);
mi_stats_print(NULL); mi_stats_print(NULL);
} }
static void intro_log(malloc_zone_t* zone, void* p) { static void intro_log(malloc_zone_t* zone, void* p) {
UNUSED(zone); UNUSED(p);
// todo? // todo?
} }
static void intro_force_lock(malloc_zone_t* zone) { static void intro_force_lock(malloc_zone_t* zone) {
UNUSED(zone);
// todo? // todo?
} }
static void intro_force_unlock(malloc_zone_t* zone) { static void intro_force_unlock(malloc_zone_t* zone) {
UNUSED(zone);
// todo? // todo?
} }
static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) { static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) {
UNUSED(zone);
// todo... // todo...
stats->blocks_in_use = 0; stats->blocks_in_use = 0;
stats->size_in_use = 0; stats->size_in_use = 0;
@ -138,6 +163,7 @@ static void intro_statistics(malloc_zone_t* zone, malloc_statistics_t* stats) {
} }
static boolean_t intro_zone_locked(malloc_zone_t* zone) { static boolean_t intro_zone_locked(malloc_zone_t* zone) {
UNUSED(zone);
return false; return false;
} }
@ -161,7 +187,6 @@ static malloc_zone_t* mi_get_default_zone()
} }
} }
static void __attribute__((constructor)) _mi_macos_override_malloc() static void __attribute__((constructor)) _mi_macos_override_malloc()
{ {
static malloc_introspection_t intro; static malloc_introspection_t intro;
@ -201,6 +226,7 @@ static void __attribute__((constructor)) _mi_macos_override_malloc()
zone.free_definite_size = &zone_free_definite_size; zone.free_definite_size = &zone_free_definite_size;
zone.pressure_relief = &zone_pressure_relief; zone.pressure_relief = &zone_pressure_relief;
intro.zone_locked = &intro_zone_locked; intro.zone_locked = &intro_zone_locked;
intro.statistics = &intro_statistics;
// force the purgeable zone to exist to avoid strange bugs // force the purgeable zone to exist to avoid strange bugs
if (malloc_default_purgeable_zone) { if (malloc_default_purgeable_zone) {
@ -225,6 +251,7 @@ static void __attribute__((constructor)) _mi_macos_override_malloc()
malloc_zone_unregister(purgeable_zone); malloc_zone_unregister(purgeable_zone);
malloc_zone_register(purgeable_zone); malloc_zone_register(purgeable_zone);
} }
} }
#endif // MI_MALLOC_OVERRIDE #endif // MI_MALLOC_OVERRIDE

View file

@ -1,715 +0,0 @@
/* ----------------------------------------------------------------------------
Copyright (c) 2018, Microsoft Research, Daan Leijen
This is free software; you can redistribute it and/or modify it under the
terms of the MIT license. A copy of the license can be found in the file
"LICENSE" at the root of this distribution.
-----------------------------------------------------------------------------*/
#include "mimalloc.h"
#include "mimalloc-internal.h"
#if !defined(_WIN32)
#error "this file should only be included on Windows"
#endif
#include <windows.h>
#include <psapi.h>
#include <stdlib.h> // getenv
#include <stdio.h> // _setmaxstdio
#include <string.h> // strstr
/*
To override the C runtime `malloc` on Windows we need to patch the allocation
functions at runtime initialization. Unfortunately we can never patch before the
runtime initializes itself, because as soon as we call `GetProcAddress` on the
runtime module (a DLL or EXE in Windows speak), it will first load and initialize
(by the OS calling `DllMain` on it).
This means that some things might be already allocated by the C runtime itself
(and possibly other DLL's) before we get to resolve runtime adresses. This is
no problem if everyone unwinds in order: when we unload, we unpatch and restore
the original crt `free` routines and crt malloc'd memory is freed correctly.
But things go wrong if such early CRT alloc'd memory is freed or re-allocated
_after_ we patch, but _before_ we unload (and unpatch), or if any memory allocated
by us is freed after we unpatched.
There are two tricky situations to deal with:
1. The Thread Local Storage (TLS): when the main thread stops it will call registered
callbacks on TLS entries (allocated by `FlsAlloc`). This is done by the OS
before any DLL's are unloaded. Unfortunately, the C runtime registers such
TLS entries with CRT allocated memory which is freed in the callback.
2. Inside the CRT:
a. Some variables might get initialized by patched allocated
blocks but freed during CRT unloading after we unpatched
(like temporary file buffers).
b. Some blocks are allocated at CRT and freed by the CRT (like the
environment storage).
c. And some blocks are allocated by the CRT and then reallocated
while patched, and finally freed after unpatching! This
happens with the `atexit` functions for example to grow the array
of registered functions.
In principle situation 2 is hopeless: since we cannot patch before CRT initialization,
we can never be sure how to free or reallocate a pointer during CRT unloading.
However, in practice there is a good solution: when terminating, we just patch
the reallocation and free routines to no-ops -- we are winding down anyway! This leaves
just the reallocation problm of CRT alloc'd memory once we are patched. Here, a study of the
CRT reveals that there seem to be just three such situations:
1. When registering `atexit` routines (to grow the exit function table),
2. When calling `_setmaxstdio` (to grow the file handle table),
3. and `_popen`/`_wpopen` (to grow handle pairs). These turn out not to be
a problem as these are NULL initialized.
We fix these by providing wrappers:
1. We first register a _global_ `atexit` routine ourselves (`mi_patches_at_exit`) before patching,
and then patch the `_crt_atexit` function to implement our own global exit list (and the
same for `_crt_at_quick_exit`). All module local lists are no problem since they are always fully
(un)patched from initialization to end. We can register in the global list by dynamically
getting the global `_crt_atexit` entry from `ucrtbase.dll`.
2. The `_setmaxstdio` is _detoured_: we patch it by a stub that unpatches first,
calls the original routine and repatches again.
That leaves us to reliably shutdown and enter "termination mode":
1. Using our trick to get the global exit list entry point, we register an exit function `mi_patches_atexit`
that first executes all our home brew list of exit functions, and then enters a _termination_
phase that patches realloc/free variants with no-ops. Patching later again with special no-ops for
`free` also improves efficiency during the program run since no flags need to be checked.
2. That is not quite good enough yet since after executing exit routines after us on the
global exit list (registered by the CRT),
the OS starts to unwind the TLS callbacks and we would like to run callbacks registered after loading
our DLL to be done in patched mode. So, we also allocate a TLS entry when our DLL is loaded and when its
callback is called, we re-enable the original patches again. Since TLS is destroyed in FIFO order
this runs any callbacks in later DLL's in patched mode.
3. Finally the DLL's get unloaded by the OS in order (still patched) until our DLL gets unloaded
and then we start a termination phase again, and patch realloc/free with no-ops for good this time.
*/
static int __cdecl mi_setmaxstdio(int newmax);
// ------------------------------------------------------
// Microsoft allocation extensions
// ------------------------------------------------------
typedef size_t mi_nothrow_t;
static void mi_free_nothrow(void* p, mi_nothrow_t tag) {
UNUSED(tag);
mi_free(p);
}
// Versions of `free`, `realloc`, `recalloc`, `expand` and `msize`
// that are used during termination and are no-ops.
static void mi_free_term(void* p) {
UNUSED(p);
}
static void mi_free_size_term(void* p, size_t size) {
UNUSED(size);
UNUSED(p);
}
static void mi_free_nothrow_term(void* p, mi_nothrow_t tag) {
UNUSED(tag);
UNUSED(p);
}
static void* mi_realloc_term(void* p, size_t newsize) {
UNUSED(p); UNUSED(newsize);
return NULL;
}
static void* mi__recalloc_term(void* p, size_t newcount, size_t newsize) {
UNUSED(p); UNUSED(newcount); UNUSED(newsize);
return NULL;
}
static void* mi__expand_term(void* p, size_t newsize) {
UNUSED(p); UNUSED(newsize);
return NULL;
}
static size_t mi__msize_term(void* p) {
UNUSED(p);
return 0;
}
static void* mi__malloc_dbg(size_t size, int block_type, const char* fname, int line) {
UNUSED(block_type); UNUSED(fname); UNUSED(line);
return _malloc_base(size);
}
static void* mi__calloc_dbg(size_t count, size_t size, int block_type, const char* fname, int line) {
UNUSED(block_type); UNUSED(fname); UNUSED(line);
return _calloc_base(count, size);
}
static void* mi__realloc_dbg(void* p, size_t size, int block_type, const char* fname, int line) {
UNUSED(block_type); UNUSED(fname); UNUSED(line);
return _realloc_base(p, size);
}
static void mi__free_dbg(void* p, int block_type) {
UNUSED(block_type);
_free_base(p);
}
// the `recalloc`,`expand`, and `msize` don't have base versions and thus need a separate term version
static void* mi__recalloc_dbg(void* p, size_t count, size_t size, int block_type, const char* fname, int line) {
UNUSED(block_type); UNUSED(fname); UNUSED(line);
return mi_recalloc(p, count, size);
}
static void* mi__expand_dbg(void* p, size_t size, int block_type, const char* fname, int line) {
UNUSED(block_type); UNUSED(fname); UNUSED(line);
return mi__expand(p, size);
}
static size_t mi__msize_dbg(void* p, int block_type) {
UNUSED(block_type);
return mi_usable_size(p);
}
static void* mi__recalloc_dbg_term(void* p, size_t count, size_t size, int block_type, const char* fname, int line) {
UNUSED(block_type); UNUSED(fname); UNUSED(line);
return mi__recalloc_term(p, count, size);
}
static void* mi__expand_dbg_term(void* p, size_t size, int block_type, const char* fname, int line) {
UNUSED(block_type); UNUSED(fname); UNUSED(line);
return mi__expand_term(p, size);
}
static size_t mi__msize_dbg_term(void* p, int block_type) {
UNUSED(block_type);
return mi__msize_term(p);
}
// ------------------------------------------------------
// implement our own global atexit handler
// ------------------------------------------------------
typedef void (cbfun_t)(void);
typedef int (atexit_fun_t)(cbfun_t* fn);
typedef uintptr_t encoded_t;
typedef struct exit_list_s {
encoded_t functions; // encoded pointer to array of encoded function pointers
size_t count;
size_t capacity;
} exit_list_t;
#define MI_EXIT_INC (64)
static exit_list_t atexit_list = { 0, 0, 0 };
static exit_list_t at_quick_exit_list = { 0, 0, 0 };
static CRITICAL_SECTION atexit_lock;
// encode/decode function pointers with a random canary for security
static encoded_t canary;
static inline void *decode(encoded_t x) {
return (void*)(x^canary);
}
static inline encoded_t encode(void* p) {
return ((uintptr_t)p ^ canary);
}
static void init_canary()
{
canary = _mi_random_init(0);
atexit_list.functions = at_quick_exit_list.functions = encode(NULL);
}
// initialize the list
static void mi_initialize_atexit(void) {
InitializeCriticalSection(&atexit_lock);
init_canary();
}
// register an exit function
static int mi_register_atexit(exit_list_t* list, cbfun_t* fn) {
if (fn == NULL) return EINVAL;
EnterCriticalSection(&atexit_lock);
encoded_t* functions = (encoded_t*)decode(list->functions);
if (list->count >= list->capacity) { // at first `functions == decode(0) == NULL`
encoded_t* newf = (encoded_t*)mi_recalloc(functions, list->capacity + MI_EXIT_INC, sizeof(cbfun_t*));
if (newf != NULL) {
list->capacity += MI_EXIT_INC;
list->functions = encode(newf);
functions = newf;
}
}
int result;
if (list->count < list->capacity && functions != NULL) {
functions[list->count] = encode(fn);
list->count++;
result = 0; // success
}
else {
result = ENOMEM;
}
LeaveCriticalSection(&atexit_lock);
return result;
}
// Register a global `atexit` function
static int mi_atexit(cbfun_t* fn) {
return mi_register_atexit(&atexit_list,fn);
}
static int mi_at_quick_exit(cbfun_t* fn) {
return mi_register_atexit(&at_quick_exit_list,fn);
}
static int mi_register_onexit(void* table, cbfun_t* fn) {
// TODO: how can we distinguish a quick_exit from atexit?
return mi_atexit(fn);
}
// Execute exit functions in a list
static void mi_execute_exit_list(exit_list_t* list) {
// copy and zero the list structure
EnterCriticalSection(&atexit_lock);
exit_list_t clist = *list;
memset(list,0,sizeof(*list));
LeaveCriticalSection(&atexit_lock);
// now execute the functions outside of the lock
encoded_t* functions = (encoded_t*)decode(clist.functions);
if (functions != NULL) {
for (size_t i = clist.count; i > 0; i--) { // careful with unsigned count down..
cbfun_t* fn = (cbfun_t*)decode(functions[i-1]);
if (fn==NULL) break; // corrupted!
fn();
}
mi_free(functions);
}
}
// ------------------------------------------------------
// Jump assembly instructions for patches
// ------------------------------------------------------
#if defined(_M_IX86) || defined(_M_X64)
#define MI_JUMP_SIZE 14 // at most 2+4+8 for a long jump or 1+5 for a short one
typedef struct mi_jump_s {
uint8_t opcodes[MI_JUMP_SIZE];
} mi_jump_t;
void mi_jump_restore(void* current, const mi_jump_t* saved) {
memcpy(current, &saved->opcodes, MI_JUMP_SIZE);
}
void mi_jump_write(void* current, void* target, mi_jump_t* save) {
if (save != NULL) {
memcpy(&save->opcodes, current, MI_JUMP_SIZE);
}
uint8_t* opcodes = ((mi_jump_t*)current)->opcodes;
ptrdiff_t diff = (uint8_t*)target - (uint8_t*)current;
uint32_t ofs32 = (uint32_t)diff;
#ifdef _M_X64
uint64_t ofs64 = (uint64_t)diff;
if (ofs64 != (uint64_t)ofs32) {
// use long jump
opcodes[0] = 0xFF;
opcodes[1] = 0x25;
*((uint32_t*)&opcodes[2]) = 0;
*((uint64_t*)&opcodes[6]) = (uint64_t)target;
}
else
#endif
{
// use short jump
opcodes[0] = 0xE9;
*((uint32_t*)&opcodes[1]) = ofs32 - 5 /* size of the short jump instruction */;
}
}
#elif defined(_M_ARM64)
#define MI_JUMP_SIZE 16
typedef struct mi_jump_s {
uint8_t opcodes[MI_JUMP_SIZE];
} mi_jump_t;
void mi_jump_restore(void* current, const mi_jump_t* saved) {
memcpy(current, &saved->opcodes, MI_JUMP_SIZE);
}
void mi_jump_write(void* current, void* target, mi_jump_t* save) {
if (save != NULL) {
memcpy(&save->opcodes, current, MI_JUMP_SIZE);
}
uint8_t* opcodes = ((mi_jump_t*)current)->opcodes;
uint64_t diff = (uint8_t*)target - (uint8_t*)current;
// 0x50 0x00 0x00 0x58 ldr x16, .+8 # load PC relative +8
// 0x00 0x02 0x3F 0xD6 blr x16 # and jump
// <address>
// <address>
static const uint8_t jump_opcodes[8] = { 0x50, 0x00, 0x00, 0x58, 0x00, 0x02, 0x3F, 0xD6 };
memcpy(&opcodes[0], jump_opcodes, sizeof(jump_opcodes));
*((uint64_t*)&opcodes[8]) = diff;
}
#else
#error "define jump instructions for this platform"
#endif
// ------------------------------------------------------
// Patches
// ------------------------------------------------------
typedef enum patch_apply_e {
PATCH_NONE,
PATCH_TARGET,
PATCH_TARGET_TERM
} patch_apply_t;
#define MAX_ENTRIES 4 // maximum number of patched entry points (like `malloc` in ucrtbase and msvcrt)
typedef struct mi_patch_s {
const char* name; // name of the function to patch
void* target; // the address of the new target (never NULL)
void* target_term; // the address of the target during termination (or NULL)
patch_apply_t applied; // what target has been applied?
void* originals[MAX_ENTRIES]; // the resolved addresses of the function (or NULLs)
mi_jump_t saves[MAX_ENTRIES]; // the saved instructions in case it was applied
} mi_patch_t;
#define MI_PATCH_NAME3(name,target,term) { name, &target, &term, PATCH_NONE, {NULL,NULL,NULL,NULL} }
#define MI_PATCH_NAME2(name,target) { name, &target, NULL, PATCH_NONE, {NULL,NULL,NULL,NULL} }
#define MI_PATCH3(name,target,term) MI_PATCH_NAME3(#name, target, term)
#define MI_PATCH2(name,target) MI_PATCH_NAME2(#name, target)
#define MI_PATCH1(name) MI_PATCH2(name,mi_##name)
static mi_patch_t patches[] = {
// we implement our own global exit handler (as the CRT versions do a realloc internally)
//MI_PATCH2(_crt_atexit, mi_atexit),
//MI_PATCH2(_crt_at_quick_exit, mi_at_quick_exit),
MI_PATCH2(_setmaxstdio, mi_setmaxstdio),
MI_PATCH2(_register_onexit_function, mi_register_onexit),
// override higher level atexit functions so we can implement at_quick_exit correcty
MI_PATCH2(atexit, mi_atexit),
MI_PATCH2(at_quick_exit, mi_at_quick_exit),
// regular entries
MI_PATCH2(malloc, mi_malloc),
MI_PATCH2(calloc, mi_calloc),
MI_PATCH3(realloc, mi_realloc,mi_realloc_term),
MI_PATCH3(free, mi_free,mi_free_term),
// extended api
MI_PATCH2(_strdup, mi_strdup),
MI_PATCH2(_strndup, mi_strndup),
MI_PATCH3(_expand, mi__expand,mi__expand_term),
MI_PATCH3(_recalloc, mi_recalloc,mi__recalloc_term),
MI_PATCH3(_msize, mi_usable_size,mi__msize_term),
// base versions
MI_PATCH2(_malloc_base, mi_malloc),
MI_PATCH2(_calloc_base, mi_calloc),
MI_PATCH3(_realloc_base, mi_realloc,mi_realloc_term),
MI_PATCH3(_free_base, mi_free,mi_free_term),
// these base versions are in the crt but without import records
MI_PATCH_NAME3("_recalloc_base", mi_recalloc,mi__recalloc_term),
MI_PATCH_NAME3("_msize_base", mi_usable_size,mi__msize_term),
// debug
MI_PATCH2(_malloc_dbg, mi__malloc_dbg),
MI_PATCH2(_realloc_dbg, mi__realloc_dbg),
MI_PATCH2(_calloc_dbg, mi__calloc_dbg),
MI_PATCH2(_free_dbg, mi__free_dbg),
MI_PATCH3(_expand_dbg, mi__expand_dbg, mi__expand_dbg_term),
MI_PATCH3(_recalloc_dbg, mi__recalloc_dbg, mi__recalloc_dbg_term),
MI_PATCH3(_msize_dbg, mi__msize_dbg, mi__msize_dbg_term),
#if 0
// override new/delete variants for efficiency (?)
#ifdef _WIN64
// 64 bit new/delete
MI_PATCH_NAME2("??2@YAPEAX_K@Z", mi_new),
MI_PATCH_NAME2("??_U@YAPEAX_K@Z", mi_new),
MI_PATCH_NAME3("??3@YAXPEAX@Z", mi_free, mi_free_term),
MI_PATCH_NAME3("??_V@YAXPEAX@Z", mi_free, mi_free_term),
MI_PATCH_NAME3("??3@YAXPEAX_K@Z", mi_free_size, mi_free_size_term), // delete sized
MI_PATCH_NAME3("??_V@YAXPEAX_K@Z", mi_free_size, mi_free_size_term), // delete sized
MI_PATCH_NAME2("??2@YAPEAX_KAEBUnothrow_t@std@@@Z", mi_new),
MI_PATCH_NAME2("??_U@YAPEAX_KAEBUnothrow_t@std@@@Z", mi_new),
MI_PATCH_NAME3("??3@YAXPEAXAEBUnothrow_t@std@@@Z", mi_free_nothrow, mi_free_nothrow_term),
MI_PATCH_NAME3("??_V@YAXPEAXAEBUnothrow_t@std@@@Z", mi_free_nothrow, mi_free_nothrow_term),
#else
// 32 bit new/delete
MI_PATCH_NAME2("??2@YAPAXI@Z", mi_new),
MI_PATCH_NAME2("??_U@YAPAXI@Z", mi_new),
MI_PATCH_NAME3("??3@YAXPAX@Z", mi_free, mi_free_term),
MI_PATCH_NAME3("??_V@YAXPAX@Z", mi_free, mi_free_term),
MI_PATCH_NAME3("??3@YAXPAXI@Z", mi_free_size, mi_free_size_term), // delete sized
MI_PATCH_NAME3("??_V@YAXPAXI@Z", mi_free_size, mi_free_size_term), // delete sized
MI_PATCH_NAME2("??2@YAPAXIABUnothrow_t@std@@@Z", mi_new),
MI_PATCH_NAME2("??_U@YAPAXIABUnothrow_t@std@@@Z", mi_new),
MI_PATCH_NAME3("??3@YAXPAXABUnothrow_t@std@@@Z", mi_free_nothrow, mi_free_nothrow_term),
MI_PATCH_NAME3("??_V@YAXPAXABUnothrow_t@std@@@Z", mi_free_nothrow, mi_free_nothrow_term),
#endif
#endif
{ NULL, NULL, NULL, PATCH_NONE, {NULL,NULL,NULL,NULL} }
};
// Apply a patch
static bool mi_patch_apply(mi_patch_t* patch, patch_apply_t apply)
{
if (patch->originals[0] == NULL) return true; // unresolved
if (apply == PATCH_TARGET_TERM && patch->target_term == NULL) apply = PATCH_TARGET; // avoid re-applying non-term variants
if (patch->applied == apply) return false;
for (int i = 0; i < MAX_ENTRIES; i++) {
void* original = patch->originals[i];
if (original == NULL) break; // no more
DWORD protect = PAGE_READWRITE;
if (!VirtualProtect(original, MI_JUMP_SIZE, PAGE_EXECUTE_READWRITE, &protect)) return false;
if (apply == PATCH_NONE) {
mi_jump_restore(original, &patch->saves[i]);
}
else {
void* target = (apply == PATCH_TARGET ? patch->target : patch->target_term);
mi_assert_internal(target != NULL);
if (target != NULL) mi_jump_write(original, target, &patch->saves[i]);
}
VirtualProtect(original, MI_JUMP_SIZE, protect, &protect);
}
patch->applied = apply;
return true;
}
// Apply all patches
static bool _mi_patches_apply(patch_apply_t apply, patch_apply_t* previous) {
static patch_apply_t current = PATCH_NONE;
if (previous != NULL) *previous = current;
if (current == apply) return true;
current = apply;
bool ok = true;
for (size_t i = 0; patches[i].name != NULL; i++) {
if (!mi_patch_apply(&patches[i], apply)) ok = false;
}
return ok;
}
// Export the following three functions just in case
// a user needs that level of control.
// Disable all patches
mi_decl_export void mi_patches_disable(void) {
_mi_patches_apply(PATCH_NONE, NULL);
}
// Enable all patches normally
mi_decl_export bool mi_patches_enable(void) {
return _mi_patches_apply( PATCH_TARGET, NULL );
}
// Enable all patches in termination phase where free is a no-op
mi_decl_export bool mi_patches_enable_term(void) {
return _mi_patches_apply(PATCH_TARGET_TERM, NULL);
}
// ------------------------------------------------------
// Stub for _setmaxstdio
// ------------------------------------------------------
static int __cdecl mi_setmaxstdio(int newmax) {
patch_apply_t previous;
_mi_patches_apply(PATCH_NONE, &previous); // disable patches
int result = _setmaxstdio(newmax); // call original function (that calls original CRT recalloc)
_mi_patches_apply(previous,NULL); // and re-enable patches
return result;
}
// ------------------------------------------------------
// Resolve addresses dynamically
// ------------------------------------------------------
// Try to resolve patches for a given module (DLL)
static void mi_module_resolve(const char* fname, HMODULE mod, int priority) {
// see if any patches apply
for (size_t i = 0; patches[i].name != NULL; i++) {
mi_patch_t* patch = &patches[i];
if (patch->applied == PATCH_NONE) {
// find an available entry
int i = 0;
while (i < MAX_ENTRIES && patch->originals[i] != NULL) i++;
if (i < MAX_ENTRIES) {
void* addr = GetProcAddress(mod, patch->name);
if (addr != NULL) {
// found it! set the address
patch->originals[i] = addr;
_mi_trace_message(" found %s at %s!%p (entry %i)\n", patch->name, fname, addr, i);
}
}
}
}
}
#define MIMALLOC_NAME "mimalloc-override.dll"
#define UCRTBASE_NAME "ucrtbase.dll"
#define UCRTBASED_NAME "ucrtbased.dll"
// Resolve addresses of all patches by inspecting the loaded modules
static atexit_fun_t* crt_atexit = NULL;
static atexit_fun_t* crt_at_quick_exit = NULL;
static bool mi_patches_resolve(void) {
// get all loaded modules
HANDLE process = GetCurrentProcess(); // always -1, no need to release
DWORD needed = 0;
HMODULE modules[400]; // try to stay under 4k to not trigger the guard page
EnumProcessModules(process, modules, sizeof(modules), &needed);
if (needed == 0) return false;
int count = needed / sizeof(HMODULE);
int ucrtbase_index = 0;
int mimalloc_index = 0;
// iterate through the loaded modules
for (int i = 0; i < count; i++) {
HMODULE mod = modules[i];
char filename[MAX_PATH] = { 0 };
DWORD slen = GetModuleFileName(mod, filename, MAX_PATH);
if (slen > 0 && slen < MAX_PATH) {
// filter out potential crt modules only
filename[slen] = 0;
const char* lastsep = strrchr(filename, '\\');
const char* basename = (lastsep==NULL ? filename : lastsep+1);
_mi_trace_message(" %i: dynamic module %s\n", i, filename);
// remember indices so we can check load order (in debug mode)
if (_stricmp(basename, MIMALLOC_NAME) == 0) mimalloc_index = i;
if (_stricmp(basename, UCRTBASE_NAME) == 0) ucrtbase_index = i;
if (_stricmp(basename, UCRTBASED_NAME) == 0) ucrtbase_index = i;
// see if we potentially patch in this module
int priority = 0;
if (i == 0) priority = 2; // main module to allow static crt linking
else if (_strnicmp(basename, "ucrt", 4) == 0) priority = 3; // new ucrtbase.dll in windows 10
// NOTE: don't override msvcr -- leads to crashes in setlocale (needs more testing)
// else if (_strnicmp(basename, "msvcr", 5) == 0) priority = 1; // older runtimes
if (priority > 0) {
// probably found a crt module, try to patch it
mi_module_resolve(basename,mod,priority);
// try to find the atexit functions for the main process (in `ucrtbase.dll`)
if (crt_atexit==NULL) crt_atexit = (atexit_fun_t*)GetProcAddress(mod, "_crt_atexit");
if (crt_at_quick_exit == NULL) crt_at_quick_exit = (atexit_fun_t*)GetProcAddress(mod, "_crt_at_quick_exit");
}
}
}
int diff = mimalloc_index - ucrtbase_index;
if (diff > 1) {
_mi_warning_message("warning: the \"mimalloc-override\" DLL seems not to load before or right after the C runtime (\"ucrtbase\").\n"
" Try to fix this by changing the linking order.\n");
}
return true;
}
// ------------------------------------------------------
// Dll Entry
// ------------------------------------------------------
extern BOOL WINAPI _DllMainCRTStartup(HINSTANCE inst, DWORD reason, LPVOID reserved);
static DWORD mi_fls_unwind_entry;
static void NTAPI mi_fls_unwind(PVOID value) {
if (value != NULL) mi_patches_enable(); // and re-enable normal patches again for DLL's loaded after us
return;
}
static void mi_patches_atexit(void) {
mi_execute_exit_list(&atexit_list);
mi_patches_enable_term(); // enter termination phase and patch realloc/free with a no-op
}
static void mi_patches_at_quick_exit(void) {
mi_execute_exit_list(&at_quick_exit_list);
mi_patches_enable_term(); // enter termination phase and patch realloc/free with a no-op
}
BOOL WINAPI DllEntry(HINSTANCE inst, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
__security_init_cookie();
}
else if (reason == DLL_PROCESS_DETACH) {
// enter termination phase for good now
mi_patches_enable_term();
}
// C runtime main
BOOL ok = _DllMainCRTStartup(inst, reason, reserved);
if (reason == DLL_PROCESS_ATTACH && ok) {
// initialize at exit lists
mi_initialize_atexit();
// Now resolve patches
ok = mi_patches_resolve();
if (ok) {
// check if patching is not disabled
#pragma warning(suppress:4996)
const char* s = getenv("MIMALLOC_DISABLE_OVERRIDE");
bool enabled = (s == NULL || !(strstr("1;TRUE;YES;ON", s) != NULL));
if (!enabled) {
_mi_verbose_message("override is disabled\n");
}
else {
// and register our unwind entry (this must be after resolving due to possible delayed DLL initialization from GetProcAddress)
mi_fls_unwind_entry = FlsAlloc(&mi_fls_unwind);
if (mi_fls_unwind_entry != FLS_OUT_OF_INDEXES) {
FlsSetValue(mi_fls_unwind_entry, (void*)1);
}
// register our patch disabler in the global exit list
if (crt_atexit != NULL) (*crt_atexit)(&mi_patches_atexit);
if (crt_at_quick_exit != NULL) (*crt_at_quick_exit)(&mi_patches_at_quick_exit);
// and patch ! this also redirects the `atexit` handling for the global exit list
mi_patches_enable();
_mi_verbose_message("override is enabled\n");
// hide internal allocation
mi_stats_reset();
}
}
}
return ok;
}

View file

@ -13,7 +13,7 @@ terms of the MIT license. A copy of the license can be found in the file
#error "It is only possible to override "malloc" on Windows when building as a DLL (and linking the C runtime as a DLL)" #error "It is only possible to override "malloc" on Windows when building as a DLL (and linking the C runtime as a DLL)"
#endif #endif
#if defined(MI_MALLOC_OVERRIDE) && !defined(_WIN32) #if defined(MI_MALLOC_OVERRIDE) && !(defined(_WIN32)) // || (defined(__MACH__) && !defined(MI_INTERPOSE)))
// ------------------------------------------------------ // ------------------------------------------------------
// Override system malloc // Override system malloc
@ -47,26 +47,31 @@ terms of the MIT license. A copy of the license can be found in the file
const void* replacement; const void* replacement;
const void* target; const void* target;
}; };
#define MI_INTERPOSEX(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun } #define MI_INTERPOSE_FUN(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun }
#define MI_INTERPOSE_MI(fun) MI_INTERPOSEX(fun,mi_##fun) #define MI_INTERPOSE_MI(fun) MI_INTERPOSE_FUN(fun,mi_##fun)
__attribute__((used)) static struct mi_interpose_s _mi_interposes[] __attribute__((section("__DATA, __interpose"))) = __attribute__((used)) static struct mi_interpose_s _mi_interposes[] __attribute__((section("__DATA, __interpose"))) =
{ {
MI_INTERPOSE_MI(malloc), MI_INTERPOSE_MI(malloc),
MI_INTERPOSE_MI(calloc), MI_INTERPOSE_MI(calloc),
MI_INTERPOSE_MI(realloc), MI_INTERPOSE_MI(realloc),
MI_INTERPOSE_MI(free),
MI_INTERPOSE_MI(strdup), MI_INTERPOSE_MI(strdup),
MI_INTERPOSE_MI(strndup) MI_INTERPOSE_MI(strndup),
MI_INTERPOSE_MI(realpath),
MI_INTERPOSE_MI(posix_memalign),
MI_INTERPOSE_MI(reallocf),
MI_INTERPOSE_MI(valloc),
// some code allocates from a zone but deallocates using plain free :-( (like NxHashResizeToCapacity <https://github.com/nneonneo/osx-10.9-opensource/blob/master/objc4-551.1/runtime/hashtable2.mm>)
MI_INTERPOSE_FUN(free,mi_cfree), // use safe free that checks if pointers are from us
}; };
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
// cannot override malloc unless using a dll. // cannot override malloc unless using a dll.
// we just override new/delete which does work in a static library. // we just override new/delete which does work in a static library.
#else #else
// On all other systems forward to our API // On all other systems forward to our API
void* malloc(size_t size) mi_attr_noexcept MI_FORWARD1(mi_malloc, size); void* malloc(size_t size) MI_FORWARD1(mi_malloc, size);
void* calloc(size_t size, size_t n) mi_attr_noexcept MI_FORWARD2(mi_calloc, size, n); void* calloc(size_t size, size_t n) MI_FORWARD2(mi_calloc, size, n);
void* realloc(void* p, size_t newsize) mi_attr_noexcept MI_FORWARD2(mi_realloc, p, newsize); void* realloc(void* p, size_t newsize) MI_FORWARD2(mi_realloc, p, newsize);
void free(void* p) mi_attr_noexcept MI_FORWARD0(mi_free, p); void free(void* p) MI_FORWARD0(mi_free, p);
#endif #endif
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__) #if (defined(__GNUC__) || defined(__clang__)) && !defined(__MACH__)
@ -94,11 +99,11 @@ terms of the MIT license. A copy of the license can be found in the file
void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { UNUSED(tag); return mi_new_nothrow(n); } void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { UNUSED(tag); return mi_new_nothrow(n); }
#if (__cplusplus >= 201402L || _MSC_VER >= 1916) #if (__cplusplus >= 201402L || _MSC_VER >= 1916)
void operator delete (void* p, std::size_t n) MI_FORWARD02(mi_free_size,p,n); void operator delete (void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n);
void operator delete[](void* p, std::size_t n) MI_FORWARD02(mi_free_size,p,n); void operator delete[](void* p, std::size_t n) noexcept MI_FORWARD02(mi_free_size,p,n);
#endif #endif
#if (__cplusplus > 201402L || defined(__cpp_aligned_new)) #if (__cplusplus > 201402L || defined(__cpp_aligned_new)) && (!defined(__GNUC__) || (__GNUC__ > 5))
void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); } void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); } void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); }
void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); }; void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); };
@ -194,4 +199,3 @@ int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_me
#endif #endif
#endif // MI_MALLOC_OVERRIDE && !_WIN32 #endif // MI_MALLOC_OVERRIDE && !_WIN32

View file

@ -9,7 +9,6 @@ terms of the MIT license. A copy of the license can be found in the file
// mi prefixed publi definitions of various Posix, Unix, and C++ functions // mi prefixed publi definitions of various Posix, Unix, and C++ functions
// for convenience and used when overriding these functions. // for convenience and used when overriding these functions.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
#include "mimalloc.h" #include "mimalloc.h"
#include "mimalloc-internal.h" #include "mimalloc-internal.h"
@ -49,31 +48,36 @@ int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept
if (p == NULL) return EINVAL; if (p == NULL) return EINVAL;
if (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment if (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment
if (!_mi_is_power_of_two(alignment)) return EINVAL; // not a power of 2 if (!_mi_is_power_of_two(alignment)) return EINVAL; // not a power of 2
void* q = mi_malloc_aligned(size, alignment); void* q = (mi_malloc_satisfies_alignment(alignment, size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment));
if (q==NULL && size != 0) return ENOMEM; if (q==NULL && size != 0) return ENOMEM;
mi_assert_internal(((uintptr_t)q % alignment) == 0);
*p = q; *p = q;
return 0; return 0;
} }
void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept { mi_decl_restrict void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept {
return mi_malloc_aligned(size, alignment); void* p = (mi_malloc_satisfies_alignment(alignment,size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment));
mi_assert_internal(((uintptr_t)p % alignment) == 0);
return p;
} }
void* mi_valloc(size_t size) mi_attr_noexcept { mi_decl_restrict void* mi_valloc(size_t size) mi_attr_noexcept {
return mi_malloc_aligned(size, _mi_os_page_size()); return mi_memalign( _mi_os_page_size(), size );
} }
void* mi_pvalloc(size_t size) mi_attr_noexcept { mi_decl_restrict void* mi_pvalloc(size_t size) mi_attr_noexcept {
size_t psize = _mi_os_page_size(); size_t psize = _mi_os_page_size();
if (size >= SIZE_MAX - psize) return NULL; // overflow if (size >= SIZE_MAX - psize) return NULL; // overflow
size_t asize = ((size + psize - 1) / psize) * psize; size_t asize = _mi_align_up(size, psize);
return mi_malloc_aligned(asize, psize); return mi_malloc_aligned(asize, psize);
} }
void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept { mi_decl_restrict void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept {
if (alignment==0 || !_mi_is_power_of_two(alignment)) return NULL; if (alignment==0 || !_mi_is_power_of_two(alignment)) return NULL;
if ((size&(alignment-1)) != 0) return NULL; // C11 requires integral multiple, see <https://en.cppreference.com/w/c/memory/aligned_alloc> if ((size&(alignment-1)) != 0) return NULL; // C11 requires integral multiple, see <https://en.cppreference.com/w/c/memory/aligned_alloc>
return mi_malloc_aligned(size, alignment); void* p = (mi_malloc_satisfies_alignment(alignment, size) ? mi_malloc(size) : mi_malloc_aligned(size, alignment));
mi_assert_internal(((uintptr_t)p % alignment) == 0);
return p;
} }
void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept { // BSD void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept { // BSD
@ -88,7 +92,7 @@ void* mi__expand(void* p, size_t newsize) mi_attr_noexcept { // Microsoft
return res; return res;
} }
unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept { mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept {
if (s==NULL) return NULL; if (s==NULL) return NULL;
size_t len; size_t len;
for(len = 0; s[len] != 0; len++) { } for(len = 0; s[len] != 0; len++) { }
@ -100,7 +104,7 @@ unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept {
return p; return p;
} }
unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept { mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept {
return (unsigned char*)mi_strdup((const char*)s); return (unsigned char*)mi_strdup((const char*)s);
} }

Some files were not shown because too many files have changed in this diff Show more