io分为缓冲io和无缓冲io,缓冲io是将数据放入用户进程空间的缓冲区,通过数据读取函数scanf等在缓冲区读取函数,printf甚至要达到固定的缓冲条件才能输出,如换行符、缓冲区大小1024、fflush这些,当然这里不介绍这些,无缓冲io则进程空间没有缓冲,只存在系统的内核缓冲区,现在我们进行一下缓冲io的读取速度对比
样例
#include <stdio.h>
#include <chrono>
#include <iostream>
#include <unistd.h>
const int MX = 100000000;
int main()
{
char c;
char *buf;
buf = (char *)malloc(sizeof(char) * 9000);
for (int i = 1; i <= 8192; i <<= 1)
{
int k = MX % i == 0 ? 0 : 1;
auto start = std::chrono::system_clock::now();
for(int j = 0; j < MX / i + k; ++j)
{
// printf("f");
read(STDIN_FILENO, buf, i);
// scanf("%c", &c);
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
./a.out < data 运行时间对比
1:53980
2:27307
4:13865
8:6898
16:3549
32:1749
64:949
128:512
256:262
512:158
1024:91
2048:63
4096:49
8192:50
可发现随着缓冲区的增大速度逐渐变快,缓冲小的时候到缓冲区来回切换较多,就比如车子可以拉十块砖但只拉了一块砖,走了十趟,到了4096为巅峰,至于为什么是4096是巅峰我猜测是因为内存分页的缘故,我们的系统一般都是按4kb进行内存分页的,所以4096相当于卡车装的总数
现我们将有内核缓冲读取改为无内核缓冲读取测试
添加代码
void setnonblocking(int fd)
{
int flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
if(fcntl(fd, F_SETFL, flags) < 0)
perror("fcntl error");
}
setnonblocking(STDIN_FILENO);
./a.out < data
1:52624
2:27435
4:14176
8:7501
16:3943
32:1963
64:1072
128:611
256:378
512:213
1024:160
2048:84
4096:64
8192:62
从数据上看速度有些变慢,因为他要跑到内核缓冲区读取数据,路程变远了,所以造成了速度变慢了,但他不会造成阻塞,用它在网络io中使用些微的耗时增加就远不如网络阻塞的耗时增加,不过那时又会造成缓冲区满等问题,这里就不细说了
本文到此结束,有问题欢迎指出