既然我们想做比较靠谱的性能测试,首先要知道如何准确测量一段代码的执行时间
此时,寄出了自己的windows 核心编程–7.6 有对于线程执行时间的获取的描述
#include <windows.h>
#include <assert.h>
#include "CElapsedMicroseconds.h"
static BOOL g_bInitFrequncy = QueryPerformanceFrequency(&CElapsedMicroseconds::m_Frequency);
CElapsedMicroseconds::CElapsedMicroseconds()
{
assert(g_bInitFrequncy);
// 避免被中断
SetProcessPriorityBoost(GetCurrentProcess(), true);
assert(QueryPerformanceCounter(&m_StartingTime));
}
LARGE_INTEGER CElapsedMicroseconds::GetElapsedMicroseconds()
{
LARGE_INTEGER EndingTime = {};
LARGE_INTEGER ElapsedMicroseconds = {};
assert(QueryPerformanceCounter(&EndingTime));
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - m_StartingTime.QuadPart;
ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= m_Frequency.QuadPart;
m_StartingTime = EndingTime; // 更新最后的执行时间
return ElapsedMicroseconds;
}
CElapsedMicroseconds::~CElapsedMicroseconds()
{
SetProcessPriorityBoost(GetCurrentProcess(), false);
}
这个文章,尝试梳理一下定制内存管理器的必要性以及测试内存allocator 的方法
- 必要性
- 当我们无脑的调用new 和 delete,或者malloc free 的时候,通过之前的代码看到,显然使用的是系统默认堆.
- 而多线程环境下,如果全部程序都使用这种无脑的方法,一个是需求种类复杂,大小导致,长时间执行必然导致内存碎片,内存申请和释放都将消耗很长的时间
- 另一方面,多线程环境下,对于同一个堆的同步访问将导致大量的时间
- 长时间运行的系统,分配模式需要保持低碎片,否则时间越久,碎片将导致系统无法继续执行。
- 系统调用,进内核、出内核,将消耗大量时间
- 优化allocator 的方向
- 参考https://www.codeproject.com/Articles/1083210/An-Efficient-Cplusplus-Fixed-Block-Memory-Allocato
- Heap blocks
全新块的申请是new 从process heap 中申请的,free 的时候,放入了free-list,再次申请的时候悠闲从free-list 申请,没有再去new(后进先出,提高重复利用率) - Heap pool
通过 new 从process heap 申请一个单独的池,之后通过这个pool 申请内存 - Static pool
使用一个静态的内存池,通常是一块比较大的静态内存,来存储所有的内存块。该静态内存池后续被用来申请内存。
heap pool 和 static pool 模式提供了固定申请执行时间。heap blocks可能有额外的查找和new 操作。
- 阅读了网络上一些内存管理器的文章后发现,大部分的实现,都是将内存申请时限为:
union{
void* next;
char pData[size];
}
通过上面的这种方式,实现了memory pool 的概念,再加上一些锁,优化的最佳的实现也就是锁的实现。
-
bitmap 的方法表达内存是否被占用,申请和释放都使用比较短的时间
-
通过增加heap 的个数,一方面减少多线程申请和释放的竞争,另一方面,减少内存相互的影响,提高多线程环境下申请和释放的速度。
优化的具体方法,放在下一届,下面先想一下测试方法和用例,否则写出来也不知道好坏
内存测试框架的要求,想要测试的alloctor需要实现特定的内存申请接口,统一测试方法
接口设计的要求:
- 支持多线程环境测试
- 支持测试原生的malloc free,new delete 测试
- 支持内存碎片类型的申请释放操作的测试
- 支持固定大小内存块的频繁申请释放(可能特定场景就会是这种,看哪种实现效率高)
- 单进程测试单独的小功能, 避免初始地址空间不同带来的影响
- 测试进程都以最高优先级运行,保证测试的可信度
- 申请和释放分别计时
- 数组类型的申请、释放操作计时
- 多次执行取平均
- 对比boost 的实现
- 是否需要在非必要的时候,释放空闲的整块的大块的内存
下一个开始写代码了