Support jemalloc as the default allocator on Linux (#7250)

Add jemalloc as an alternative malloc implementation for the Verilator
binary. When both tcmalloc and jemalloc are available, jemalloc is
preferred due to its better performance on RTLMeter.

The new --enable-jemalloc flag (default=check) mirrors the existing
--enable-tcmalloc behavior: auto-detected at configure time, supports
both static and dynamic linking, and is disabled when --enable-dev-asan
is active.
This commit is contained in:
Yangyu Chen 2026-03-14 05:08:15 +08:00 committed by GitHub
parent 7cd49a8028
commit bb5a9dc247
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 78 additions and 12 deletions

View File

@ -36,8 +36,8 @@ jobs:
echo "path-exclude /usr/share/info/*" | sudo tee -a /etc/dpkg/dpkg.cfg.d/01_nodoc
sudo apt update || \
sudo apt update
sudo apt install ccache mold help2man libfl-dev libgoogle-perftools-dev libsystemc-dev || \
sudo apt install ccache mold help2man libfl-dev libgoogle-perftools-dev libsystemc-dev
sudo apt install ccache mold help2man libfl-dev libjemalloc-dev libsystemc-dev || \
sudo apt install ccache mold help2man libfl-dev libjemalloc-dev libsystemc-dev
- name: Use saved ccache
uses: actions/cache@v5

View File

@ -60,8 +60,8 @@ jobs:
echo "path-exclude /usr/share/info/*" | sudo tee -a /etc/dpkg/dpkg.cfg.d/01_nodoc
sudo apt update || \
sudo apt update
sudo apt install ccache mold libfl-dev libgoogle-perftools-dev libsystemc-dev || \
sudo apt install ccache mold libfl-dev libgoogle-perftools-dev libsystemc-dev
sudo apt install ccache mold libfl-dev libjemalloc-dev libsystemc-dev || \
sudo apt install ccache mold libfl-dev libjemalloc-dev libsystemc-dev
- name: Download Verilator installation archive
uses: actions/download-artifact@v8

View File

@ -60,8 +60,8 @@ if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then
sudo apt-get install ccache help2man libfl-dev
if [[ ! "$CI_RUNS_ON" =~ "ubuntu-22.04" ]]; then
# Some conflict of libunwind verison on 22.04, can live without it for now
sudo apt-get install libgoogle-perftools-dev ||
sudo apt-get install libgoogle-perftools-dev
sudo apt-get install libjemalloc-dev ||
sudo apt-get install libjemalloc-dev
fi
if [[ "$CI_RUNS_ON" =~ "ubuntu-20.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-22.04" ]] || [[ "$CI_RUNS_ON" =~ "ubuntu-24.04" ]]; then
sudo apt-get install libsystemc libsystemc-dev ||

View File

@ -37,7 +37,7 @@ RUN apt-get update \
libfl2 \
libfl-dev \
libclang-rt-18-dev \
libgoogle-perftools-dev \
libjemalloc-dev \
libsystemc \
libsystemc-dev \
numactl \

View File

@ -22,7 +22,7 @@ RUN apt-get update \
help2man \
libfl2 \
libfl-dev \
libgoogle-perftools-dev \
libjemalloc-dev \
numactl \
perl \
perl-doc \

View File

@ -64,8 +64,8 @@ AC_ARG_ENABLE([dev-asan],
[AS_HELP_STRING([--enable-dev-asan],
[Enable compiling Verilator with ASAN
AddressSanitizer for memory error detection.
This disables tcmalloc. Does not affect
Verilated models using ASAN.])],
This disables tcmalloc and jemalloc. Does not
affect Verilated models using ASAN.])],
[case "${enableval}" in
yes) CFG_WITH_DEV_ASAN=yes ;;
no) CFG_WITH_DEV_ASAN=no ;;
@ -93,6 +93,27 @@ else
AC_MSG_RESULT($CFG_WITH_TCMALLOC)
fi
# Flag to enable linking Verilator with jemalloc if available
AC_MSG_CHECKING(whether to use jemalloc)
AC_ARG_ENABLE([jemalloc],
[AS_HELP_STRING([--enable-jemalloc],
[Use libjemalloc for faster dynamic memory
management in Verilator binary. Preferred over
tcmalloc when both are available
@<:@default=check@:>@])],
[case "${enableval}" in
yes) CFG_WITH_JEMALLOC=yes ;;
no) CFG_WITH_JEMALLOC=no ;;
*) AC_MSG_ERROR([bad value '${enableval}' for --enable-jemalloc]) ;;
esac],
[CFG_WITH_JEMALLOC=check;])
if test "$CFG_WITH_DEV_ASAN" = "yes"; then
CFG_WITH_JEMALLOC=no
AC_MSG_RESULT("disabled by --enable-dev-asan")
else
AC_MSG_RESULT($CFG_WITH_JEMALLOC)
fi
# Flag to enable code coverage build with gcov
AC_MSG_CHECKING(whether to build for gcov code coverage collection)
AC_ARG_ENABLE([dev-gcov],
@ -567,8 +588,10 @@ if test "$CFG_ENABLE_PARTIAL_STATIC" = "yes"; then
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -static-libstdc++)
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -Xlinker -gc-sections)
LTCMALLOC="-Wl,--whole-archive -l:libtcmalloc_minimal.a -Wl,--no-whole-archive"
LJEMALLOC="-Wl,--whole-archive -l:libjemalloc.a -Wl,--no-whole-archive"
else
LTCMALLOC=-ltcmalloc_minimal
LJEMALLOC=-ljemalloc
fi
AC_SUBST(CFG_LDFLAGS_SRC)
AC_SUBST(CFG_LDFLAGS_VERILATED)
@ -584,11 +607,38 @@ _MY_LDLIBS_CHECK_OPT(CFG_LIBS, -latomic)
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -lbcrypt)
_MY_LDLIBS_CHECK_OPT(CFG_LIBS, -lpsapi)
# Check if jemalloc is available based on --enable-jemalloc
# jemalloc is preferred over tcmalloc when both are available
CFG_HAVE_JEMALLOC=no
_MY_LDLIBS_CHECK_IFELSE(
$LJEMALLOC,
[if test "$CFG_WITH_JEMALLOC" != "no"; then
CFG_LIBS="$LJEMALLOC $CFG_LIBS";
CFG_HAVE_JEMALLOC=yes;
# If using jemalloc, add some extra options to make the compiler not assume
# it is using its own versions of the standard library functions
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-malloc)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-calloc)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-realloc)
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-free)
AC_DEFINE([HAVE_JEMALLOC],[1],[Defined if have jemalloc])
fi],
[if test "$CFG_WITH_JEMALLOC" = "yes"; then
AC_MSG_ERROR([--enable-jemalloc was given but test for ${LJEMALLOC} failed])
fi])
AC_SUBST(HAVE_JEMALLOC)
# Check if tcmalloc is available based on --enable-tcmalloc
# Only use tcmalloc if jemalloc was not found/enabled
if test "$CFG_HAVE_JEMALLOC" = "yes"; then
AC_MSG_NOTICE([jemalloc found, skipping tcmalloc check])
else
CFG_HAVE_TCMALLOC=no
_MY_LDLIBS_CHECK_IFELSE(
$LTCMALLOC,
[if test "$CFG_WITH_TCMALLOC" != "no"; then
CFG_LIBS="$LTCMALLOC $CFG_LIBS";
CFG_HAVE_TCMALLOC=yes;
# If using tcmalloc, add some extra options to make the compiler not assume
# it is using its own versions of the standard library functions
_MY_CXX_CHECK_OPT(CFG_CXXFLAGS_SRC,-fno-builtin-malloc)
@ -600,6 +650,7 @@ _MY_LDLIBS_CHECK_IFELSE(
[if test "$CFG_WITH_TCMALLOC" = "yes"; then
AC_MSG_ERROR([--enable-tcmalloc was given but test for ${LTCMALLOC} failed])
fi])
fi
AC_SUBST(HAVE_TCMALLOC)
AC_SUBST(CFG_LIBS)

View File

@ -61,7 +61,7 @@ In brief, to install from git:
# Prerequisites:
#sudo apt-get install git help2man perl python3 make autoconf g++ flex bison ccache
#sudo apt-get install libgoogle-perftools-dev numactl perl-doc
#sudo apt-get install libgoogle-perftools-dev libjemalloc-dev numactl perl-doc
#sudo apt-get install libfl2 # Ubuntu only (ignore if gives error)
#sudo apt-get install libfl-dev # Ubuntu only (ignore if gives error)
#sudo apt-get install zlibc zlib1g zlib1g-dev # Ubuntu only (ignore if gives error)
@ -144,7 +144,7 @@ installed for good performance:
sudo apt-get install ccache # If present at build, needed for run
sudo apt-get install mold # If present at build, needed for run
sudo apt-get install libgoogle-perftools-dev numactl
sudo apt-get install libjemalloc-dev numactl
To build Verilator you will need to install these packages; these do not
need to be present to run Verilator:

View File

@ -57,6 +57,9 @@ VL_DEFINE_DEBUG_FUNCTIONS;
#ifdef HAVE_TCMALLOC
#include <gperftools/malloc_extension.h>
#endif
#ifdef HAVE_JEMALLOC
#include <jemalloc/jemalloc.h>
#endif
// clang-format off
#if defined(_WIN32) || defined(__MINGW32__)
@ -413,6 +416,18 @@ void V3Os::releaseMemory() {
#ifdef HAVE_TCMALLOC
MallocExtension::instance()->ReleaseFreeMemory();
#endif
#ifdef HAVE_JEMALLOC
// Purge all unused dirty pages across all arenas
unsigned narenas = 0;
size_t sz = sizeof(narenas);
if (mallctl("arenas.narenas", &narenas, &sz, nullptr, 0)) {
return; // Failed to get number of arenas, give up
}
char buf[64];
// Index equal to narenas represents all arenas
VL_SNPRINTF(buf, sizeof(buf), "arena.%u.purge", narenas);
mallctl(buf, nullptr, nullptr, nullptr, 0);
#endif
}
//######################################################################