mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-23 21:23:06 +00:00
Compare commits
13 Commits
afeda129b0
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
262f08301a | ||
|
|
04aad97faa | ||
|
|
80c8fcb4f9 | ||
|
|
7aab2c0e01 | ||
|
|
349740cbd2 | ||
|
|
90567ced21 | ||
|
|
dec5668b48 | ||
|
|
30b1a41042 | ||
|
|
68fe1be1ad | ||
|
|
184f304dd3 | ||
|
|
dfe3a2ed5f | ||
|
|
d0705543e0 | ||
|
|
c597d73778 |
38
.github/workflows/linux-ci.yml
vendored
38
.github/workflows/linux-ci.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -124,7 +124,7 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: clang
|
CC: clang
|
||||||
CXX: clang++
|
CXX: clang++
|
||||||
CONFIGURE_FLAGS: "--enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes"
|
||||||
- env:
|
- env:
|
||||||
CC: clang
|
CC: clang
|
||||||
@@ -193,7 +193,7 @@ jobs:
|
|||||||
CXX: g++
|
CXX: g++
|
||||||
CROSS_COMPILE_32BIT: yes
|
CROSS_COMPILE_32BIT: yes
|
||||||
COMPILER_FLAGS: -m32
|
COMPILER_FLAGS: -m32
|
||||||
CONFIGURE_FLAGS: "--enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -251,7 +251,7 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--enable-debug --enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--enable-debug --enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -296,7 +296,7 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--enable-prof --enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--enable-prof --enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -336,7 +336,7 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--disable-stats --enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--disable-stats --enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -371,7 +371,7 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--disable-libdl --enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--disable-libdl --enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -401,7 +401,7 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--enable-opt-safety-checks --enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--enable-opt-safety-checks --enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -426,7 +426,7 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--with-lg-page=16 --enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--with-lg-page=16 --enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -451,22 +451,22 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--enable-prof --enable-prof-frameptr --with-malloc-conf=tcache:false"
|
CONFIGURE_FLAGS: "--enable-prof --enable-prof-libunwind --with-malloc-conf=tcache:false"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--enable-prof --enable-prof-frameptr --with-malloc-conf=dss:primary"
|
CONFIGURE_FLAGS: "--enable-prof --enable-prof-libunwind --with-malloc-conf=dss:primary"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--enable-prof --enable-prof-frameptr --with-malloc-conf=percpu_arena:percpu"
|
CONFIGURE_FLAGS: "--enable-prof --enable-prof-libunwind --with-malloc-conf=percpu_arena:percpu"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--enable-prof --enable-prof-frameptr --with-malloc-conf=background_thread:true"
|
CONFIGURE_FLAGS: "--enable-prof --enable-prof-libunwind --with-malloc-conf=background_thread:true"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -547,6 +547,11 @@ jobs:
|
|||||||
echo "=== CPU Info ==="
|
echo "=== CPU Info ==="
|
||||||
lscpu | grep -E "Architecture|CPU op-mode|Byte Order|CPU\(s\):" || true
|
lscpu | grep -E "Architecture|CPU op-mode|Byte Order|CPU\(s\):" || true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libunwind-dev
|
||||||
|
|
||||||
- name: Install dependencies (32-bit)
|
- name: Install dependencies (32-bit)
|
||||||
if: matrix.env.CROSS_COMPILE_32BIT == 'yes'
|
if: matrix.env.CROSS_COMPILE_32BIT == 'yes'
|
||||||
run: |
|
run: |
|
||||||
@@ -635,7 +640,7 @@ jobs:
|
|||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
CONFIGURE_FLAGS: "--enable-prof --enable-prof-frameptr"
|
CONFIGURE_FLAGS: "--enable-prof --enable-prof-libunwind"
|
||||||
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
EXTRA_CFLAGS: "-Werror -Wno-array-bounds"
|
||||||
- env:
|
- env:
|
||||||
CC: gcc
|
CC: gcc
|
||||||
@@ -681,6 +686,11 @@ jobs:
|
|||||||
echo "=== CPU Info ==="
|
echo "=== CPU Info ==="
|
||||||
lscpu | grep -E "Architecture|CPU op-mode|Byte Order|CPU\(s\):" || true
|
lscpu | grep -E "Architecture|CPU op-mode|Byte Order|CPU\(s\):" || true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libunwind-dev
|
||||||
|
|
||||||
- name: Install dependencies (32-bit)
|
- name: Install dependencies (32-bit)
|
||||||
if: matrix.env.CROSS_COMPILE_32BIT == 'yes'
|
if: matrix.env.CROSS_COMPILE_32BIT == 'yes'
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
28
.travis.yml
28
.travis.yml
@@ -39,7 +39,7 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
@@ -75,7 +75,7 @@ jobs:
|
|||||||
env: CC=clang CXX=clang++ CONFIGURE_FLAGS="--with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes"
|
env: CC=clang CXX=clang++ CONFIGURE_FLAGS="--with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=clang CXX=clang++ CONFIGURE_FLAGS="--enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes"
|
env: CC=clang CXX=clang++ CONFIGURE_FLAGS="--enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=clang CXX=clang++ CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes"
|
env: CC=clang CXX=clang++ CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds -Wno-unknown-warning-option -Wno-ignored-attributes"
|
||||||
@@ -108,7 +108,7 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CROSS_COMPILE_32BIT=yes COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CROSS_COMPILE_32BIT=yes COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CROSS_COMPILE_32BIT=yes COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CROSS_COMPILE_32BIT=yes COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CROSS_COMPILE_32BIT=yes COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CROSS_COMPILE_32BIT=yes COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
@@ -138,7 +138,7 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-debug --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-debug --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-debug --enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-debug --enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-debug --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-debug --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
@@ -165,7 +165,7 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
@@ -189,7 +189,7 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-stats --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-stats --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-stats --enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-stats --enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-stats --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-stats --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
@@ -210,7 +210,7 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-libdl --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-libdl --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-libdl --enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-libdl --enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-libdl --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--disable-libdl --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
@@ -228,7 +228,7 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-opt-safety-checks --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-opt-safety-checks --with-lg-page=16" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-opt-safety-checks --enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-opt-safety-checks --enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-opt-safety-checks --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-opt-safety-checks --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
@@ -243,7 +243,7 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-opt-safety-checks --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-opt-safety-checks --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16 --enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16 --enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16 --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16 --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
@@ -258,16 +258,16 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16 --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16 --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-frameptr --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-libunwind --with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-frameptr --with-malloc-conf=dss:primary" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-libunwind --with-malloc-conf=dss:primary" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-frameptr --with-malloc-conf=percpu_arena:percpu" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-libunwind --with-malloc-conf=percpu_arena:percpu" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-frameptr --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-libunwind --with-malloc-conf=background_thread:true" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: amd64
|
arch: amd64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-malloc-conf=tcache:false,dss:primary" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-malloc-conf=tcache:false,dss:primary" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
@@ -315,7 +315,7 @@ jobs:
|
|||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16 --with-lg-hugepage=29" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-lg-page=16 --with-lg-hugepage=29" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: arm64
|
arch: arm64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-frameptr" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--enable-prof --enable-prof-libunwind" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
- os: linux
|
- os: linux
|
||||||
arch: arm64
|
arch: arm64
|
||||||
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
env: CC=gcc CXX=g++ CONFIGURE_FLAGS="--with-malloc-conf=tcache:false" EXTRA_CFLAGS="-Werror -Wno-array-bounds"
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ any of the following arguments (not a definitive list) to 'configure':
|
|||||||
in the following list that appears to function correctly:
|
in the following list that appears to function correctly:
|
||||||
|
|
||||||
+ libunwind (requires --enable-prof-libunwind)
|
+ libunwind (requires --enable-prof-libunwind)
|
||||||
+ frame pointer (requires --enable-prof-frameptr)
|
|
||||||
+ libgcc (unless --disable-prof-libgcc)
|
+ libgcc (unless --disable-prof-libgcc)
|
||||||
+ gcc intrinsics (unless --disable-prof-gcc)
|
+ gcc intrinsics (unless --disable-prof-gcc)
|
||||||
|
|
||||||
@@ -148,12 +147,6 @@ any of the following arguments (not a definitive list) to 'configure':
|
|||||||
Use the libunwind library (http://www.nongnu.org/libunwind/) for stack
|
Use the libunwind library (http://www.nongnu.org/libunwind/) for stack
|
||||||
backtracing.
|
backtracing.
|
||||||
|
|
||||||
* `--enable-prof-frameptr`
|
|
||||||
|
|
||||||
Use the optimized frame pointer unwinder for stack backtracing. Safe
|
|
||||||
to use in mixed code (with and without frame pointers) - but requires
|
|
||||||
frame pointers to produce meaningful stacks. Linux only.
|
|
||||||
|
|
||||||
* `--disable-prof-libgcc`
|
* `--disable-prof-libgcc`
|
||||||
|
|
||||||
Disable the use of libgcc's backtracing functionality.
|
Disable the use of libgcc's backtracing functionality.
|
||||||
|
|||||||
@@ -146,7 +146,6 @@ C_SRCS := $(srcroot)src/jemalloc.c \
|
|||||||
$(srcroot)src/prof_data.c \
|
$(srcroot)src/prof_data.c \
|
||||||
$(srcroot)src/prof_log.c \
|
$(srcroot)src/prof_log.c \
|
||||||
$(srcroot)src/prof_recent.c \
|
$(srcroot)src/prof_recent.c \
|
||||||
$(srcroot)src/prof_stack_range.c \
|
|
||||||
$(srcroot)src/prof_stats.c \
|
$(srcroot)src/prof_stats.c \
|
||||||
$(srcroot)src/prof_sys.c \
|
$(srcroot)src/prof_sys.c \
|
||||||
$(srcroot)src/psset.c \
|
$(srcroot)src/psset.c \
|
||||||
|
|||||||
28
configure.ac
28
configure.ac
@@ -1557,33 +1557,6 @@ if test "x$backtrace_method" = "x" -a "x$enable_prof_libunwind" = "x1" ; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test `uname -s` = "Linux"
|
|
||||||
then
|
|
||||||
AC_ARG_ENABLE([prof-frameptr],
|
|
||||||
[AS_HELP_STRING([--enable-prof-frameptr], [Use optimized frame pointer unwinder for backtracing (Linux only)])],
|
|
||||||
[if test "x$enable_prof_frameptr" = "xno" ; then
|
|
||||||
enable_prof_frameptr="0"
|
|
||||||
else
|
|
||||||
enable_prof_frameptr="1"
|
|
||||||
if test "x$enable_prof" = "x0" ; then
|
|
||||||
AC_MSG_ERROR([--enable-prof-frameptr should only be used with --enable-prof])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
],
|
|
||||||
[enable_prof_frameptr="0"]
|
|
||||||
)
|
|
||||||
if test "x$backtrace_method" = "x" -a "x$enable_prof_frameptr" = "x1" \
|
|
||||||
-a "x$GCC" = "xyes" ; then
|
|
||||||
JE_CFLAGS_ADD([-fno-omit-frame-pointer])
|
|
||||||
backtrace_method="frame pointer linux"
|
|
||||||
AC_DEFINE([JEMALLOC_PROF_FRAME_POINTER], [ ], [ ])
|
|
||||||
else
|
|
||||||
enable_prof_frameptr="0"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
enable_prof_frameptr="0"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_ARG_ENABLE([prof-libgcc],
|
AC_ARG_ENABLE([prof-libgcc],
|
||||||
[AS_HELP_STRING([--disable-prof-libgcc],
|
[AS_HELP_STRING([--disable-prof-libgcc],
|
||||||
[Do not use libgcc for backtracing])],
|
[Do not use libgcc for backtracing])],
|
||||||
@@ -3186,7 +3159,6 @@ AC_MSG_RESULT([user_config : ${enable_user_config}])
|
|||||||
AC_MSG_RESULT([experimental_smallocx : ${enable_experimental_smallocx}])
|
AC_MSG_RESULT([experimental_smallocx : ${enable_experimental_smallocx}])
|
||||||
AC_MSG_RESULT([prof : ${enable_prof}])
|
AC_MSG_RESULT([prof : ${enable_prof}])
|
||||||
AC_MSG_RESULT([prof-libunwind : ${enable_prof_libunwind}])
|
AC_MSG_RESULT([prof-libunwind : ${enable_prof_libunwind}])
|
||||||
AC_MSG_RESULT([prof-frameptr : ${enable_prof_frameptr}])
|
|
||||||
AC_MSG_RESULT([prof-libgcc : ${enable_prof_libgcc}])
|
AC_MSG_RESULT([prof-libgcc : ${enable_prof_libgcc}])
|
||||||
AC_MSG_RESULT([prof-gcc : ${enable_prof_gcc}])
|
AC_MSG_RESULT([prof-gcc : ${enable_prof_gcc}])
|
||||||
AC_MSG_RESULT([fill : ${enable_fill}])
|
AC_MSG_RESULT([fill : ${enable_fill}])
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ struct emitter_col_s {
|
|||||||
ssize_t ssize_val;
|
ssize_t ssize_val;
|
||||||
const char *str_val;
|
const char *str_val;
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
|
* Optional JSON key. When set, emitter_row() emits this column as a
|
||||||
|
* "json_key": value pair in JSON mode; columns left NULL are table-only.
|
||||||
|
*/
|
||||||
|
const char *json_key;
|
||||||
|
|
||||||
/* Filled in by initialization. */
|
/* Filled in by initialization. */
|
||||||
ql_elm(emitter_col_t) link;
|
ql_elm(emitter_col_t) link;
|
||||||
@@ -79,6 +84,8 @@ struct emitter_s {
|
|||||||
bool item_at_depth;
|
bool item_at_depth;
|
||||||
/* True if we emitted a key and will emit corresponding value next. */
|
/* True if we emitted a key and will emit corresponding value next. */
|
||||||
bool emitted_key;
|
bool emitted_key;
|
||||||
|
/* Gap-collapsing state for the emitter_table_sparse_row() bracket. */
|
||||||
|
bool table_sparse_in_gap;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
@@ -270,6 +277,7 @@ emitter_init(emitter_t *emitter, emitter_output_t emitter_output,
|
|||||||
emitter->item_at_depth = false;
|
emitter->item_at_depth = false;
|
||||||
emitter->emitted_key = false;
|
emitter->emitted_key = false;
|
||||||
emitter->nesting_depth = 0;
|
emitter->nesting_depth = 0;
|
||||||
|
emitter->table_sparse_in_gap = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@@ -447,6 +455,46 @@ static inline void
|
|||||||
emitter_col_init(emitter_col_t *col, emitter_row_t *row) {
|
emitter_col_init(emitter_col_t *col, emitter_row_t *row) {
|
||||||
ql_elm_new(col, link);
|
ql_elm_new(col, link);
|
||||||
ql_tail_insert(&row->cols, col, link);
|
ql_tail_insert(&row->cols, col, link);
|
||||||
|
col->json_key = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sparse table rows. Some tables have one row per size class but most rows
|
||||||
|
* are all-zero; in table output those runs are collapsed to a single "---"
|
||||||
|
* separator. Bracket such a table with emitter_table_sparse_begin() /
|
||||||
|
* _end() and emit each row with emitter_table_sparse_row(), passing whether
|
||||||
|
* that row is a gap (all-zero). The emitter prints the separator on a
|
||||||
|
* gap->non-gap transition and at a trailing gap, and suppresses the gap rows
|
||||||
|
* themselves; callers no longer track gap state. Table output only -- a
|
||||||
|
* no-op in JSON, where callers emit every row's object separately.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
emitter_table_sparse_begin(emitter_t *emitter) {
|
||||||
|
emitter->table_sparse_in_gap = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
emitter_table_sparse_row(emitter_t *emitter, emitter_row_t *row, bool is_gap) {
|
||||||
|
if (emitter->output != emitter_output_table) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool prev_in_gap = emitter->table_sparse_in_gap;
|
||||||
|
emitter->table_sparse_in_gap = is_gap;
|
||||||
|
if (prev_in_gap && !is_gap) {
|
||||||
|
emitter_printf(emitter, " ---\n");
|
||||||
|
}
|
||||||
|
if (!is_gap) {
|
||||||
|
emitter_table_row(emitter, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
emitter_table_sparse_end(emitter_t *emitter) {
|
||||||
|
if (emitter->output == emitter_output_table
|
||||||
|
&& emitter->table_sparse_in_gap) {
|
||||||
|
emitter_printf(emitter, " ---\n");
|
||||||
|
}
|
||||||
|
emitter->table_sparse_in_gap = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@@ -499,6 +547,142 @@ emitter_dict_end(emitter_t *emitter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Internal: emit a row's json-keyed columns as JSON kvs, in column order. */
|
||||||
|
static inline void
|
||||||
|
emitter_row_json(emitter_t *emitter, emitter_row_t *row) {
|
||||||
|
emitter_col_t *col;
|
||||||
|
ql_foreach (col, &row->cols, link) {
|
||||||
|
if (col->json_key != NULL) {
|
||||||
|
emitter_json_kv(emitter, col->json_key, col->type,
|
||||||
|
(const void *)&col->bool_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit a row of columns to whichever format is active. In table mode, prints
|
||||||
|
* the aligned table row (see emitter_table_row). In JSON mode, emits each
|
||||||
|
* column that has a non-NULL json_key as a "json_key": value pair, in column
|
||||||
|
* order (columns without a json_key are table-only). This lets a caller
|
||||||
|
* describe a row once and render it to either format. For JSON objects (one
|
||||||
|
* per row), wrap the call in emitter_json_object_begin()/_end().
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
emitter_row(emitter_t *emitter, emitter_row_t *row) {
|
||||||
|
emitter_table_row(emitter, row);
|
||||||
|
if (emitter_outputs_json(emitter)) {
|
||||||
|
emitter_row_json(emitter, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sparse counterpart of emitter_row() for per-size-class tables: the table
|
||||||
|
* side collapses all-zero ("gap") rows (see emitter_table_sparse_row), while
|
||||||
|
* the JSON side still emits every row's json-keyed columns. Bracket the loop
|
||||||
|
* with emitter_table_sparse_begin()/_end(), and wrap each row's JSON in
|
||||||
|
* emitter_json_object_begin()/_end() when the rows form an array of objects.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
emitter_sparse_row(emitter_t *emitter, emitter_row_t *row, bool is_gap) {
|
||||||
|
emitter_table_sparse_row(emitter, row, is_gap);
|
||||||
|
if (emitter_outputs_json(emitter)) {
|
||||||
|
emitter_row_json(emitter, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Descriptor-driven column tables. A descriptor array defines table and JSON
|
||||||
|
* order; columns with a NULL json_key are table-only. The getter lets one
|
||||||
|
* engine serve different row types while keeping derived values (rates,
|
||||||
|
* utilization, and so on) with the table-specific code. A column is active
|
||||||
|
* when all its required_flags are present in the active_flags supplied by the
|
||||||
|
* caller; the emitter assigns no domain-specific meaning to those bits.
|
||||||
|
*/
|
||||||
|
typedef struct emitter_col_desc_s emitter_col_desc_t;
|
||||||
|
struct emitter_col_desc_s {
|
||||||
|
const char *json_key;
|
||||||
|
const char *table_label;
|
||||||
|
emitter_justify_t justify;
|
||||||
|
int width;
|
||||||
|
emitter_type_t type;
|
||||||
|
unsigned required_flags;
|
||||||
|
void (*get)(const void *row, emitter_col_t *col);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
emitter_col_desc_active(const emitter_col_desc_t *desc,
|
||||||
|
unsigned active_flags) {
|
||||||
|
return (desc->required_flags & ~active_flags) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
emitter_col_table_build(const emitter_col_desc_t *descs, size_t ndescs,
|
||||||
|
unsigned active_flags, emitter_row_t *row, emitter_col_t *cols,
|
||||||
|
emitter_row_t *header_row, emitter_col_t *header_cols) {
|
||||||
|
emitter_row_init(row);
|
||||||
|
emitter_row_init(header_row);
|
||||||
|
for (size_t i = 0; i < ndescs; i++) {
|
||||||
|
if (!emitter_col_desc_active(&descs[i], active_flags)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter_col_init(&cols[i], row);
|
||||||
|
cols[i].justify = descs[i].justify;
|
||||||
|
cols[i].width = descs[i].width;
|
||||||
|
cols[i].type = descs[i].type;
|
||||||
|
|
||||||
|
emitter_col_init(&header_cols[i], header_row);
|
||||||
|
header_cols[i].justify = descs[i].justify;
|
||||||
|
header_cols[i].width = descs[i].width;
|
||||||
|
header_cols[i].type = emitter_type_title;
|
||||||
|
header_cols[i].str_val = descs[i].table_label != NULL
|
||||||
|
? descs[i].table_label : descs[i].json_key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
emitter_col_table_header(emitter_t *emitter, emitter_row_t *header_row,
|
||||||
|
emitter_col_t *first_header_col, const char *table_prefix,
|
||||||
|
const char *json_key) {
|
||||||
|
first_header_col->width -= (int)strlen(table_prefix);
|
||||||
|
emitter_table_printf(emitter, "%s", table_prefix);
|
||||||
|
emitter_table_row(emitter, header_row);
|
||||||
|
emitter_json_array_kv_begin(emitter, json_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
emitter_col_table_fill(const emitter_col_desc_t *descs, size_t ndescs,
|
||||||
|
unsigned active_flags, emitter_col_t *cols, const void *row) {
|
||||||
|
for (size_t i = 0; i < ndescs; i++) {
|
||||||
|
if (!emitter_col_desc_active(&descs[i], active_flags)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cols[i].type = descs[i].type;
|
||||||
|
descs[i].get(row, &cols[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
emitter_col_table_emit_json(emitter_t *emitter,
|
||||||
|
const emitter_col_desc_t *descs, size_t ndescs, unsigned active_flags,
|
||||||
|
emitter_col_t *cols) {
|
||||||
|
if (!emitter_outputs_json(emitter)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < ndescs; i++) {
|
||||||
|
const emitter_col_desc_t *desc = &descs[i];
|
||||||
|
if (!emitter_col_desc_active(desc, active_flags)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (desc->json_key != NULL) {
|
||||||
|
emitter_type_t json_type = cols[i].type == emitter_type_title
|
||||||
|
? emitter_type_string : cols[i].type;
|
||||||
|
emitter_json_kv(emitter, desc->json_key, json_type,
|
||||||
|
(const void *)&cols[i].bool_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
emitter_begin(emitter_t *emitter) {
|
emitter_begin(emitter_t *emitter) {
|
||||||
if (emitter_outputs_json(emitter)) {
|
if (emitter_outputs_json(emitter)) {
|
||||||
|
|||||||
@@ -175,9 +175,6 @@
|
|||||||
/* Use gcc intrinsics for profile backtracing if defined. */
|
/* Use gcc intrinsics for profile backtracing if defined. */
|
||||||
#undef JEMALLOC_PROF_GCC
|
#undef JEMALLOC_PROF_GCC
|
||||||
|
|
||||||
/* Use frame pointer for profile backtracing if defined. Linux only. */
|
|
||||||
#undef JEMALLOC_PROF_FRAME_POINTER
|
|
||||||
|
|
||||||
/* JEMALLOC_PAGEID enabled page id */
|
/* JEMALLOC_PAGEID enabled page id */
|
||||||
#undef JEMALLOC_PAGEID
|
#undef JEMALLOC_PAGEID
|
||||||
|
|
||||||
|
|||||||
@@ -130,13 +130,6 @@ static const bool config_prof_libunwind =
|
|||||||
false
|
false
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
static const bool config_prof_frameptr =
|
|
||||||
#ifdef JEMALLOC_PROF_FRAME_POINTER
|
|
||||||
true
|
|
||||||
#else
|
|
||||||
false
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
static const bool maps_coalesce =
|
static const bool maps_coalesce =
|
||||||
#ifdef JEMALLOC_MAPS_COALESCE
|
#ifdef JEMALLOC_MAPS_COALESCE
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -89,13 +89,4 @@ malloc_close(int fd) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline off_t
|
|
||||||
malloc_lseek(int fd, off_t offset, int whence) {
|
|
||||||
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_lseek)
|
|
||||||
return (off_t)syscall(SYS_lseek, fd, offset, whence);
|
|
||||||
#else
|
|
||||||
return lseek(fd, offset, whence);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* JEMALLOC_INTERNAL_MALLOC_IO_H */
|
#endif /* JEMALLOC_INTERNAL_MALLOC_IO_H */
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ void prof_fdump_impl(tsd_t *tsd);
|
|||||||
void prof_idump_impl(tsd_t *tsd);
|
void prof_idump_impl(tsd_t *tsd);
|
||||||
bool prof_mdump_impl(tsd_t *tsd, const char *filename);
|
bool prof_mdump_impl(tsd_t *tsd, const char *filename);
|
||||||
void prof_gdump_impl(tsd_t *tsd);
|
void prof_gdump_impl(tsd_t *tsd);
|
||||||
int prof_thread_stack_range(uintptr_t fp, uintptr_t *low, uintptr_t *high);
|
|
||||||
|
|
||||||
/* Used in unit tests. */
|
/* Used in unit tests. */
|
||||||
typedef int(prof_sys_thread_name_read_t)(char *buf, size_t limit);
|
typedef int(prof_sys_thread_name_read_t)(char *buf, size_t limit);
|
||||||
|
|||||||
340
include/jemalloc/internal/stats_internal.h
Normal file
340
include/jemalloc/internal/stats_internal.h
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
#ifndef JEMALLOC_INTERNAL_STATS_INTERNAL_H
|
||||||
|
#define JEMALLOC_INTERNAL_STATS_INTERNAL_H
|
||||||
|
|
||||||
|
#include "jemalloc/internal/jemalloc_preamble.h"
|
||||||
|
#include "jemalloc/internal/arena.h" /* ARENA_NAME_LEN */
|
||||||
|
#include "jemalloc/internal/assert.h"
|
||||||
|
#include "jemalloc/internal/ctl.h"
|
||||||
|
#include "jemalloc/internal/emitter.h"
|
||||||
|
#include "jemalloc/internal/prof_stats.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal implementation support for src/stats.c only -- do NOT include from
|
||||||
|
* other translation units.
|
||||||
|
*
|
||||||
|
* This header holds noisy local scaffolding for malloc_stats_print(): ctl
|
||||||
|
* gather plumbing, gather structs, emitter table-column helpers, and option
|
||||||
|
* list helpers. It is deliberately not a reusable stats-gather API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CTL_GET(n, v, t) \
|
||||||
|
do { \
|
||||||
|
size_t sz = sizeof(t); \
|
||||||
|
xmallctl(n, (void *)v, &sz, NULL, 0); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CTL_LEAF_PREPARE(mib, miblen, name) \
|
||||||
|
do { \
|
||||||
|
assert(miblen < CTL_MAX_DEPTH); \
|
||||||
|
size_t miblen_new = CTL_MAX_DEPTH; \
|
||||||
|
xmallctlmibnametomib(mib, miblen, name, &miblen_new); \
|
||||||
|
assert(miblen_new > miblen); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CTL_LEAF(mib, miblen, leaf, v, t) \
|
||||||
|
do { \
|
||||||
|
assert(miblen < CTL_MAX_DEPTH); \
|
||||||
|
size_t miblen_new = CTL_MAX_DEPTH; \
|
||||||
|
size_t sz = sizeof(t); \
|
||||||
|
xmallctlbymibname( \
|
||||||
|
mib, miblen, leaf, &miblen_new, (void *)v, &sz, NULL, 0); \
|
||||||
|
assert(miblen_new == miblen + 1); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CTL_MIB_GET(n, i, v, t, ind) \
|
||||||
|
do { \
|
||||||
|
size_t mib[CTL_MAX_DEPTH]; \
|
||||||
|
size_t miblen = sizeof(mib) / sizeof(size_t); \
|
||||||
|
size_t sz = sizeof(t); \
|
||||||
|
xmallctlnametomib(n, mib, &miblen); \
|
||||||
|
mib[(ind)] = (i); \
|
||||||
|
xmallctlbymib(mib, miblen, (void *)v, &sz, NULL, 0); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CTL_M1_GET(n, i, v, t) CTL_MIB_GET(n, i, v, t, 1)
|
||||||
|
#define CTL_M2_GET(n, i, v, t) CTL_MIB_GET(n, i, v, t, 2)
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Per-section gather structs. The stats_gather_*() functions that fill them
|
||||||
|
* are static in src/stats.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* One arena's memory-accounting stats (stats.arenas.<i>.*). */
|
||||||
|
typedef struct stats_arena_mem_s {
|
||||||
|
size_t mapped;
|
||||||
|
size_t retained;
|
||||||
|
size_t pinned;
|
||||||
|
size_t base;
|
||||||
|
size_t internal;
|
||||||
|
size_t metadata_edata;
|
||||||
|
size_t metadata_rtree;
|
||||||
|
size_t metadata_thp;
|
||||||
|
size_t tcache_bytes;
|
||||||
|
size_t tcache_stashed_bytes;
|
||||||
|
size_t resident;
|
||||||
|
size_t abandoned_vm;
|
||||||
|
size_t extent_avail;
|
||||||
|
size_t page; /* arenas.page, for the active-bytes conversion */
|
||||||
|
} stats_arena_mem_t;
|
||||||
|
|
||||||
|
/* One arena extents row (stats.arenas.<i>.extents.<pszind>.*). */
|
||||||
|
typedef struct stats_arena_extent_s {
|
||||||
|
size_t ndirty;
|
||||||
|
size_t nmuzzy;
|
||||||
|
size_t nretained;
|
||||||
|
size_t npinned;
|
||||||
|
size_t ntotal;
|
||||||
|
size_t dirty_bytes;
|
||||||
|
size_t muzzy_bytes;
|
||||||
|
size_t retained_bytes;
|
||||||
|
size_t pinned_bytes;
|
||||||
|
size_t total_bytes;
|
||||||
|
} stats_arena_extent_t;
|
||||||
|
|
||||||
|
/* One arena's "basics" (stats.arenas.<i>.{nthreads,uptime,dss}). */
|
||||||
|
typedef struct stats_arena_basics_s {
|
||||||
|
unsigned nthreads;
|
||||||
|
uint64_t uptime;
|
||||||
|
const char *dss;
|
||||||
|
char name[ARENA_NAME_LEN];
|
||||||
|
bool has_name; /* false for the merged/destroyed pseudo-arenas */
|
||||||
|
} stats_arena_basics_t;
|
||||||
|
|
||||||
|
/* One arena's decay / page stats (stats.arenas.<i>.*). */
|
||||||
|
typedef struct stats_arena_decay_s {
|
||||||
|
ssize_t dirty_decay_ms;
|
||||||
|
ssize_t muzzy_decay_ms;
|
||||||
|
size_t pactive;
|
||||||
|
size_t pdirty;
|
||||||
|
size_t pmuzzy;
|
||||||
|
uint64_t dirty_npurge;
|
||||||
|
uint64_t dirty_nmadvise;
|
||||||
|
uint64_t dirty_purged;
|
||||||
|
uint64_t muzzy_npurge;
|
||||||
|
uint64_t muzzy_nmadvise;
|
||||||
|
uint64_t muzzy_purged;
|
||||||
|
} stats_arena_decay_t;
|
||||||
|
|
||||||
|
/* One size class of arena allocation counts (stats.arenas.<i>.{small,large}.*). */
|
||||||
|
typedef struct stats_arena_alloc_s {
|
||||||
|
size_t allocated;
|
||||||
|
uint64_t nmalloc;
|
||||||
|
uint64_t ndalloc;
|
||||||
|
uint64_t nrequests;
|
||||||
|
uint64_t nfills;
|
||||||
|
uint64_t nflushes;
|
||||||
|
} stats_arena_alloc_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One arena bin row (stats.arenas.<i>.bins.<j>.* + arenas.bin.<j>.*,
|
||||||
|
* plus prof.stats.bins.<j>.{live,accum} when profiling stats are enabled).
|
||||||
|
*/
|
||||||
|
typedef struct stats_arena_bin_s {
|
||||||
|
uint64_t nslabs;
|
||||||
|
uint64_t nmalloc;
|
||||||
|
uint64_t ndalloc;
|
||||||
|
uint64_t nrequests;
|
||||||
|
uint64_t nfills;
|
||||||
|
uint64_t nflushes;
|
||||||
|
uint64_t nreslabs;
|
||||||
|
size_t reg_size;
|
||||||
|
size_t slab_size;
|
||||||
|
size_t curregs;
|
||||||
|
size_t curslabs;
|
||||||
|
size_t nonfull_slabs;
|
||||||
|
uint32_t nregs;
|
||||||
|
uint32_t nshards;
|
||||||
|
prof_stats_t prof_live;
|
||||||
|
prof_stats_t prof_accum;
|
||||||
|
} stats_arena_bin_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One arena large-extent row (stats.arenas.<i>.lextents.<j>.* +
|
||||||
|
* arenas.lextent.<j>.*, plus prof.stats.lextents.<j>.{live,accum} when
|
||||||
|
* profiling stats are enabled).
|
||||||
|
*/
|
||||||
|
typedef struct stats_arena_lextent_s {
|
||||||
|
uint64_t nmalloc;
|
||||||
|
uint64_t ndalloc;
|
||||||
|
uint64_t nrequests;
|
||||||
|
size_t lextent_size;
|
||||||
|
size_t curlextents;
|
||||||
|
prof_stats_t prof_live;
|
||||||
|
prof_stats_t prof_accum;
|
||||||
|
} stats_arena_lextent_t;
|
||||||
|
|
||||||
|
/* HPA shard small-extent cache (stats.arenas.<i>.hpa_sec_*). */
|
||||||
|
typedef struct stats_arena_hpa_sec_s {
|
||||||
|
size_t sec_bytes;
|
||||||
|
size_t sec_hits;
|
||||||
|
size_t sec_misses;
|
||||||
|
size_t sec_dalloc_flush;
|
||||||
|
size_t sec_dalloc_noflush;
|
||||||
|
size_t sec_overfills;
|
||||||
|
} stats_arena_hpa_sec_t;
|
||||||
|
|
||||||
|
/* PAC small-extent cache (stats.arenas.<i>.pac_sec_*). */
|
||||||
|
typedef struct stats_arena_pac_sec_s {
|
||||||
|
size_t sec_bytes;
|
||||||
|
size_t sec_hits;
|
||||||
|
size_t sec_misses;
|
||||||
|
size_t sec_dalloc_flush;
|
||||||
|
size_t sec_dalloc_noflush;
|
||||||
|
} stats_arena_pac_sec_t;
|
||||||
|
|
||||||
|
/* HPA shard counters (stats.arenas.<i>.hpa_shard.*). */
|
||||||
|
typedef struct stats_arena_hpa_counters_s {
|
||||||
|
size_t npageslabs;
|
||||||
|
size_t nactive;
|
||||||
|
size_t ndirty;
|
||||||
|
size_t npageslabs_nonhuge;
|
||||||
|
size_t nactive_nonhuge;
|
||||||
|
size_t ndirty_nonhuge;
|
||||||
|
size_t nretained_nonhuge;
|
||||||
|
size_t npageslabs_huge;
|
||||||
|
size_t nactive_huge;
|
||||||
|
size_t ndirty_huge;
|
||||||
|
uint64_t npurge_passes;
|
||||||
|
uint64_t npurges;
|
||||||
|
uint64_t nhugifies;
|
||||||
|
uint64_t nhugify_failures;
|
||||||
|
uint64_t ndehugifies;
|
||||||
|
} stats_arena_hpa_counters_t;
|
||||||
|
|
||||||
|
/* One HPA slab class (full/empty/nonfull) row. */
|
||||||
|
typedef struct stats_arena_hpa_slab_s {
|
||||||
|
size_t npageslabs_huge;
|
||||||
|
size_t nactive_huge;
|
||||||
|
size_t ndirty_huge;
|
||||||
|
size_t npageslabs_nonhuge;
|
||||||
|
size_t nactive_nonhuge;
|
||||||
|
size_t ndirty_nonhuge;
|
||||||
|
size_t nretained_nonhuge;
|
||||||
|
} stats_arena_hpa_slab_t;
|
||||||
|
|
||||||
|
/* Arena configuration / size-class scalars (arenas.*). */
|
||||||
|
typedef struct stats_arena_config_s {
|
||||||
|
unsigned narenas;
|
||||||
|
ssize_t dirty_decay_ms;
|
||||||
|
ssize_t muzzy_decay_ms;
|
||||||
|
size_t quantum;
|
||||||
|
size_t page;
|
||||||
|
size_t hugepage;
|
||||||
|
bool have_tcache_max;
|
||||||
|
size_t tcache_max;
|
||||||
|
unsigned nbins;
|
||||||
|
unsigned nhbins;
|
||||||
|
unsigned nlextents;
|
||||||
|
} stats_arena_config_t;
|
||||||
|
|
||||||
|
/* Per-size-class geometry (emitted in JSON only). */
|
||||||
|
typedef struct stats_arena_bin_meta_s {
|
||||||
|
size_t size;
|
||||||
|
uint32_t nregs;
|
||||||
|
size_t slab_size;
|
||||||
|
uint32_t nshards;
|
||||||
|
} stats_arena_bin_meta_t;
|
||||||
|
|
||||||
|
typedef struct stats_arena_lextent_meta_s {
|
||||||
|
size_t size;
|
||||||
|
} stats_arena_lextent_meta_t;
|
||||||
|
|
||||||
|
/* Process-wide global stats (stats.* + stats.background_thread.*). */
|
||||||
|
typedef struct stats_global_s {
|
||||||
|
size_t allocated;
|
||||||
|
size_t active;
|
||||||
|
size_t metadata;
|
||||||
|
size_t metadata_edata;
|
||||||
|
size_t metadata_rtree;
|
||||||
|
size_t metadata_thp;
|
||||||
|
size_t resident;
|
||||||
|
size_t mapped;
|
||||||
|
size_t retained;
|
||||||
|
size_t pinned;
|
||||||
|
size_t zero_reallocs;
|
||||||
|
size_t num_background_threads;
|
||||||
|
uint64_t background_thread_num_runs;
|
||||||
|
uint64_t background_thread_run_interval;
|
||||||
|
} stats_global_t;
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Emitter table-column helper macros: declare an emitter_col_t (and, for
|
||||||
|
* COL_HDR, its header column) and wire it into a row.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define COL_DECLARE(column_name) emitter_col_t col_##column_name;
|
||||||
|
|
||||||
|
#define COL_INIT(row_name, column_name, left_or_right, col_width, etype) \
|
||||||
|
emitter_col_init(&col_##column_name, &row_name); \
|
||||||
|
col_##column_name.justify = emitter_justify_##left_or_right; \
|
||||||
|
col_##column_name.width = col_width; \
|
||||||
|
col_##column_name.type = emitter_type_##etype;
|
||||||
|
|
||||||
|
#define COL(row_name, column_name, left_or_right, col_width, etype) \
|
||||||
|
COL_DECLARE(column_name); \
|
||||||
|
COL_INIT(row_name, column_name, left_or_right, col_width, etype)
|
||||||
|
|
||||||
|
#define COL_HDR_DECLARE(column_name) \
|
||||||
|
COL_DECLARE(column_name); \
|
||||||
|
emitter_col_t header_##column_name;
|
||||||
|
|
||||||
|
#define COL_HDR_INIT( \
|
||||||
|
row_name, column_name, human, left_or_right, col_width, etype) \
|
||||||
|
COL_INIT(row_name, column_name, left_or_right, col_width, etype) \
|
||||||
|
emitter_col_init(&header_##column_name, &header_##row_name); \
|
||||||
|
header_##column_name.justify = emitter_justify_##left_or_right; \
|
||||||
|
header_##column_name.width = col_width; \
|
||||||
|
header_##column_name.type = emitter_type_title; \
|
||||||
|
header_##column_name.str_val = human ? human : #column_name;
|
||||||
|
|
||||||
|
#define COL_HDR(row_name, column_name, human, left_or_right, col_width, etype) \
|
||||||
|
COL_HDR_DECLARE(column_name) \
|
||||||
|
COL_HDR_INIT( \
|
||||||
|
row_name, column_name, human, left_or_right, col_width, etype)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* stats_general_print() config/option list helpers. Unhygienic by design:
|
||||||
|
* they assume `emitter` and the standard scratch locals are in scope at the
|
||||||
|
* call site -- bv/bsz (bool), cpv/cpsz (const char *), uv/usz (unsigned),
|
||||||
|
* i64v/i64sz, u64v/u64sz, sv/ssz (size_t), ssv/sssz (ssize_t), plus bv2/ssv2
|
||||||
|
* for the *_MUTABLE variants. (CONFIG_WRITE_BOOL uses CTL_GET above; the
|
||||||
|
* OPT_WRITE_* variants use je_mallctl directly.)
|
||||||
|
*/
|
||||||
|
#define CONFIG_WRITE_BOOL(name) \
|
||||||
|
do { \
|
||||||
|
CTL_GET("config." #name, &bv, bool); \
|
||||||
|
emitter_kv( \
|
||||||
|
emitter, #name, "config." #name, emitter_type_bool, &bv); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define OPT_WRITE(name, var, size, emitter_type) \
|
||||||
|
if (je_mallctl("opt." name, (void *)&var, &size, NULL, 0) == 0) { \
|
||||||
|
emitter_kv(emitter, name, "opt." name, emitter_type, &var); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OPT_WRITE_MUTABLE(name, var1, var2, size, emitter_type, altname) \
|
||||||
|
if (je_mallctl("opt." name, (void *)&var1, &size, NULL, 0) == 0 \
|
||||||
|
&& je_mallctl(altname, (void *)&var2, &size, NULL, 0) == 0) { \
|
||||||
|
emitter_kv_note(emitter, name, "opt." name, emitter_type, \
|
||||||
|
&var1, altname, emitter_type, &var2); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OPT_WRITE_BOOL(name) OPT_WRITE(name, bv, bsz, emitter_type_bool)
|
||||||
|
#define OPT_WRITE_BOOL_MUTABLE(name, altname) \
|
||||||
|
OPT_WRITE_MUTABLE(name, bv, bv2, bsz, emitter_type_bool, altname)
|
||||||
|
|
||||||
|
#define OPT_WRITE_UNSIGNED(name) OPT_WRITE(name, uv, usz, emitter_type_unsigned)
|
||||||
|
|
||||||
|
#define OPT_WRITE_INT64(name) OPT_WRITE(name, i64v, i64sz, emitter_type_int64)
|
||||||
|
#define OPT_WRITE_UINT64(name) OPT_WRITE(name, u64v, u64sz, emitter_type_uint64)
|
||||||
|
|
||||||
|
#define OPT_WRITE_SIZE_T(name) OPT_WRITE(name, sv, ssz, emitter_type_size)
|
||||||
|
#define OPT_WRITE_SSIZE_T(name) OPT_WRITE(name, ssv, sssz, emitter_type_ssize)
|
||||||
|
#define OPT_WRITE_SSIZE_T_MUTABLE(name, altname) \
|
||||||
|
OPT_WRITE_MUTABLE(name, ssv, ssv2, sssz, emitter_type_ssize, altname)
|
||||||
|
|
||||||
|
#define OPT_WRITE_CHAR_P(name) OPT_WRITE(name, cpv, cpsz, emitter_type_string)
|
||||||
|
|
||||||
|
#endif /* JEMALLOC_INTERNAL_STATS_INTERNAL_H */
|
||||||
@@ -225,7 +225,7 @@ def generate_linux_job(arch):
|
|||||||
exclude += [LARGE_HUGEPAGE]
|
exclude += [LARGE_HUGEPAGE]
|
||||||
|
|
||||||
linux_configure_flags = list(configure_flag_unusuals)
|
linux_configure_flags = list(configure_flag_unusuals)
|
||||||
linux_configure_flags.append(Option.as_configure_flag("--enable-prof --enable-prof-frameptr"))
|
linux_configure_flags.append(Option.as_configure_flag("--enable-prof --enable-prof-libunwind"))
|
||||||
|
|
||||||
linux_unusuals = (compilers_unusual + feature_unusuals
|
linux_unusuals = (compilers_unusual + feature_unusuals
|
||||||
+ linux_configure_flags + malloc_conf_unusuals)
|
+ linux_configure_flags + malloc_conf_unusuals)
|
||||||
@@ -342,6 +342,11 @@ def generate_linux_job(arch):
|
|||||||
echo "=== CPU Info ==="
|
echo "=== CPU Info ==="
|
||||||
lscpu | grep -E "Architecture|CPU op-mode|Byte Order|CPU\\(s\\):" || true
|
lscpu | grep -E "Architecture|CPU op-mode|Byte Order|CPU\\(s\\):" || true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libunwind-dev
|
||||||
|
|
||||||
- name: Install dependencies (32-bit)
|
- name: Install dependencies (32-bit)
|
||||||
if: matrix.env.CROSS_COMPILE_32BIT == 'yes'
|
if: matrix.env.CROSS_COMPILE_32BIT == 'yes'
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ def generate_linux(arch):
|
|||||||
exclude += [LARGE_HUGEPAGE]
|
exclude += [LARGE_HUGEPAGE]
|
||||||
|
|
||||||
linux_configure_flags = list(configure_flag_unusuals)
|
linux_configure_flags = list(configure_flag_unusuals)
|
||||||
linux_configure_flags.append(Option.as_configure_flag("--enable-prof --enable-prof-frameptr"))
|
linux_configure_flags.append(Option.as_configure_flag("--enable-prof --enable-prof-libunwind"))
|
||||||
|
|
||||||
linux_unusuals = (compilers_unusual + feature_unusuals
|
linux_unusuals = (compilers_unusual + feature_unusuals
|
||||||
+ linux_configure_flags + malloc_conf_unusuals)
|
+ linux_configure_flags + malloc_conf_unusuals)
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ if [[ "$TRAVIS_OS_NAME" != "linux" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libunwind-dev
|
||||||
if [[ "$CROSS_COMPILE_32BIT" == "yes" ]]; then
|
if [[ "$CROSS_COMPILE_32BIT" == "yes" ]]; then
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get -y install gcc-multilib g++-multilib
|
sudo apt-get -y install gcc-multilib g++-multilib
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -121,7 +121,6 @@ CTL_PROTO(config_opt_safety_checks)
|
|||||||
CTL_PROTO(config_prof)
|
CTL_PROTO(config_prof)
|
||||||
CTL_PROTO(config_prof_libgcc)
|
CTL_PROTO(config_prof_libgcc)
|
||||||
CTL_PROTO(config_prof_libunwind)
|
CTL_PROTO(config_prof_libunwind)
|
||||||
CTL_PROTO(config_prof_frameptr)
|
|
||||||
CTL_PROTO(config_stats)
|
CTL_PROTO(config_stats)
|
||||||
CTL_PROTO(config_utrace)
|
CTL_PROTO(config_utrace)
|
||||||
CTL_PROTO(config_xmalloc)
|
CTL_PROTO(config_xmalloc)
|
||||||
@@ -495,7 +494,6 @@ static const ctl_named_node_t config_node[] = {
|
|||||||
{NAME("prof"), CTL(config_prof)},
|
{NAME("prof"), CTL(config_prof)},
|
||||||
{NAME("prof_libgcc"), CTL(config_prof_libgcc)},
|
{NAME("prof_libgcc"), CTL(config_prof_libgcc)},
|
||||||
{NAME("prof_libunwind"), CTL(config_prof_libunwind)},
|
{NAME("prof_libunwind"), CTL(config_prof_libunwind)},
|
||||||
{NAME("prof_frameptr"), CTL(config_prof_frameptr)},
|
|
||||||
{NAME("stats"), CTL(config_stats)}, {NAME("utrace"), CTL(config_utrace)},
|
{NAME("stats"), CTL(config_stats)}, {NAME("utrace"), CTL(config_utrace)},
|
||||||
{NAME("xmalloc"), CTL(config_xmalloc)}};
|
{NAME("xmalloc"), CTL(config_xmalloc)}};
|
||||||
|
|
||||||
@@ -2210,7 +2208,6 @@ CTL_RO_CONFIG_GEN(config_opt_safety_checks, bool)
|
|||||||
CTL_RO_CONFIG_GEN(config_prof, bool)
|
CTL_RO_CONFIG_GEN(config_prof, bool)
|
||||||
CTL_RO_CONFIG_GEN(config_prof_libgcc, bool)
|
CTL_RO_CONFIG_GEN(config_prof_libgcc, bool)
|
||||||
CTL_RO_CONFIG_GEN(config_prof_libunwind, bool)
|
CTL_RO_CONFIG_GEN(config_prof_libunwind, bool)
|
||||||
CTL_RO_CONFIG_GEN(config_prof_frameptr, bool)
|
|
||||||
CTL_RO_CONFIG_GEN(config_stats, bool)
|
CTL_RO_CONFIG_GEN(config_stats, bool)
|
||||||
CTL_RO_CONFIG_GEN(config_utrace, bool)
|
CTL_RO_CONFIG_GEN(config_utrace, bool)
|
||||||
CTL_RO_CONFIG_GEN(config_xmalloc, bool)
|
CTL_RO_CONFIG_GEN(config_xmalloc, bool)
|
||||||
|
|||||||
@@ -826,8 +826,16 @@ init_thp_state(void) {
|
|||||||
static const char sys_state_never[] = "always madvise [never]\n";
|
static const char sys_state_never[] = "always madvise [never]\n";
|
||||||
char buf[sizeof(sys_state_madvise)];
|
char buf[sizeof(sys_state_madvise)];
|
||||||
|
|
||||||
|
# if defined(O_CLOEXEC)
|
||||||
|
int fd = malloc_open(
|
||||||
|
"/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY | O_CLOEXEC);
|
||||||
|
# else
|
||||||
int fd = malloc_open(
|
int fd = malloc_open(
|
||||||
"/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY);
|
"/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY);
|
||||||
|
if (fd != -1) {
|
||||||
|
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
goto label_error;
|
goto label_error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,174 +0,0 @@
|
|||||||
#include "jemalloc/internal/jemalloc_preamble.h"
|
|
||||||
|
|
||||||
#include "jemalloc/internal/malloc_io.h"
|
|
||||||
#include "jemalloc/internal/prof_sys.h"
|
|
||||||
|
|
||||||
#if defined(__linux__) && defined(JEMALLOC_HAVE_GETTID)
|
|
||||||
|
|
||||||
# include <errno.h>
|
|
||||||
# include <fcntl.h>
|
|
||||||
# include <stdio.h>
|
|
||||||
# include <stdlib.h> // strtoul
|
|
||||||
# include <string.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Converts a string representing a hexadecimal number to an unsigned long long
|
|
||||||
* integer. Functionally equivalent to strtoull() (for base 16) but faster for
|
|
||||||
* that case.
|
|
||||||
*
|
|
||||||
* @param nptr Pointer to the string to be converted.
|
|
||||||
* @param endptr Pointer to a pointer to character, which will be set to the
|
|
||||||
* character in `nptr` where parsing stopped. Can be NULL.
|
|
||||||
* @return The converted unsigned long long integer value.
|
|
||||||
*/
|
|
||||||
static inline unsigned long long int
|
|
||||||
strtoull_hex(const char *nptr, char **endptr) {
|
|
||||||
unsigned long long int val = 0;
|
|
||||||
int ii = 0;
|
|
||||||
for (; ii < 16; ++ii) {
|
|
||||||
char c = nptr[ii];
|
|
||||||
if (c >= '0' && c <= '9') {
|
|
||||||
val = (val << 4) + (c - '0');
|
|
||||||
} else if (c >= 'a' && c <= 'f') {
|
|
||||||
val = (val << 4) + (c - 'a' + 10);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (endptr) {
|
|
||||||
*endptr = (char *)(nptr + ii);
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
prof_mapping_containing_addr(uintptr_t addr, const char *maps_path,
|
|
||||||
uintptr_t *mm_start, uintptr_t *mm_end) {
|
|
||||||
int ret = ENOENT; /* not found */
|
|
||||||
*mm_start = *mm_end = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Each line of /proc/<pid>/maps is:
|
|
||||||
* <start>-<end> <perms> <offset> <dev> <inode> <pathname>
|
|
||||||
*
|
|
||||||
* The fields we care about are always within the first 34 characters so
|
|
||||||
* as long as `buf` contains the start of a mapping line it can always be
|
|
||||||
* parsed.
|
|
||||||
*/
|
|
||||||
static const int kMappingFieldsWidth = 34;
|
|
||||||
|
|
||||||
int fd = -1;
|
|
||||||
char buf[4096];
|
|
||||||
ssize_t remaining = 0; /* actual number of bytes read to buf */
|
|
||||||
char *line = NULL;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if (fd < 0) {
|
|
||||||
/* case 0: initial open of maps file */
|
|
||||||
fd = malloc_open(maps_path, O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
remaining = malloc_read_fd(fd, buf, sizeof(buf));
|
|
||||||
if (remaining < 0) {
|
|
||||||
ret = errno;
|
|
||||||
break;
|
|
||||||
} else if (remaining == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
line = buf;
|
|
||||||
} else if (line == NULL) {
|
|
||||||
/* case 1: no newline found in buf */
|
|
||||||
remaining = malloc_read_fd(fd, buf, sizeof(buf));
|
|
||||||
if (remaining < 0) {
|
|
||||||
ret = errno;
|
|
||||||
break;
|
|
||||||
} else if (remaining == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
line = memchr(buf, '\n', remaining);
|
|
||||||
if (line != NULL) {
|
|
||||||
line++; /* advance to character after newline */
|
|
||||||
remaining -= (line - buf);
|
|
||||||
}
|
|
||||||
} else if (line != NULL && remaining < kMappingFieldsWidth) {
|
|
||||||
/*
|
|
||||||
* case 2: found newline but insufficient characters remaining in
|
|
||||||
* buf
|
|
||||||
*/
|
|
||||||
memcpy(buf, line,
|
|
||||||
remaining); /* copy remaining characters to start of buf */
|
|
||||||
line = buf;
|
|
||||||
|
|
||||||
ssize_t count = malloc_read_fd(
|
|
||||||
fd, buf + remaining, sizeof(buf) - remaining);
|
|
||||||
if (count < 0) {
|
|
||||||
ret = errno;
|
|
||||||
break;
|
|
||||||
} else if (count == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
remaining +=
|
|
||||||
count; /* actual number of bytes read to buf */
|
|
||||||
} else {
|
|
||||||
/* case 3: found newline and sufficient characters to parse */
|
|
||||||
|
|
||||||
/* parse <start>-<end> */
|
|
||||||
char *tmp = line;
|
|
||||||
uintptr_t start_addr = (uintptr_t)strtoull_hex(
|
|
||||||
tmp, &tmp);
|
|
||||||
if (addr >= start_addr) {
|
|
||||||
tmp++; /* advance to character after '-' */
|
|
||||||
uintptr_t end_addr = (uintptr_t)strtoull_hex(
|
|
||||||
tmp, NULL);
|
|
||||||
if (addr < end_addr) {
|
|
||||||
*mm_start = start_addr;
|
|
||||||
*mm_end = end_addr;
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Advance to character after next newline in the current buf. */
|
|
||||||
char *prev_line = line;
|
|
||||||
line = memchr(line, '\n', remaining);
|
|
||||||
if (line != NULL) {
|
|
||||||
line++; /* advance to character after newline */
|
|
||||||
remaining -= (line - prev_line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
malloc_close(fd);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
prof_thread_stack_range(uintptr_t fp, uintptr_t *low, uintptr_t *high) {
|
|
||||||
/*
|
|
||||||
* NOTE: Prior to kernel 4.5 an entry for every thread stack was included in
|
|
||||||
* /proc/<pid>/maps as [STACK:<tid>]. Starting with kernel 4.5 only the main
|
|
||||||
* thread stack remains as the [stack] mapping. For other thread stacks the
|
|
||||||
* mapping is still visible in /proc/<pid>/task/<tid>/maps (though not
|
|
||||||
* labeled as [STACK:tid]).
|
|
||||||
* https://lists.ubuntu.com/archives/kernel-team/2016-March/074681.html
|
|
||||||
*/
|
|
||||||
char maps_path[64]; // "/proc/<pid>/task/<tid>/maps"
|
|
||||||
malloc_snprintf(maps_path, sizeof(maps_path), "/proc/%d/task/%d/maps",
|
|
||||||
getpid(), gettid());
|
|
||||||
return prof_mapping_containing_addr(fp, maps_path, low, high);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
int
|
|
||||||
prof_thread_stack_range(
|
|
||||||
UNUSED uintptr_t addr, uintptr_t *stack_start, uintptr_t *stack_end) {
|
|
||||||
*stack_start = *stack_end = 0;
|
|
||||||
return ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __linux__
|
|
||||||
102
src/prof_sys.c
102
src/prof_sys.c
@@ -28,11 +28,6 @@
|
|||||||
JEMALLOC_TEST_HOOK(_Unwind_Backtrace, test_hooks_libc_hook)
|
JEMALLOC_TEST_HOOK(_Unwind_Backtrace, test_hooks_libc_hook)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef JEMALLOC_PROF_FRAME_POINTER
|
|
||||||
// execinfo backtrace() as fallback unwinder
|
|
||||||
# include <execinfo.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
malloc_mutex_t prof_dump_filename_mtx;
|
malloc_mutex_t prof_dump_filename_mtx;
|
||||||
@@ -109,103 +104,6 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) {
|
|||||||
|
|
||||||
_Unwind_Backtrace(prof_unwind_callback, &data);
|
_Unwind_Backtrace(prof_unwind_callback, &data);
|
||||||
}
|
}
|
||||||
#elif (defined(JEMALLOC_PROF_FRAME_POINTER))
|
|
||||||
JEMALLOC_DIAGNOSTIC_PUSH
|
|
||||||
JEMALLOC_DIAGNOSTIC_IGNORE_FRAME_ADDRESS
|
|
||||||
|
|
||||||
struct stack_range {
|
|
||||||
uintptr_t start;
|
|
||||||
uintptr_t end;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct thread_unwind_info {
|
|
||||||
struct stack_range stack_range;
|
|
||||||
bool fallback;
|
|
||||||
};
|
|
||||||
static __thread struct thread_unwind_info unwind_info = {
|
|
||||||
.stack_range =
|
|
||||||
{
|
|
||||||
.start = 0,
|
|
||||||
.end = 0,
|
|
||||||
},
|
|
||||||
.fallback = false,
|
|
||||||
}; /* thread local */
|
|
||||||
|
|
||||||
static void
|
|
||||||
prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) {
|
|
||||||
/* fp: current stack frame pointer
|
|
||||||
*
|
|
||||||
* stack_range: readable stack memory range for the current thread.
|
|
||||||
* Used to validate frame addresses during stack unwinding.
|
|
||||||
* For most threads there is a single valid stack range
|
|
||||||
* that is fixed at thread creation time. This may not be
|
|
||||||
* the case when folly fibers or boost contexts are used.
|
|
||||||
* In those cases fall back to using execinfo backtrace()
|
|
||||||
* (DWARF unwind).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* always safe to get the current stack frame address */
|
|
||||||
uintptr_t fp = (uintptr_t)__builtin_frame_address(0);
|
|
||||||
|
|
||||||
/* new thread - get the stack range */
|
|
||||||
if (!unwind_info.fallback
|
|
||||||
&& unwind_info.stack_range.start == unwind_info.stack_range.end) {
|
|
||||||
if (prof_thread_stack_range(fp, &unwind_info.stack_range.start,
|
|
||||||
&unwind_info.stack_range.end)
|
|
||||||
!= 0) {
|
|
||||||
unwind_info.fallback = true;
|
|
||||||
} else {
|
|
||||||
assert(fp >= unwind_info.stack_range.start
|
|
||||||
&& fp < unwind_info.stack_range.end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unwind_info.fallback) {
|
|
||||||
goto label_fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned ii = 0;
|
|
||||||
while (ii < max_len && fp != 0) {
|
|
||||||
if (fp < unwind_info.stack_range.start
|
|
||||||
|| fp >= unwind_info.stack_range.end) {
|
|
||||||
/*
|
|
||||||
* Determining the stack range from procfs can be
|
|
||||||
* relatively expensive especially for programs with
|
|
||||||
* many threads / shared libraries. If the stack
|
|
||||||
* range has changed, it is likely to change again
|
|
||||||
* in the future (fibers or some other stack
|
|
||||||
* manipulation). So fall back to backtrace for this
|
|
||||||
* thread.
|
|
||||||
*/
|
|
||||||
unwind_info.fallback = true;
|
|
||||||
goto label_fallback;
|
|
||||||
}
|
|
||||||
void *ip = ((void **)fp)[1];
|
|
||||||
if (ip == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
vec[ii++] = ip;
|
|
||||||
fp = ((uintptr_t *)fp)[0];
|
|
||||||
}
|
|
||||||
*len = ii;
|
|
||||||
return;
|
|
||||||
|
|
||||||
label_fallback:
|
|
||||||
/*
|
|
||||||
* Using the backtrace from execinfo.h here. Note that it may get
|
|
||||||
* redirected to libunwind when a libunwind not built with build-time
|
|
||||||
* flag --disable-weak-backtrace is linked.
|
|
||||||
*/
|
|
||||||
assert(unwind_info.fallback);
|
|
||||||
int nframes = backtrace(vec, max_len);
|
|
||||||
if (nframes > 0) {
|
|
||||||
*len = nframes;
|
|
||||||
} else {
|
|
||||||
*len = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JEMALLOC_DIAGNOSTIC_POP
|
|
||||||
#elif (defined(JEMALLOC_PROF_GCC))
|
#elif (defined(JEMALLOC_PROF_GCC))
|
||||||
JEMALLOC_DIAGNOSTIC_PUSH
|
JEMALLOC_DIAGNOSTIC_PUSH
|
||||||
JEMALLOC_DIAGNOSTIC_IGNORE_FRAME_ADDRESS
|
JEMALLOC_DIAGNOSTIC_IGNORE_FRAME_ADDRESS
|
||||||
|
|||||||
2863
src/stats.c
2863
src/stats.c
File diff suppressed because it is too large
Load Diff
@@ -498,13 +498,13 @@ emit_table_row(emitter_t *emitter) {
|
|||||||
emitter_begin(emitter);
|
emitter_begin(emitter);
|
||||||
emitter_row_t row;
|
emitter_row_t row;
|
||||||
emitter_col_t abc = {
|
emitter_col_t abc = {
|
||||||
emitter_justify_left, 10, emitter_type_title, {0}, {0, 0}};
|
emitter_justify_left, 10, emitter_type_title};
|
||||||
abc.str_val = "ABC title";
|
abc.str_val = "ABC title";
|
||||||
emitter_col_t def = {
|
emitter_col_t def = {
|
||||||
emitter_justify_right, 15, emitter_type_title, {0}, {0, 0}};
|
emitter_justify_right, 15, emitter_type_title};
|
||||||
def.str_val = "DEF title";
|
def.str_val = "DEF title";
|
||||||
emitter_col_t ghi = {
|
emitter_col_t ghi = {
|
||||||
emitter_justify_right, 5, emitter_type_title, {0}, {0, 0}};
|
emitter_justify_right, 5, emitter_type_title};
|
||||||
ghi.str_val = "GHI";
|
ghi.str_val = "GHI";
|
||||||
|
|
||||||
emitter_row_init(&row);
|
emitter_row_init(&row);
|
||||||
@@ -548,6 +548,230 @@ static const char *table_row_table =
|
|||||||
"789 false 1011\n"
|
"789 false 1011\n"
|
||||||
"\"a string\" false ghi\n";
|
"\"a string\" false ghi\n";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* emitter_row(): columns that carry a json_key render both to the aligned
|
||||||
|
* table (all columns) and, in JSON mode, to "json_key": value pairs in column
|
||||||
|
* order; columns without a json_key are table-only.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
emit_row(emitter_t *emitter) {
|
||||||
|
emitter_begin(emitter);
|
||||||
|
|
||||||
|
emitter_row_t row;
|
||||||
|
emitter_row_init(&row);
|
||||||
|
|
||||||
|
/* Table-only column (no json_key set). */
|
||||||
|
emitter_col_t col_label;
|
||||||
|
emitter_col_init(&col_label, &row);
|
||||||
|
col_label.justify = emitter_justify_left;
|
||||||
|
col_label.width = 6;
|
||||||
|
col_label.type = emitter_type_title;
|
||||||
|
col_label.str_val = "row:";
|
||||||
|
|
||||||
|
/* Dual columns: rendered in both table and JSON. */
|
||||||
|
emitter_col_t col_x;
|
||||||
|
emitter_col_init(&col_x, &row);
|
||||||
|
col_x.justify = emitter_justify_right;
|
||||||
|
col_x.width = 6;
|
||||||
|
col_x.type = emitter_type_unsigned;
|
||||||
|
col_x.unsigned_val = 10;
|
||||||
|
col_x.json_key = "x";
|
||||||
|
|
||||||
|
emitter_col_t col_y;
|
||||||
|
emitter_col_init(&col_y, &row);
|
||||||
|
col_y.justify = emitter_justify_right;
|
||||||
|
col_y.width = 6;
|
||||||
|
col_y.type = emitter_type_unsigned;
|
||||||
|
col_y.unsigned_val = 20;
|
||||||
|
col_y.json_key = "y";
|
||||||
|
|
||||||
|
emitter_json_object_kv_begin(emitter, "obj");
|
||||||
|
emitter_row(emitter, &row);
|
||||||
|
emitter_json_object_end(emitter);
|
||||||
|
|
||||||
|
emitter_end(emitter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *row_json =
|
||||||
|
"{\n"
|
||||||
|
"\t\"obj\": {\n"
|
||||||
|
"\t\t\"x\": 10,\n"
|
||||||
|
"\t\t\"y\": 20\n"
|
||||||
|
"\t}\n"
|
||||||
|
"}\n";
|
||||||
|
static const char *row_json_compact = "{\"obj\":{\"x\":10,\"y\":20}}";
|
||||||
|
static const char *row_table = "row: 10 20\n";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* emitter_sparse_row(): the table side collapses runs of all-zero ("gap") rows
|
||||||
|
* to a single "---" separator (on a gap->non-gap transition and at a trailing
|
||||||
|
* gap), while the JSON side still emits every row's json-keyed columns.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
emit_sparse_row(emitter_t *emitter) {
|
||||||
|
emitter_begin(emitter);
|
||||||
|
|
||||||
|
emitter_row_t row;
|
||||||
|
emitter_row_init(&row);
|
||||||
|
emitter_col_t col_v;
|
||||||
|
emitter_col_init(&col_v, &row);
|
||||||
|
col_v.justify = emitter_justify_right;
|
||||||
|
col_v.width = 6;
|
||||||
|
col_v.type = emitter_type_unsigned;
|
||||||
|
col_v.json_key = "v";
|
||||||
|
|
||||||
|
unsigned vals[] = {1, 0, 0, 2, 0, 0};
|
||||||
|
bool gap[] = {false, true, true, false, true, true};
|
||||||
|
|
||||||
|
emitter_json_array_kv_begin(emitter, "arr");
|
||||||
|
emitter_table_sparse_begin(emitter);
|
||||||
|
for (unsigned i = 0; i < sizeof(vals) / sizeof(vals[0]); i++) {
|
||||||
|
col_v.unsigned_val = vals[i];
|
||||||
|
emitter_json_object_begin(emitter);
|
||||||
|
emitter_sparse_row(emitter, &row, gap[i]);
|
||||||
|
emitter_json_object_end(emitter);
|
||||||
|
}
|
||||||
|
emitter_table_sparse_end(emitter);
|
||||||
|
emitter_json_array_end(emitter);
|
||||||
|
|
||||||
|
emitter_end(emitter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *sparse_row_json =
|
||||||
|
"{\n"
|
||||||
|
"\t\"arr\": [\n"
|
||||||
|
"\t\t{\n"
|
||||||
|
"\t\t\t\"v\": 1\n"
|
||||||
|
"\t\t},\n"
|
||||||
|
"\t\t{\n"
|
||||||
|
"\t\t\t\"v\": 0\n"
|
||||||
|
"\t\t},\n"
|
||||||
|
"\t\t{\n"
|
||||||
|
"\t\t\t\"v\": 0\n"
|
||||||
|
"\t\t},\n"
|
||||||
|
"\t\t{\n"
|
||||||
|
"\t\t\t\"v\": 2\n"
|
||||||
|
"\t\t},\n"
|
||||||
|
"\t\t{\n"
|
||||||
|
"\t\t\t\"v\": 0\n"
|
||||||
|
"\t\t},\n"
|
||||||
|
"\t\t{\n"
|
||||||
|
"\t\t\t\"v\": 0\n"
|
||||||
|
"\t\t}\n"
|
||||||
|
"\t]\n"
|
||||||
|
"}\n";
|
||||||
|
static const char *sparse_row_json_compact =
|
||||||
|
"{\"arr\":[{\"v\":1},{\"v\":0},{\"v\":0},{\"v\":2},{\"v\":0},{\"v\":0}]}";
|
||||||
|
static const char *sparse_row_table =
|
||||||
|
" 1\n"
|
||||||
|
" ---\n"
|
||||||
|
" 2\n"
|
||||||
|
" ---\n";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t size;
|
||||||
|
uint64_t count;
|
||||||
|
uint64_t prof_count;
|
||||||
|
const char *label;
|
||||||
|
uint64_t requests;
|
||||||
|
} col_table_test_row_t;
|
||||||
|
|
||||||
|
#define COL_TABLE_TEST_GETTER(name, member, value_member) \
|
||||||
|
static void \
|
||||||
|
col_table_test_get_##name(const void *vrow, emitter_col_t *col) { \
|
||||||
|
const col_table_test_row_t *row = vrow; \
|
||||||
|
col->value_member = row->member; \
|
||||||
|
}
|
||||||
|
COL_TABLE_TEST_GETTER(size, size, size_val)
|
||||||
|
COL_TABLE_TEST_GETTER(count, count, uint64_val)
|
||||||
|
COL_TABLE_TEST_GETTER(prof_count, prof_count, uint64_val)
|
||||||
|
COL_TABLE_TEST_GETTER(label, label, str_val)
|
||||||
|
COL_TABLE_TEST_GETTER(requests, requests, uint64_val)
|
||||||
|
#undef COL_TABLE_TEST_GETTER
|
||||||
|
|
||||||
|
enum {
|
||||||
|
COL_TABLE_TEST_SIZE,
|
||||||
|
COL_TABLE_TEST_COUNT,
|
||||||
|
COL_TABLE_TEST_PROF_COUNT,
|
||||||
|
COL_TABLE_TEST_LABEL,
|
||||||
|
COL_TABLE_TEST_REQUESTS,
|
||||||
|
COL_TABLE_TEST_NCOLS
|
||||||
|
};
|
||||||
|
|
||||||
|
#define COL_TABLE_TEST_FLAG_PROF (1U << 0)
|
||||||
|
|
||||||
|
static const emitter_col_desc_t col_table_test_descs[] = {
|
||||||
|
{NULL, "size", emitter_justify_right, 8, emitter_type_size, 0,
|
||||||
|
col_table_test_get_size},
|
||||||
|
{"count", "count", emitter_justify_right, 8, emitter_type_uint64,
|
||||||
|
0, col_table_test_get_count},
|
||||||
|
{"prof_count", "prof", emitter_justify_right, 6, emitter_type_uint64,
|
||||||
|
COL_TABLE_TEST_FLAG_PROF, col_table_test_get_prof_count},
|
||||||
|
{"label", "label", emitter_justify_right, 7, emitter_type_title, 0,
|
||||||
|
col_table_test_get_label},
|
||||||
|
{"requests", "requests", emitter_justify_right, 10,
|
||||||
|
emitter_type_uint64, 0, col_table_test_get_requests},
|
||||||
|
};
|
||||||
|
_Static_assert(
|
||||||
|
sizeof(col_table_test_descs) / sizeof(col_table_test_descs[0]) ==
|
||||||
|
COL_TABLE_TEST_NCOLS,
|
||||||
|
"col_table_test_descs must match COL_TABLE_TEST_NCOLS");
|
||||||
|
|
||||||
|
TEST_BEGIN(test_col_desc_flags) {
|
||||||
|
expect_true(emitter_col_desc_active(
|
||||||
|
&col_table_test_descs[COL_TABLE_TEST_COUNT], 0),
|
||||||
|
"A column without requirements should always be active");
|
||||||
|
expect_false(emitter_col_desc_active(
|
||||||
|
&col_table_test_descs[COL_TABLE_TEST_PROF_COUNT], 0),
|
||||||
|
"A column with an unmet requirement should be inactive");
|
||||||
|
expect_true(emitter_col_desc_active(
|
||||||
|
&col_table_test_descs[COL_TABLE_TEST_PROF_COUNT],
|
||||||
|
COL_TABLE_TEST_FLAG_PROF),
|
||||||
|
"A column with a satisfied requirement should be active");
|
||||||
|
}
|
||||||
|
TEST_END
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_col_table(emitter_t *emitter) {
|
||||||
|
col_table_test_row_t value = {42, 7, 100, "row", 9};
|
||||||
|
emitter_row_t row, header_row;
|
||||||
|
emitter_col_t cols[COL_TABLE_TEST_NCOLS];
|
||||||
|
emitter_col_t header_cols[COL_TABLE_TEST_NCOLS];
|
||||||
|
|
||||||
|
emitter_begin(emitter);
|
||||||
|
emitter_col_table_build(col_table_test_descs, COL_TABLE_TEST_NCOLS,
|
||||||
|
COL_TABLE_TEST_FLAG_PROF, &row, cols, &header_row, header_cols);
|
||||||
|
emitter_col_table_header(
|
||||||
|
emitter, &header_row, &header_cols[0], "mock:", "rows");
|
||||||
|
emitter_col_table_fill(col_table_test_descs, COL_TABLE_TEST_NCOLS,
|
||||||
|
COL_TABLE_TEST_FLAG_PROF, cols, &value);
|
||||||
|
emitter_json_object_begin(emitter);
|
||||||
|
emitter_col_table_emit_json(emitter, col_table_test_descs,
|
||||||
|
COL_TABLE_TEST_NCOLS, COL_TABLE_TEST_FLAG_PROF, cols);
|
||||||
|
emitter_json_object_end(emitter);
|
||||||
|
emitter_table_row(emitter, &row);
|
||||||
|
emitter_json_array_end(emitter);
|
||||||
|
emitter_end(emitter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *col_table_json =
|
||||||
|
"{\n"
|
||||||
|
"\t\"rows\": [\n"
|
||||||
|
"\t\t{\n"
|
||||||
|
"\t\t\t\"count\": 7,\n"
|
||||||
|
"\t\t\t\"prof_count\": 100,\n"
|
||||||
|
"\t\t\t\"label\": \"row\",\n"
|
||||||
|
"\t\t\t\"requests\": 9\n"
|
||||||
|
"\t\t}\n"
|
||||||
|
"\t]\n"
|
||||||
|
"}\n";
|
||||||
|
static const char *col_table_json_compact =
|
||||||
|
"{\"rows\":[{\"count\":7,\"prof_count\":100,\"label\":\"row\","
|
||||||
|
"\"requests\":9}]}";
|
||||||
|
static const char *col_table_table =
|
||||||
|
"mock:size count prof label requests\n"
|
||||||
|
" 42 7 100 row 9\n";
|
||||||
|
|
||||||
#define GENERATE_TEST(feature) \
|
#define GENERATE_TEST(feature) \
|
||||||
TEST_BEGIN(test_##feature) { \
|
TEST_BEGIN(test_##feature) { \
|
||||||
expect_emit_output(emit_##feature, feature##_json, \
|
expect_emit_output(emit_##feature, feature##_json, \
|
||||||
@@ -563,10 +787,14 @@ GENERATE_TEST(modal)
|
|||||||
GENERATE_TEST(json_array)
|
GENERATE_TEST(json_array)
|
||||||
GENERATE_TEST(json_nested_array)
|
GENERATE_TEST(json_nested_array)
|
||||||
GENERATE_TEST(table_row)
|
GENERATE_TEST(table_row)
|
||||||
|
GENERATE_TEST(row)
|
||||||
|
GENERATE_TEST(sparse_row)
|
||||||
|
GENERATE_TEST(col_table)
|
||||||
|
|
||||||
int
|
int
|
||||||
main(void) {
|
main(void) {
|
||||||
return test_no_reentrancy(test_dict, test_table_printf,
|
return test_no_reentrancy(test_dict, test_table_printf,
|
||||||
test_nested_dict, test_types, test_modal, test_json_array,
|
test_nested_dict, test_types, test_modal, test_json_array,
|
||||||
test_json_nested_array, test_table_row);
|
test_json_nested_array, test_table_row, test_row, test_sparse_row,
|
||||||
|
test_col_table, test_col_desc_flags);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -489,7 +489,6 @@ TEST_BEGIN(test_mallctl_config) {
|
|||||||
TEST_MALLCTL_CONFIG(prof, bool);
|
TEST_MALLCTL_CONFIG(prof, bool);
|
||||||
TEST_MALLCTL_CONFIG(prof_libgcc, bool);
|
TEST_MALLCTL_CONFIG(prof_libgcc, bool);
|
||||||
TEST_MALLCTL_CONFIG(prof_libunwind, bool);
|
TEST_MALLCTL_CONFIG(prof_libunwind, bool);
|
||||||
TEST_MALLCTL_CONFIG(prof_frameptr, bool);
|
|
||||||
TEST_MALLCTL_CONFIG(stats, bool);
|
TEST_MALLCTL_CONFIG(stats, bool);
|
||||||
TEST_MALLCTL_CONFIG(utrace, bool);
|
TEST_MALLCTL_CONFIG(utrace, bool);
|
||||||
TEST_MALLCTL_CONFIG(xmalloc, bool);
|
TEST_MALLCTL_CONFIG(xmalloc, bool);
|
||||||
|
|||||||
Reference in New Issue
Block a user