Skip to content

Instantly share code, notes, and snippets.

@MihaelIsaev
Last active April 9, 2025 17:22
Show Gist options
  • Save MihaelIsaev/fbb0135e9b1bb1d2691bb71a30528bc6 to your computer and use it in GitHub Desktop.
Save MihaelIsaev/fbb0135e9b1bb1d2691bb71a30528bc6 to your computer and use it in GitHub Desktop.
How to patch Swift `static-linux-sdk` with `mimalloc` step-by-step

According to the Performance penalty from the Static Linux SDK post I would like to provide a step-by-step instruction of how to patch static-linux-sdk with mimalloc

Why?

It is important for swift apps – especially for server-side apps – to be performant

Doesn't Static Linux SDK already have mimalloc?

Great question! Maybe in the future — who knows?

If you're from the future, you can check your SDK by running

llvm-nm libc.a | grep 'mi_'

If it returns nothing, then mimalloc hasn't been integrated yet — and you can integrate it by following this instruction

If it returns a lot of mi_, then congrats — you've already got mimalloc in your SDK 🎉

Disclaimer

You are doing it at your own risk 😱

Requirements

x86_64 and arm64 ubuntu/debian environment

Or docker with QEMU, but I had no luck with it yet. So I used x86_64 and arm64 machines on Hetzner Cloud

static-linux-sdk gives you the ability to compile into x86 and ARM architectures, it means that it has two versions of libc.a, one for each platform

We have to patch both

Step-by-step

Get SDK

I assume you already have it installed on your machine, but if not then install or just download it

Install

swift sdk install <URL> --checksum <CHECKSUM>

Download SDK

  1. Go to swift.org
  2. Choose Ubuntu or Debian
  3. Choose version of OS 4.1. Hit the Download Linux Static SDK button 4.2 Or copy link and download it with curl e.g. curl -LO <URL>

Extract SDK archive

Let's assume you downloaded swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz

Then, execute

tar -xzf swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz

Take libc.a files from it

Create x86_64 and aarch64 directories

mkdir x86_64 && mkdir aarch64

Copy both versions of libc.a into these directories

If you have it installed then it is located at ~/.swiftpm/swift-sdks

If not then it is where you extracted it

cp swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/usr/lib/libc.a ./x86_64/libc.a
cp swift-6.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/aarch64/usr/lib/libc.a ./aarch64/libc.a

Patching

Do the following steps on both x86_64 and arm64 machines

Install required packages via apt

# install required packages
apt update
apt install -y llvm software-properties-common build-essential libssl-dev clang

Prepare cmake

Note

mimalloc requires cmake >= 3.18.0

Check your cmake version

cmake --version

If it is lower, then install 3.27.9 from sources by following these steps

# download cmake
curl -LO https://github.com/Kitware/CMake/releases/download/v3.27.9/cmake-3.27.9.tar.gz
# extract cmake
tar -xf cmake-3.27.9.tar.gz
# go to cmake dir
cd cmake-3.27.9
# compile cmake
./bootstrap --prefix=$HOME/.local
make -j$(nproc)
make install
# add cmake into PATH
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# check cmake version
cmake --version
# go back to the parent dir
cd ../

Download

  1. Download mimalloc_v2.1.7.diff and patch_musl.sh
curl -LO https://gist.github.com/MihaelIsaev/fbb0135e9b1bb1d2691bb71a30528bc6/raw/4448da386e6d0dbd704716091be4818e56ba3d28/mimalloc_v2.1.7.diff
curl -LO https://gist.github.com/MihaelIsaev/fbb0135e9b1bb1d2691bb71a30528bc6/raw/4448da386e6d0dbd704716091be4818e56ba3d28/patch_musl.sh
  1. Make patch_musl.sh executable
chmod +x ./patch_musl.sh
  1. Uploadlibc.a for the current CPU architecture

Patch libc.a

It will create libc.a.bak backup of the original file

./patch_musl.sh

🥳 Now you have successfully patched libc.a with mimalloc

Tip

Don't forget to patch it for both architectures

Copy libc.a back into your SDK

I assume you have it installed, so copy proper libc.a files into their usr/lib directories

Do I need to put libmimalloc.a alongside libc.a?

No, mimalloc has been merged into libc.a

Docker version?

I tried to do it but had no luck yet. You are welcome to implement it and update this instruction 🤝

