Add mimalloc to improve multithreaded performance (#6188)
Co-authored-by: Zackery Mason-Blaug <zackery.mason-blaug@ntd.nintendo.com>
diff --git a/.gitignore b/.gitignore
index e85cea9..042becf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,7 @@
/external/effcee
/external/re2
/external/protobuf
+/external/mimalloc
/out
/TAGS
/third_party/llvm-build/
diff --git a/BUILD.bazel b/BUILD.bazel
index 0c0bfe9..979c233 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -131,6 +131,8 @@
"source/*.cpp",
"source/util/*.cpp",
"source/val/*.cpp",
+ ], exclude = [
+ "source/mimalloc.cpp"
]) + [
":build_version_inc",
":gen_compressed_tables",
diff --git a/DEPS b/DEPS
index 0cbd750..3e2fb77 100644
--- a/DEPS
+++ b/DEPS
@@ -15,6 +15,8 @@
're2_revision': 'c84a140c93352cdabbfb547c531be34515b12228',
'spirv_headers_revision': '2a611a970fdbc41ac2e3e328802aed9985352dca',
+
+ 'mimalloc_revision': '51c09e7b6a0ac5feeba998710f00c7dd7aa67bbf',
}
deps = {
@@ -36,5 +38,8 @@
'external/spirv-headers':
Var('github') + '/KhronosGroup/SPIRV-Headers.git@' +
Var('spirv_headers_revision'),
+
+ 'external/mimalloc':
+ Var('github') + '/microsoft/mimalloc.git@' + Var('mimalloc_revision'),
}
diff --git a/README.md b/README.md
index 7bf8a51..adfb5a9 100644
--- a/README.md
+++ b/README.md
@@ -300,6 +300,7 @@
git clone https://github.com/google/effcee.git spirv-tools/external/effcee
git clone https://github.com/google/re2.git spirv-tools/external/re2
git clone https://github.com/abseil/abseil-cpp.git spirv-tools/external/abseil_cpp
+ git clone https://github.com/microsoft/mimalloc.git spirv-tools/external/mimalloc
#### Dependency on Effcee
@@ -312,6 +313,23 @@
RE2 sources to appear in `external/re2`, and Abseil sources to appear in
`external/abseil_cpp`.
+#### Dependency on mimalloc
+
+SPIRV-Tools may be configured to use the [mimalloc][mimalloc] library to improve memory
+allocation performance. In order to avoid unexpectedly changing allocation behavior of
+applications that link SPIRV-Tools libraries statically, this option has no effect on
+the static libraries.
+
+In the CMake build, usage of mimalloc is controlled by the `SPIRV_TOOLS_USE_MIMALLOC`
+option. This variable defaults on `ON` when building for Windows and `OFF` when building
+for other platforms. Enabling this option on non-Windows platforms is supported and is
+expected to work normally, but this has not been tested as thoroughly and extensively as
+the Windows version. In the future, the `SPIRV_TOOLS_USE_MIMALLOC` option may default to
+`ON` for non-Windows platforms as well.
+
+*Note*: mimalloc is currently only supported when building with CMake. When using Bazel,
+mimalloc is not used.
+
### Source code organization
* `example`: demo code of using SPIRV-Tools APIs
@@ -325,6 +343,7 @@
* `external/abseil_cpp`: Location of [Abseil][abseil-cpp] sources, if Abseil is
not already configured by an enclosing project.
(The RE2 project already requires Abseil.)
+* `external/mimalloc`: Intended location for [mimalloc][mimalloc] sources, not provided
* `include/`: API clients should add this directory to the include search path
* `external/spirv-headers`: Intended location for
[SPIR-V headers][spirv-headers], not provided
@@ -801,6 +820,7 @@
[effcee]: https://github.com/google/effcee
[re2]: https://github.com/google/re2
[abseil-cpp]: https://github.com/abseil/abseil-cpp
+[mimalloc]: https://github.com/microsoft/mimalloc
[CMake]: https://cmake.org/
[cpp-style-guide]: https://google.github.io/styleguide/cppguide.html
[clang-sanitizers]: http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
index 1ccab19..d8c7266 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
@@ -26,6 +26,46 @@
set(${var} ${val} PARENT_SCOPE)
endfunction()
+if (DEFINED mimalloc_SOURCE_DIR)
+ # This allows flexible position of the mimalloc repo.
+ set(MIMALLOC_DIR ${mimalloc_SOURCE_DIR})
+else()
+ if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mimalloc)
+ set(MIMALLOC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mimalloc)
+ endif()
+endif()
+
+# Used on Windows by default, but allow opt-in on other platforms
+if (WIN32)
+ set(SPIRV_TOOLS_USE_MIMALLOC_DEFAULT_VALUE ON)
+else()
+ set(SPIRV_TOOLS_USE_MIMALLOC_DEFAULT_VALUE OFF)
+endif()
+
+# To avoid unexpected side effects on users of the static library, mimalloc
+# may only be used when building executables and shared libraries.
+include(CMakeDependentOption)
+cmake_dependent_option(SPIRV_TOOLS_USE_MIMALLOC
+ "Executables and shared libraries use mimalloc instead of the default allocator"
+ ${SPIRV_TOOLS_USE_MIMALLOC_DEFAULT_VALUE} "MIMALLOC_DIR" OFF)
+
+if (SPIRV_TOOLS_USE_MIMALLOC)
+ if (NOT WIN32)
+ push_variable(MI_OVERRIDE 0)
+ endif()
+ push_variable(MI_BUILD_TESTS 0)
+
+ add_subdirectory(${MIMALLOC_DIR} ${CMAKE_BINARY_DIR}/external/mimalloc EXCLUDE_FROM_ALL)
+ if (${CMAKE_CXX_COMPILER_ID} MATCHES Clang)
+ target_compile_options(mimalloc-static PRIVATE -Wno-int-conversion)
+ endif()
+
+ if (NOT WIN32)
+ pop_variable(MI_OVERRIDE)
+ endif()
+ pop_variable(MI_BUILD_TESTS)
+endif()
+
if (DEFINED SPIRV-Headers_SOURCE_DIR)
# This allows flexible position of the SPIRV-Headers repo.
set(SPIRV_HEADER_DIR ${SPIRV-Headers_SOURCE_DIR})
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index f822ada..fd2d963 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -297,6 +297,12 @@
${CMAKE_CURRENT_SOURCE_DIR}/util/timer.cpp)
endif()
+if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ set(SPIRV_SOURCES
+ ${SPIRV_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/mimalloc.cpp)
+endif()
+
# The software_version.cpp file includes build-version.inc.
# Rebuild the software_version.cpp object file if it is older than
# build-version.inc or whenever build-version.inc itself is out of
@@ -333,6 +339,9 @@
# Always build ${SPIRV_TOOLS}-shared. This is expected distro packages, and
# unlike the other SPIRV_TOOLS target, defaults to hidden symbol visibility.
add_library(${SPIRV_TOOLS}-shared SHARED ${SPIRV_SOURCES})
+if (SPIRV_TOOLS_USE_MIMALLOC)
+ target_link_libraries(${SPIRV_TOOLS}-shared PRIVATE mimalloc-static)
+endif()
spirv_tools_default_target_options(${SPIRV_TOOLS}-shared)
set_target_properties(${SPIRV_TOOLS}-shared PROPERTIES CXX_VISIBILITY_PRESET hidden)
target_compile_definitions(${SPIRV_TOOLS}-shared
@@ -357,6 +366,9 @@
set(SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS}-static ${SPIRV_TOOLS}-shared)
else()
add_library(${SPIRV_TOOLS} ${SPIRV_TOOLS_LIBRARY_TYPE} ${SPIRV_SOURCES})
+ if (SPIRV_TOOLS_USE_MIMALLOC)
+ target_link_libraries(${SPIRV_TOOLS} PRIVATE mimalloc-static)
+ endif()
spirv_tools_default_target_options(${SPIRV_TOOLS})
set(SPIRV_TOOLS_TARGETS ${SPIRV_TOOLS} ${SPIRV_TOOLS}-shared)
endif()
@@ -365,12 +377,15 @@
find_library(LIBRT rt)
if(LIBRT)
foreach(target ${SPIRV_TOOLS_TARGETS})
- target_link_libraries(${target} rt)
+ target_link_libraries(${target} PUBLIC rt)
endforeach()
endif()
endif()
if(ENABLE_SPIRV_TOOLS_INSTALL)
+ if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ list(APPEND SPIRV_TOOLS_TARGETS mimalloc-static)
+ endif()
install(TARGETS ${SPIRV_TOOLS_TARGETS} EXPORT ${SPIRV_TOOLS}Targets)
export(EXPORT ${SPIRV_TOOLS}Targets FILE ${SPIRV_TOOLS}Target.cmake)
diff --git a/source/diff/CMakeLists.txt b/source/diff/CMakeLists.txt
index 52f18f2..d288261 100644
--- a/source/diff/CMakeLists.txt
+++ b/source/diff/CMakeLists.txt
@@ -18,8 +18,16 @@
diff.cpp
)
+if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ list(APPEND SPIRV_TOOLS_DIFF_SOURCES ${spirv-tools_SOURCE_DIR}/source/mimalloc.cpp)
+endif()
+
add_library(SPIRV-Tools-diff ${SPIRV_TOOLS_LIBRARY_TYPE} ${SPIRV_TOOLS_DIFF_SOURCES})
+if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ target_link_libraries(SPIRV-Tools-diff PRIVATE mimalloc-static)
+endif()
+
spvtools_default_compile_options(SPIRV-Tools-diff)
target_include_directories(SPIRV-Tools-diff
PUBLIC
@@ -39,7 +47,13 @@
spvtools_check_symbol_exports(SPIRV-Tools-diff)
if(ENABLE_SPIRV_TOOLS_INSTALL)
- install(TARGETS SPIRV-Tools-diff EXPORT SPIRV-Tools-diffTargets)
+ set(SPIRV-Tools-diff-InstallTargets SPIRV-Tools-diff)
+
+ if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ list(APPEND SPIRV-Tools-diff-InstallTargets mimalloc-static)
+ endif()
+
+ install(TARGETS ${SPIRV-Tools-diff-InstallTargets} EXPORT SPIRV-Tools-diffTargets)
export(EXPORT SPIRV-Tools-diffTargets FILE SPIRV-Tools-diffTargets.cmake)
spvtools_config_package_dir(SPIRV-Tools-diff PACKAGE_DIR)
diff --git a/source/fuzz/CMakeLists.txt b/source/fuzz/CMakeLists.txt
index 86ee657..d067bd4 100644
--- a/source/fuzz/CMakeLists.txt
+++ b/source/fuzz/CMakeLists.txt
@@ -438,8 +438,16 @@
spvtools_pch(SPIRV_TOOLS_FUZZ_SOURCES pch_source_fuzz)
+ if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ list(APPEND SPIRV_TOOLS_DIFF_SOURCES ${spirv-tools_SOURCE_DIR}/source/mimalloc.cpp)
+ endif()
+
add_library(SPIRV-Tools-fuzz ${SPIRV_TOOLS_FUZZ_SOURCES})
+ if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ target_link_libraries(SPIRV-Tools-fuzz PRIVATE mimalloc-static)
+ endif()
+
spvtools_default_compile_options(SPIRV-Tools-fuzz)
# Compilation of the auto-generated protobuf source file will yield warnings,
@@ -470,7 +478,13 @@
spvtools_check_symbol_exports(SPIRV-Tools-fuzz)
if(ENABLE_SPIRV_TOOLS_INSTALL)
- install(TARGETS SPIRV-Tools-fuzz EXPORT SPIRV-Tools-fuzzTargets)
+ set(SPIRV-Tools-fuzz-InstallTargets SPIRV-Tools-fuzz)
+
+ if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ list(APPEND SPIRV-Tools-fuzz-InstallTargets mimalloc-static)
+ endif()
+
+ install(TARGETS ${SPIRV-Tools-fuzz-InstallTargets} EXPORT SPIRV-Tools-fuzzTargets)
export(EXPORT SPIRV-Tools-fuzzTargets FILE SPIRV-Tools-fuzzTarget.cmake)
spvtools_config_package_dir(SPIRV-Tools-fuzz PACKAGE_DIR)
diff --git a/source/mimalloc.cpp b/source/mimalloc.cpp
new file mode 100644
index 0000000..777cd6f
--- /dev/null
+++ b/source/mimalloc.cpp
@@ -0,0 +1,15 @@
+// Copyright (c) 2025 The Khronos Group Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "mimalloc-new-delete.h"
diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt
index ee3aeb1..ba0b211 100644
--- a/source/opt/CMakeLists.txt
+++ b/source/opt/CMakeLists.txt
@@ -260,8 +260,16 @@
spvtools_pch(SPIRV_TOOLS_OPT_SOURCES pch_source_opt)
+if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ list(APPEND SPIRV_TOOLS_OPT_SOURCES ${spirv-tools_SOURCE_DIR}/source/mimalloc.cpp)
+endif()
+
add_library(SPIRV-Tools-opt ${SPIRV_TOOLS_LIBRARY_TYPE} ${SPIRV_TOOLS_OPT_SOURCES})
+if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ target_link_libraries(SPIRV-Tools-opt PRIVATE mimalloc-static)
+endif()
+
spvtools_default_compile_options(SPIRV-Tools-opt)
target_include_directories(SPIRV-Tools-opt
PUBLIC
@@ -278,7 +286,13 @@
spvtools_check_symbol_exports(SPIRV-Tools-opt)
if(ENABLE_SPIRV_TOOLS_INSTALL)
- install(TARGETS SPIRV-Tools-opt EXPORT SPIRV-Tools-optTargets)
+ set(SPIRV-Tools-opt-InstallTargets SPIRV-Tools-opt)
+
+ if (SPIRV_TOOLS_USE_MIMALLOC AND NOT SPIRV_TOOLS_BUILD_STATIC)
+ list(APPEND SPIRV-Tools-opt-InstallTargets mimalloc-static)
+ endif()
+
+ install(TARGETS ${SPIRV-Tools-opt-InstallTargets} EXPORT SPIRV-Tools-optTargets)
export(EXPORT SPIRV-Tools-optTargets FILE SPIRV-Tools-optTargets.cmake)
spvtools_config_package_dir(SPIRV-Tools-opt PACKAGE_DIR)
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index a6736ca..f5e830f 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -24,12 +24,21 @@
# LIBS lib_target1 lib_target2
# )
function(add_spvtools_tool)
+ if (SPIRV_TOOLS_USE_MIMALLOC)
+ list(APPEND SRCS mimalloc.cpp)
+ endif()
+
set(one_value_args TARGET)
set(multi_value_args SRCS LIBS)
cmake_parse_arguments(
ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN})
add_executable(${ARG_TARGET} ${ARG_SRCS})
+
+ if (SPIRV_TOOLS_USE_MIMALLOC)
+ target_link_libraries(${ARG_TARGET} PRIVATE mimalloc-static)
+ endif()
+
spvtools_default_compile_options(${ARG_TARGET})
target_link_libraries(${ARG_TARGET} PRIVATE ${ARG_LIBS})
target_include_directories(${ARG_TARGET} PRIVATE
diff --git a/utils/roll_deps.sh b/utils/roll_deps.sh
index a62ebe9..d8c1da3 100755
--- a/utils/roll_deps.sh
+++ b/utils/roll_deps.sh
@@ -35,6 +35,7 @@
dependency_to_branch_map["external/googletest/"]="origin/main"
dependency_to_branch_map["external/re2/"]="origin/main"
dependency_to_branch_map["external/spirv-headers/"]="origin/main"
+dependency_to_branch_map["external/mimalloc/"]="origin/main"
# This script assumes it's parent directory is the repo root.
repo_path=$(dirname "$0")/..