时间代价
所有测试的中间, 均sleep(1), 否则耗时大幅降低, 不具有参考性.
原因(极大可能是如此):
- 和线程的调度有关
- 虽然线程(进程)切换时, 会保存寄存器和栈上的内容. 但是我猜测, 许多辅助寄存器没有保存, 不得不重新计算. 所以, 自旋锁是一种很棒的东西, 当确认自旋的平均时间, 小于因为线程切换损失的时间时.
time
使用std::chrono::steady_clock::now(), 对比时间的代价, 大约为0.3us
time(NULL)的代价约为0.3us.
for(int i = 0;i<10;i++){time(NULL);}的代价为0.5us(for占据了0.1us), 难道短时间内调用time(NULL)的代价极低?
printf
std::cout << “hello” 的代价约为10us.
std::cout<<“hello”<<std::end;的代价约为50us.
printf(“hello\n”)的代价为30us.
for
for(i=0;i<1;i++){}的代价为0.05us
for(i=0; i<10;i++){}的代价为0.1us
for(i=0; i<100;i++){}的代价为1us (实际在0.8左右)
for(i=0; i<100;i++){}的代价为10us(实际在8左右)
可以记忆, for100次循环, 需要话费1us.
malloc
在glibc下测试, 单线程
int* pa=new int; 耗时4us.
for(int i=0; i<10;i++){intpa = new int;} 耗时4us
for(int i=0; i<100;i++){intpa = new int;} 耗时25us
for(int i=0; i<1000;i++){int*pa = new int;} 耗时150us
- 结论
- new 是us级的.
- 当极短时间内连续new相同长度(每次测试之间sleep), 耗时会降低一个数量级(10倍), 原因可能是内核里slab刚开辟的还在, 不用新的slab; new 不同长度时, 耗时无明显变化
int* pa=new int[i];
i < 250, 耗时较少, 可能因为在slab中, 仅当需要新的slab时, 耗时增加.
i > 250时, 耗时15-30us
for(int i=0; i<100;i++){intpa = new int[i10];} 耗时45us
slab估计预先分配好了, 耗时增加不明显
内存缺页
int* p1 = new int[10];
int* p2 = new int[100 * 1024];
p1[8] = 10; 耗时忽略(太小以至于无法统计)
p2[50 * 1024] = 10; 耗时6us
- 结论
- malloc小地址时, 位于堆上;大地址时, mmap位于堆和栈中间的映射区;
- 当p2时, 触发缺页中断, 故耗时增加
磁盘file
io空闲时.
open(); 耗时20us
close(); 耗时3us
是否阻塞对磁盘IO无意义
write(10000);耗时50us
write(1000);耗时35us
write(100);耗时35us
write(10);耗时35us
write(1);耗时35us
read(10000);耗时24us
read(1000);耗时13us
read(1);耗时6us
- 结论
- read的耗时要小于write, 大概1/3.
- 小于最佳io块大小时, 耗时变化不明显
string
string a = “hello wrold”; 耗时4us
- 字符串长度对耗时影响很小(限度内)
string b = a; 耗时1us - 写时复制的优化所致
a += “hello”; 耗时2us
容器
不考虑容器背后数据结构的性能, 只考虑容器实现代码的额外代价
map
构造函数,耗时0.5us
成功插入(插入失败耗时1us)
map[“hello”] = “world”; 耗时20us
map[1]=2;耗时10us
- key是string和int, 竟然耗时相同? 都要放在堆上, 所以??
查找,耗时1us
unordered_map
构造函数,耗时1us
成功插入(插入失败耗时1us)
map[“hello”] = “world”; 耗时20us
map[1] = 2;耗时10us
查找, 耗时1us
- 结论
数量不多是, 插入, 查找性能相近
vector
插入, 耗时2us
- 结论, 会有较大起伏, 原因未知
list
插入耗时2us
锁
mutex
std::mutex mtx;
无阻塞情况下
mtx.lock() 耗时1.5us.
mtx.unlock() 耗时0.5us.
- 结论
- 锁本身实现的耗时在2us左右, 不是很大.
thread
std::thread(fun), 耗时80ms.
不sleep, 耗时降至15ms.
- 注: 线程创建还是比较耗时间的.
memcpy
memcpy(100), 耗时0.1us
memcpy(1000), 耗时1us.
memcpy(10000), 耗时20us.
memcpy(1000 * 100), 耗时300us.
memcpy(1000 * 1000), 耗时3000us.
- 注
- 为什么延迟写入对于memcpy影响不大?
- 随着长度的增加, 耗时指数上升.写100万, 耗时3毫秒, 不低了.
进程
system(""), 耗时2500us, 毫秒级别的, 不少了.
system(“ls”), 大概10个目录和文件, 耗时6000us.
system(“tree”), 100个目录, 300个文件, 耗时20ms.
- 注:
- system还是以一个比较奢侈的函数啊. 除非命令本身耗时在几十毫秒, 才可以调用
mmap
15us, 待测试
=====================================