Credits

Credit to Sebastian Toivonen, aka MarSe32m and his post

🫡 Enjoy!

diff --git a/CMakeLists.txt b/CMakeLists.txt
index bcfe91d8..a5473c69 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -481,7 +481,6 @@ endif()
# static library
if (MI_BUILD_STATIC)
add_library(mimalloc-static STATIC ${mi_sources})
- set_property(TARGET mimalloc-static PROPERTY POSITION_INDEPENDENT_CODE ON)
target_compile_definitions(mimalloc-static PRIVATE ${mi_defines} MI_STATIC_LIB)
target_compile_options(mimalloc-static PRIVATE ${mi_cflags} ${mi_cflags_static})
target_link_libraries(mimalloc-static PRIVATE ${mi_libraries})
diff --git a/src/alloc-override.c b/src/alloc-override.c
index 12837cdd..e5bcda22 100644
--- a/src/alloc-override.c
+++ b/src/alloc-override.c
@@ -191,7 +191,7 @@ typedef void* mi_nothrow_t;
void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); }
#endif
-#elif (defined(__GNUC__) || defined(__clang__))
+#elif (defined(__GNUC__) || defined(__clang__) || defined(do_we_need_this))
// ------------------------------------------------------
// Override by defining the mangled C++ names of the operators (as
// used by GCC and CLang).
@@ -289,7 +289,7 @@ mi_decl_weak int reallocarr(void* p, size_t count, size_t size) { return mi_r
void __libc_free(void* p) MI_FORWARD0(mi_free, p)
void* __libc_memalign(size_t alignment, size_t size) { return mi_memalign(alignment, size); }
-#elif defined(__GLIBC__) && defined(__linux__)
+#elif defined(__linux__) //defined(__GLIBC__) && defined(__linux__)
// forward __libc interface (needed for glibc-based Linux distributions)
void* __libc_malloc(size_t size) MI_FORWARD1(mi_malloc,size)
void* __libc_calloc(size_t count, size_t size) MI_FORWARD2(mi_calloc,count,size)
#!/bin/bash
set -euo pipefail
echo "Looking for libc.a in current directory..."
LIBC_PATH="./libc.a"
if [ ! -f "$LIBC_PATH" ]; then
echo "Error: libc.a not found in the current directory."
exit 1
fi
echo "Backing up original libc.a to libc.a.bak"
cp "$LIBC_PATH" libc.a.bak
echo "Building mimalloc static library..."
if [ ! -d mimalloc ]; then
echo "Cloning mimalloc..."
git clone https://github.com/microsoft/mimalloc
else
echo "Using existing mimalloc directory."
fi
cd mimalloc
git fetch --tags
git checkout tags/v2.1.7
# Clean up any previous modifications
git reset --hard
git clean -fd
# Check if patch is already applied
if git apply --check ../mimalloc_v2.1.7.diff 2>/dev/null; then
echo "Applying patch..."
git apply ../mimalloc_v2.1.7.diff
else
echo "Patch already applied or incompatible. Skipping patch step."
fi
cmake -Bout -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DMI_BUILD_SHARED=OFF -DMI_BUILD_OBJECT=OFF -DMI_BUILD_TESTS=OFF .
cmake --build out
echo "Patching musl libc.a with mimalloc..."
cp ./out/libmimalloc.a .
cp "$OLDPWD/libc.a" .
# Remove musl malloc-related object files
for symbol in aligned_alloc calloc donate free free libc_calloc lite_malloc malloc malloc_usable_size memalign posix_memalign realloc realloc reallocarray valloc strdup strndup; do
llvm-ar -d libc.a "${symbol}.lo" || true
done
# Verify removals
for symbol in aligned_alloc calloc donate free libc_calloc lite_malloc malloc malloc_usable_size memalign posix_memalign realloc reallocarray valloc strdup strndup; do
if llvm-ar -t libc.a | grep -q "${symbol}.lo"; then
echo "Warning: ${symbol}.lo still exists in libc.a"
fi
done
# Inject mimalloc object files
llvm-ar -x libmimalloc.a
llvm-ar -r libc.a *.o
echo "Replacing original libc.a with patched version..."
cp libc.a "$OLDPWD/libc.a"
cd "$OLDPWD"
rm -rf mimalloc
echo "✅ Done! libc.a has been patched with mimalloc."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment