在华为云进行测试,8核心(4个物理核心开启超线程技术)
15G内存,40G硬盘
root@ecs-ec4a:~/cppMemoryPool# lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Address sizes: 42 bits physical, 48 bits virtual
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Vendor ID: AuthenticAMD
Model name: General Purpose Processor
CPU family: 25
Model: 1
Thread(s) per core: 2
Core(s) per socket: 4
Socket(s): 1
Stepping: 1
BogoMIPS: 4899.99
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm const
ant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid tsc_known_freq pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_tim
er aes xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw topoext perfctr_core invpcid_single ssbd
ibrs ibpb stibp vmmcall fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 xsaves clz
ero xsaveerptr wbnoinvd arat umip vaes vpclmulqdq fsrm arch_capabilities
Virtualization features:
Hypervisor vendor: KVM
Virtualization type: full
Caches (sum of all):
L1d: 128 KiB (4 instances)
L1i: 128 KiB (4 instances)
L2: 2 MiB (4 instances)
L3: 32 MiB (1 instance)
NUMA:
NUMA node(s): 1
NUMA node0 CPU(s): 0-7
Vulnerabilities:
Gather data sampling: Not affected
Indirect target selection: Not affected
Itlb multihit: Not affected
L1tf: Not affected
Mds: Not affected
Meltdown: Not affected
Mmio stale data: Not affected
Reg file data sampling: Not affected
Retbleed: Not affected
Spec rstack overflow: Mitigation; safe RET, no microcode
Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Spectre v2: Mitigation; Retpolines; IBPB conditional; IBRS_FW; STIBP conditional; RSB filling; PBRSB-eIBRS Not affected; BHI Not affected
Srbds: Not affected
Tsa: Vulnerable: Clear CPU buffers attempted, no microcode
Tsx async abort: Not affected
Vmscape: Not affected
root@ecs-ec4a:~/cppMemoryPool#
root@ecs-ec4a:~/cppMemoryPool# free -h
total used free shared buff/cache available
Mem: 15Gi 707Mi 13Gi 2.0Mi 834Mi 14Gi
Swap: 0B 0B 0B
root@ecs-ec4a:~/cppMemoryPool# df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 1.6G 1.1M 1.6G 1% /run
/dev/vda1 40G 6.6G 31G 18% /
tmpfs 7.7G 0 7.7G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 1.6G 4.0K 1.6G 1% /run/user/0
root@ecs-ec4a:~/cppMemoryPool#
测试代码
#include <benchmark/benchmark.h>
#include "memory.hpp"
#include <cstdlib>
#include <mutex>
#include <vector>
// 保持与你 memory.hpp 中一致的块大小
constexpr std::size_t BLOCK_SIZE = 64;
constexpr std::size_t BATCH_SIZE = 32; // 模拟真实的批量业务流
// 全局内存池指针和初始化标记
static FixedSizeMemory* g_pool = nullptr;
static std::once_flag g_pool_init_flag;
// 保证全局池只被安全地初始化一次
void InitGlobalPool() {
// 假设你的构造函数只接收 block_size,或者有默认的 blocks_per_page
g_pool = new FixedSizeMemory(BLOCK_SIZE);
}
// ==================== 1. 自定义内存池批量跑分 ====================
static void BM_CustomMemoryPool(benchmark::State& state) {
// 安全地进行单次初始化
std::call_once(g_pool_init_flag, InitGlobalPool);
// 局部数组,用来存放批量申请的指针
void* ptrs[BATCH_SIZE];
// 跑分主循环
for (auto _ : state) {
// 步骤一:批量分配,让第一级 TLS 无锁路径吃满缓存
for (std::size_t i = 0; i < BATCH_SIZE; ++i) {
ptrs[i] = g_pool->allocate();
}
// 防止编译器把分配动作优化掉
benchmark::DoNotOptimize(ptrs);
// 步骤二:批量释放,触发本地缓存高水位积攒,绕开高频锁冲突
for (std::size_t i = 0; i < BATCH_SIZE; ++i) {
g_pool->deallocate(ptrs[i]);
}
// 刷新内存状态
benchmark::ClobberMemory();
}
// 线程退出前,看门人兜底之外,强制刷新归还当前线程本地缓存
g_pool->flush_thread_cache();
}
// 注册测试,覆盖 1, 4, 8, 16 核心线程压测
BENCHMARK(BM_CustomMemoryPool)->ThreadRange(1, 16)->UseRealTime();
// ==================== 2. 对照组:原生 malloc / free 跑分 ====================
static void BM_SystemMalloc(benchmark::State& state) {
void* ptrs[BATCH_SIZE];
for (auto _ : state) {
for (std::size_t i = 0; i < BATCH_SIZE; ++i) {
ptrs[i] = std::malloc(BLOCK_SIZE);
}
benchmark::DoNotOptimize(ptrs);
for (std::size_t i = 0; i < BATCH_SIZE; ++i) {
std::free(ptrs[i]);
}
benchmark::ClobberMemory();
}
}
BENCHMARK(BM_SystemMalloc)->ThreadRange(1, 16)->UseRealTime();
// 自动生成含有 Google Benchmark 逻辑的 main 函数入口
BENCHMARK_MAIN();测试数据
root@ecs-ec4a:~/cppMemoryPool/build# ./pool_bench
2026-07-29T23:30:51+08:00
Running ./pool_bench
Run on (8 X 2449.74 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x4)
L1 Instruction 32 KiB (x4)
L2 Unified 512 KiB (x4)
L3 Unified 32768 KiB (x1)
Load Average: 0.07, 0.05, 0.00
-----------------------------------------------------------------------------------
Benchmark Time CPU Iterations
-----------------------------------------------------------------------------------
BM_CustomMemoryPool/real_time/threads:1 164 ns 164 ns 4233756
BM_CustomMemoryPool/real_time/threads:2 82.0 ns 164 ns 8468594
BM_CustomMemoryPool/real_time/threads:4 41.1 ns 164 ns 16722248
BM_CustomMemoryPool/real_time/threads:8 40.5 ns 323 ns 17197008
BM_CustomMemoryPool/real_time/threads:16 38.5 ns 322 ns 21816688
BM_SystemMalloc/real_time/threads:1 528 ns 528 ns 1324934
BM_SystemMalloc/real_time/threads:2 266 ns 531 ns 2631462
BM_SystemMalloc/real_time/threads:4 133 ns 532 ns 5256160
BM_SystemMalloc/real_time/threads:8 128 ns 1018 ns 5496872
BM_SystemMalloc/real_time/threads:16 121 ns 1016 ns 7249680
root@ecs-ec4a:~/cppMemoryPool/build# 指标定义分析
核心定义
-
1 次配对操作(Allocation Pair):即 1 次
allocate()+ 1 次deallocate()。在实际业务中,申请了内存就必须释放,因此以“完整生命周期”为单位最符合业务逻辑。 -
全系统总 QPS(System-wide Throughput):
$$\text{全系统 QPS} = \text{所有线程在 1 秒内共同完成的【配对操作】总次数}$$ -
单次配对延迟(Per-Pair Latency):
$$\text{单次配对延迟} = \frac{\text{线程数}}{\text{全系统 QPS}}$$
| 线程数 | Real Time (单次 Iteration 耗时) | 解释说明 | 全系统总 QPS | 单次 [分配+释放] 延迟 | 预估单次 allocate() 延迟 |
|---|---|---|---|---|---|
| 1 线程 | 164.0 ns |
单核无竞争 | 1.95 亿 ops/s | 5.12 ns |
2.56 ns |
| 2 线程 | 82.0 ns |
物理多核并行 | 7.80 亿 ops/s | 2.56 ns |
1.28 ns |
| 4 线程 | 41.1 ns |
物理 4 核吃满 | 31.14 亿 ops/s | 1.28 ns |
0.64 ns |
| 8 线程 | 40.5 ns |
8 逻辑核(开启超线程) | 63.21 亿 ops/s | 1.27 ns |
0.63 ns |
| 16 线程 | 38.5 ns |
超出逻辑核(时钟抢占) | 132.98 亿 ops/s | 1.20 ns |
0.60 ns |
测试代码
#include "memory.hpp"
#include <iostream>
#include <vector>
#include <thread>
#include <chrono>
#include <atomic>
#include <random>
#include <cassert>
#include <fstream>
#include <string>
#include <iomanip>
#include <unistd.h>
// 魔法数,用于检测内存踩踏(Corruption)
constexpr uint32_t MAGIC_NUMBER = 0xDEADBEEF;
struct Payload {
uint32_t magic;
uint32_t thread_id;
uint64_t seq;
char dummy[16]; // 填充数据,保证 Payload 体积
};
// 获取当前进程物理内存占用 (RSS, 单位: MB)
double get_process_rss_mb() {
std::ifstream statm("/proc/self/statm");
if (!statm.is_open()) return 0.0;
long pages = 0;
long rss_pages = 0;
statm >> pages >> rss_pages;
long page_size_kb = sysconf(_SC_PAGESIZE) / 1024;
return (rss_pages * page_size_kb) / 1024.0;
}
// 模拟真实高压业务的工作线程
void worker_thread(FixedSizeMemory& pool, int thread_id, std::atomic<bool>& stop_flag, std::atomic<uint64_t>& total_ops) {
std::mt19937 rng(1337 + thread_id);
constexpr std::size_t MAX_HOLD = 1024;
std::vector<Payload*> held_ptrs;
held_ptrs.reserve(MAX_HOLD);
uint64_t local_seq = 0;
while (!stop_flag.load(std::memory_order_relaxed)) {
// 1. 批量分配内存 (1 ~ 32 块)
std::size_t batch_size = (rng() % 32) + 1;
for (std::size_t i = 0; i < batch_size; ++i) {
void* p = pool.allocate();
if (p != nullptr) {
Payload* payload = new (p) Payload(); // placement new
payload->magic = MAGIC_NUMBER;
payload->thread_id = static_cast<uint32_t>(thread_id);
payload->seq = ++local_seq;
held_ptrs.push_back(payload);
}
}
total_ops.fetch_add(batch_size, std::memory_order_relaxed);
// 2. 随机决定是“释放部分内存”还是“继续持有”(制造动态水位波动)
if (!held_ptrs.empty()) {
// 如果手里的内存堆积太多(超过 512),优先大比例释放
std::size_t release_count = (held_ptrs.size() > 512) ?
held_ptrs.size() / 2 :
(rng() % (held_ptrs.size() + 1));
for (std::size_t i = 0; i < release_count; ++i) {
Payload* payload = held_ptrs.back();
held_ptrs.pop_back();
// 踩内存校验:如果 Magic 被篡改,直接崩溃
assert(payload->magic == MAGIC_NUMBER && "内存发生数据越界/踩内存!");
payload->~Payload();
pool.deallocate(payload);
}
}
// 3. 极短让出 CPU,模拟真实业务微小停顿
if (rng() % 10 == 0) {
std::this_thread::yield();
}
}
// 4. 线程退出前,把手里剩下的全部释放干净
for (Payload* payload : held_ptrs) {
assert(payload->magic == MAGIC_NUMBER && "内存发生数据越界/踩内存!");
payload->~Payload();
pool.deallocate(payload);
}
held_ptrs.clear();
// 手动刷新该线程的 TLS 缓存到 Page 中,确保退出时不残留
pool.flush_thread_cache();
}
int main(int argc, char* argv[]) {
// 默认跑 600 秒 (10分钟),命令行传参可指定跑多久
int duration_seconds = 600;
if (argc > 1) {
duration_seconds = std::atoi(argv[1]);
}
std::cout << "==========================================================================" << std::endl;
std::cout << " 内存池长跑稳定性 + 分段 QPS 性能衰退监测 (Soak Testing) " << std::endl;
std::cout << " 压测时长: " << duration_seconds << " 秒" << std::endl;
std::cout << "==========================================================================" << std::endl;
// 创建单块 64 字节,每页 1024 块的内存池
FixedSizeMemory pool(64, 1024);
unsigned int num_threads = std::thread::hardware_concurrency();
if (num_threads == 0) num_threads = 4;
std::cout << "启动压测线程数: " << num_threads << std::endl;
std::atomic<bool> stop_flag{false};
std::atomic<uint64_t> total_ops{0};
std::vector<std::thread> workers;
// 启动后台监控线程:每 10 秒监控一次分段 QPS 与内存占用
std::thread monitor_thread([&]() {
auto start_time = std::chrono::steady_clock::now();
uint64_t last_ops = 0;
while (!stop_flag.load(std::memory_order_relaxed)) {
// 每 10 秒统计一次区间 QPS
std::this_thread::sleep_for(std::chrono::seconds(10));
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - start_time).count();
uint64_t current_ops = total_ops.load(std::memory_order_relaxed);
uint64_t interval_ops = current_ops - last_ops;
double current_qps = interval_ops / 10.0; // 过去 10 秒内的平均 QPS
last_ops = current_ops;
double rss_mb = get_process_rss_mb();
std::size_t active_allocs = pool.allocated_count();
std::size_t pages = pool.page_count();
std::cout << "[" << std::setw(4) << elapsed << "s] "
<< "区间QPS: " << std::setw(12) << static_cast<uint64_t>(current_qps) << " ops/s | "
<< "累计操作: " << std::setw(12) << current_ops << " | "
<< "活动块: " << std::setw(5) << active_allocs << " | "
<< "Page数: " << std::setw(3) << pages << " | "
<< "RSS内存: " << std::fixed << std::setprecision(2) << rss_mb << " MB"
<< std::endl;
}
});
// 启动所有工作线程
for (unsigned int i = 0; i < num_threads; ++i) {
workers.emplace_back(worker_thread, std::ref(pool), i, std::ref(stop_flag), std::ref(total_ops));
}
// 主线程等待压测倒计时结束
std::this_thread::sleep_for(std::chrono::seconds(duration_seconds));
// 通知所有线程平滑退出
std::cout << "\n压测时间到,正在通知所有线程平滑退出并刷新 TLS..." << std::endl;
stop_flag.store(true, std::memory_order_relaxed);
for (auto& t : workers) {
if (t.joinable()) t.join();
}
if (monitor_thread.joinable()) {
monitor_thread.join();
}
std::cout << "\n================ 最终收尾与内存泄漏验证 ================" << std::endl;
std::cout << "总完成操作次数 : " << total_ops.load() << std::endl;
std::cout << "当前未归还内存块: " << pool.allocated_count() << std::endl;
std::cout << "最终申请 Page 数: " << pool.page_count() << std::endl;
// 终极断言:所有线程退出并 flush TLS 后,未归还分配数必须严格归零!
if (pool.allocated_count() == 0) {
std::cout << " SUCCESS: 长跑压测通过!0 内存泄漏,0 数据损坏,性能平稳!" << std::endl;
} else {
std::cerr << " ERROR: 压测失败!检测到内存泄漏!未归还块数: " << pool.allocated_count() << std::endl;
return 1;
}
return 0;
}测试数据
nohup: ignoring input
==========================================================================
内存池长跑稳定性 + 分段 QPS 性能衰退监测 (Soak Testing)
压测时长: 600 秒
==========================================================================
启动压测线程数: 8
[ 10s] 区间QPS: 389378654 ops/s | 累计操作: 3893786547 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 20s] 区间QPS: 389411745 ops/s | 累计操作: 7787903997 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 30s] 区间QPS: 390512243 ops/s | 累计操作: 11693026433 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 40s] 区间QPS: 389701668 ops/s | 累计操作: 15590043122 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 50s] 区间QPS: 389770212 ops/s | 累计操作: 19487745247 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 60s] 区间QPS: 390288194 ops/s | 累计操作: 23390627188 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 70s] 区间QPS: 389563709 ops/s | 累计操作: 27286264286 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 80s] 区间QPS: 389542351 ops/s | 累计操作: 31181687799 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 90s] 区间QPS: 390058793 ops/s | 累计操作: 35082275733 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 100s] 区间QPS: 390313934 ops/s | 累计操作: 38985415079 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 110s] 区间QPS: 389892869 ops/s | 累计操作: 42884343773 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 120s] 区间QPS: 390047514 ops/s | 累计操作: 46784818913 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 130s] 区间QPS: 389504280 ops/s | 累计操作: 50679861714 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 140s] 区间QPS: 389901886 ops/s | 累计操作: 54578880581 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 150s] 区间QPS: 390429693 ops/s | 累计操作: 58483177512 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 160s] 区间QPS: 390338964 ops/s | 累计操作: 62386567153 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 170s] 区间QPS: 390200460 ops/s | 累计操作: 66288571755 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 180s] 区间QPS: 390500037 ops/s | 累计操作: 70193572130 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 190s] 区间QPS: 389901181 ops/s | 累计操作: 74092583940 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 200s] 区间QPS: 389379158 ops/s | 累计操作: 77986375529 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 210s] 区间QPS: 390794075 ops/s | 累计操作: 81894316284 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 220s] 区间QPS: 390596642 ops/s | 累计操作: 85800282705 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 230s] 区间QPS: 390166316 ops/s | 累计操作: 89701945867 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 240s] 区间QPS: 390626278 ops/s | 累计操作: 93608208655 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 250s] 区间QPS: 390326427 ops/s | 累计操作: 97511472925 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 260s] 区间QPS: 389842223 ops/s | 累计操作: 101409895161 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 270s] 区间QPS: 390673486 ops/s | 累计操作: 105316630029 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 280s] 区间QPS: 390550282 ops/s | 累计操作: 109222132854 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 290s] 区间QPS: 390235222 ops/s | 累计操作: 113124485075 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 300s] 区间QPS: 390827430 ops/s | 累计操作: 117032759376 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 310s] 区间QPS: 389852471 ops/s | 累计操作: 120931284095 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 320s] 区间QPS: 390444219 ops/s | 累计操作: 124835726294 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 330s] 区间QPS: 390644064 ops/s | 累计操作: 128742166935 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 340s] 区间QPS: 390716592 ops/s | 累计操作: 132649332861 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 350s] 区间QPS: 390615132 ops/s | 累计操作: 136555484187 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 360s] 区间QPS: 390480129 ops/s | 累计操作: 140460285477 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 370s] 区间QPS: 390037826 ops/s | 累计操作: 144360663742 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 380s] 区间QPS: 390228243 ops/s | 累计操作: 148262946173 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 390s] 区间QPS: 390519860 ops/s | 累计操作: 152168144775 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 400s] 区间QPS: 390632474 ops/s | 累计操作: 156074469523 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 410s] 区间QPS: 390515007 ops/s | 累计操作: 159979619602 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 420s] 区间QPS: 390556951 ops/s | 累计操作: 163885189121 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 430s] 区间QPS: 389863889 ops/s | 累计操作: 167783828011 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 440s] 区间QPS: 390131324 ops/s | 累计操作: 171685141260 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 450s] 区间QPS: 390116021 ops/s | 累计操作: 175586301478 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 460s] 区间QPS: 390242640 ops/s | 累计操作: 179488727881 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 470s] 区间QPS: 389877631 ops/s | 累计操作: 183387504197 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 480s] 区间QPS: 389350833 ops/s | 累计操作: 187281012527 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 490s] 区间QPS: 390128285 ops/s | 累计操作: 191182295384 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 500s] 区间QPS: 390386441 ops/s | 累计操作: 195086159797 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 510s] 区间QPS: 390374202 ops/s | 累计操作: 198989901826 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 520s] 区间QPS: 390599641 ops/s | 累计操作: 202895898238 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 530s] 区间QPS: 390546578 ops/s | 累计操作: 206801364027 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 540s] 区间QPS: 390427997 ops/s | 累计操作: 210705643997 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 550s] 区间QPS: 390017848 ops/s | 累计操作: 214605822481 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 560s] 区间QPS: 390136596 ops/s | 累计操作: 218507188441 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 570s] 区间QPS: 390206555 ops/s | 累计操作: 222409253991 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 580s] 区间QPS: 390478279 ops/s | 累计操作: 226314036782 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
[ 590s] 区间QPS: 390382514 ops/s | 累计操作: 230217861927 | 活动块: 2048 | Page数: 2 | RSS内存: 1.96 MB
压测时间到,正在通知所有线程平滑退出并刷新 TLS...
[ 600s] 区间QPS: 389730517 ops/s | 累计操作: 234115167099 | 活动块: 0 | Page数: 2 | RSS内存: 3.89 MB
================ 最终收尾与内存泄漏验证 ================
总完成操作次数 : 234115167099
当前未归还内存块: 0
最终申请 Page 数: 2
SUCCESS: 长跑压测通过!0 内存泄漏,0 数据损坏,性能平稳!
同等定义下
| 时间节点 | 监控输出的区间 QPS | 累计总操作数 | 活动内存块 / Page数 | RSS 物理内存 | 全系统总 QPS | 单次 [配对+伪业务] 综合延迟 |
|---|---|---|---|---|---|---|
| 10s | 389,378,654 ops/s |
3,893,786,547 |
2048 / 2 | 1.96 MB | 3.89 亿 ops/s | 20.55 ns |
| 100s | 390,313,934 ops/s |
38,985,415,079 |
2048 / 2 | 1.96 MB | 3.90 亿 ops/s | 20.50 ns |
| 300s (半程) | 390,827,430 ops/s |
117,032,759,376 |
2048 / 2 | 1.96 MB | 3.90 亿 ops/s | 20.47 ns |
| 500s | 390,386,441 ops/s |
195,086,159,797 |
2048 / 2 | 1.96 MB | 3.90 亿 ops/s | 20.49 ns |
| 600s (终点) | 389,730,517 ops/s |
234,115,167,099 |
0 / 2 | 3.89 MB | 3.89 亿 ops/s | 20.53 ns |
Valgrind Memcheck输出如下,Asan检测无输出
两种工具的检测均没有内存泄漏
==16305==
==16305== HEAP SUMMARY:
==16305== in use at exit: 0 bytes in 0 blocks
==16305== total heap usage: 1,426 allocs, 1,426 frees, 21,480,445 bytes allocated
==16305==
==16305== All heap blocks were freed -- no leaks are possible
==16305==
==16305== For lists of detected and suppressed errors, rerun with: -s
==16305== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
root@ecs-ec4a:~/cppMemoryPool/build#