read()/fread()/mmap()执行效率对比
一、 read()/fread()/mmap()执行效率对比
系统调用read.c: #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h> int main()
{
int fd = open("linux_logo.pnm", O_RDONLY);
int num = ;
char buff[]; do{
num = read(fd, buff, );
}while(num != ); close(fd); return ;
}
库函数fread.c:
#include <stdio.h>
#include <stdlib.h> int main()
{
FILE *fp = fopen("linux_logo.pnm", "r");
int num = ;
char buff[]; do{
num = fread(buff, , , fp);
}while(num != ); close(fp); return ;
}
使用mmap进行文件映射:
#include <fcntl.h> //open
#include <sys/mman.h> //mmap
#include <sys/types.h> //fstat
#include <sys/stat.h>
#include <unistd.h> int main()
{
int i;
char buff[];
struct stat statue; int fd = open("linux_logo.pnm", O_RDONLY); fstat(fd, &statue); char *pm = mmap(NULL, statue.st_size, PROT_READ, MAP_SHARED, fd, ) ; for(i=; i<statue.st_size; i++)
{
buff[] = pm[i];
} munmap(pm, statue.st_size); close(fd); return ;
}
编译后三者执行时间:
time ./read
real 0m2.830s
user 0m0.287s
sys 0m2.178s time ./fread
real 0m0.088s
user 0m0.082s
sys 0m0.008s time ./mmap
real 0m0.026s
user 0m0.008s
sys 0m0.005s ll linux_logo.pnm
-rw-r--r--. root root Aug : linux_logo.pnm
1. ./read的sys(内核态时间)是./fread的2.178/0.008=272倍,而1152015/4096(细页大小为4kB)=281,非常接近,由知识背景推测出可能./read进行的系统调用次数为./fread的4096倍(因为fread()是带缓冲的,每次可能读取1页数据缓存起来,而read()不带缓冲,每次都从硬盘重新读取)
证明:
strace ./read 打印信息如下:
read(3, "\375", 1) = 1
read(3, "\375", 1) = 1
read(3, "\375", 1) = 1
read(3, "\375", 1) = 1
read(3, ^C <unfinished ...>
strace ./fread 打印信息如下:
read(3, "=\211+=\210+=\206+<\201+8\200/8m%)Y\31\31b)\"tB7{QAs"..., 4096) = 4096
read(3, "\223\234\211\223\234\211\223\234\211\224\235\212\225\236\213\230\241\214\227\240\213\225\236\211\224\235\"..., 4096) = 4096
read(3, "YHzYHxWFuTCvRBvRBuP>rM;uR?uR?sP="..., 4096) = 4096
read(3, "Z\231|\\\227zZ\226y[\231|^\232\177a\232\177a\232\201c\237\206h\245\214n\250\217q\247"..., 4096) = 1039
read(3, "", 4096) = 0
exit_group(0) = ?
[root@sfl sys_call]# ^C
可以看出./read每次执行read系统调用都只读取1字节,而./fread中的fread()的read系统调用每次读取4096字节,证明了自己的猜测。
2.在频繁读取问价的情况下,mmap()进行文件映射时执行效率最高的,因为它不需要频繁进行系统调用,可以像操作内存一样操作文件。
3.系统调用是相当耗费时间的,注意适当使用系统调用。
二、相关命令学习
1.time(测量)命令
time命令常用于测量一个命令的运行时间,注意不是用来显示和修改系统时间的(这是date命令干的事情)
real 0m5.064s <== 实际使用时间(real time,算上了等待、休眠等的时间)
user 0m0.020s <== 用户态使用时间(the process spent in user mode)
sys 0m0.040s <== 内核态使用时间(the process spent in kernel mode)
man time后根据说明带参数操作是不成功的,原因是:这个time使用的是shell脚本里面的,是不带命令行参数的,而可执行程序是带命令行参数的
type -a time /*列出time命令的类型,发现有两种*/
time is a shell keyword /*shell脚本中也提供了这个命令,而且默认是使用shell脚本中的*/
time is /usr/bin/time /*命令行程序*/
使用可执行程序的time即可带命令行参数,标识将./read的执行写入到test.txt中而不是command窗口,-v友好的显示;注意这里的time是测量的意思,还会列出很多其他的信息。
/usr/bin/time -o test.txt -v ./read
无法将time的输出信息重定向到文件里面,为什么?因为time是shell的关键字,shell做了特殊处理,它会把time命令后面的命令行作为一个整体来进行处理,在重定向时,实际上是针对后面的命令来的,time命令本身的输出并不会被重定向的,两种解决方法:
{ time command-line; } 2>file 注意分隔符的使用。
(time command-line) 2>file 这里time紧贴着小括号(也可以的,命令行结束也不必带分号。
2.strace命令
作用:在最简单的情况下,strace运行指定的命令,直到它退出。它拦截并记录由进程调用的系统调用和进程接收到的信号。 每个系统调用的名称,其参数及其返回值都以标准错误或-o选项指定的文件打印。
文件hello.c #include <stdio.h> void main()
{
printf("hello world!\n");
} gcc hello.c -o hello
执行命令:strace ./hello 打印如下信息:
execve("./pp", ["./pp"], [/* 57 vars */]) =
brk() = 0x9dfe000
mmap2(NULL, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -, ) = 0xb780b000
access("/etc/ld.so.preload", R_OK) = - ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY) =
fstat64(, {st_mode=S_IFREG|, st_size=, ...}) =
mmap2(NULL, , PROT_READ, MAP_PRIVATE, , ) = 0xb77ec000
close() =
open("/lib/libc.so.6", O_RDONLY) =
read(, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@\236\201\0004\0\0\0"..., ) =
fstat64(, {st_mode=S_IFREG|, st_size=, ...}) =
mmap2(0x803000, , PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, , ) = 0x803000
mprotect(0x98c000, , PROT_NONE) =
mmap2(0x98d000, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, , 0x189) = 0x98d000
mmap2(0x990000, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -, ) = 0x990000
close() =
mmap2(NULL, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -, ) = 0xb77eb000
set_thread_area({entry_number:- -> , base_addr:0xb77eb6c0, limit:, seg_32bit:, contents:, read_exec_only:, limit_in_pages:, seg_not_present:, useable:}) =
mprotect(0x98d000, , PROT_READ) =
mprotect(0x7fb000, , PROT_READ) =
munmap(0xb77ec000, ) =
fstat64(, {st_mode=S_IFCHR|, st_rdev=makedev(, ), ...}) =
mmap2(NULL, , PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -, ) = 0xb780a000
write(, "hello world!\n", ) =
exit_group() = ?
现在知道为什么包含glibc中相应的头文件就能使用里面的函数了吧,它在库/lib/libc.so.6里面,包含头文件只是为了能通过编译期而已。
参考:http://www.cnblogs.com/syntax/archive/2012/11/05/2755129.html
read()/fread()/mmap()执行效率对比的更多相关文章
- Bulk Insert & BCP执行效率对比
我们以BCP导出的CSV数据文件,分别使用Bulk insert与BCP导入数据库,对比两种方法执行效率 备注:导入目标表创建了分区聚集索引 1.BCP导出csv数据文件 数据量:15000000行, ...
- Snapman系统中TCC执行效率和C#执行效率对比
Snapman集合了TCC编译器可以直接编译执行C语言脚本,其脚本执行效率和C#编译程序进行效率对比,包括下面4方面: 1.函数执行效率 2.数字转换成字符串 3.字符串的叠加 4.MD5算法 这是C ...
- Bulk Insert & BCP执行效率对比(续)
上回由于磁盘空间(约70G)不足,导致Bulk Insert和BCP导入中途失败:今次统一一些操作,以得到Bulk insert与BCP分别执行效率: 1. 15435390笔数据,21.7G csv ...
- Linq的执行效率及优化
描述:项目中使用了linq,发现写的顺序不一样最后的结果也不一样,效率也不一样. Linq的执行效率对比 List<int> source = new List<int>(); ...
- OCIlib的几个函数的执行效率(附上pro*c的性能对比)
ocilib提供了以下几个执行sql语句的函数 OCI_ExecuteStmt/OCI_ExecuteStmtFmt 使用没有绑定变量的语句 OCI_Execute 使用有绑定变量的语句 OCI_Im ...
- 列表推导式对比For循环执行效率
我们在前面的学习中都知道,如果把1-10以内的元素追加到一个新的列表表中,如果使用for循环我们可以这么做: a = [] for i in range(1,11): a.append(i) prin ...
- SQL执行效率和性能测试方法总结
对于做管理系统和分析系统的程序员,复杂SQL语句是不可避免的,面对海量数据,有时候经过优化的某一条语句,可以提高执行效率和整体运行性能.如何选择SQL语句,本文提供了两种方法,分别对多条SQL进行量化 ...
- (转)对《30个提高Web程序执行效率的好经验》的理解
阅读了博客园发布的IT文章<30个提高Web程序执行效率的好经验>,这30条准则对我们web开发是非常有用的,不过大家可能对其中的一些准则是知其然而不知其所以然. 下面是我对这些准则的理解 ...
- [转]SQLServer SQL执行效率和性能测试方法总结
本文转自:http://www.zhixing123.cn/net/27495.html 对于做管理系统和分析系统的程序员,复杂SQL语句是不可避免的,面对海量数据,有时候经过优化的某一条语句,可以提 ...
随机推荐
- (转)不要自称是程序员,我十多年的 IT 职场总结
其他: 我是一名程序员,工作很努力,为什么绩效还总是垫底? 外企,中年失业何去何从? 来公司半年了,也悟出了一些道理. 如果我可以给每个工程教育增加一门课,它不会涉及编译器.门电路或是时间复杂度,而是 ...
- mongoDB——自动分片(转)
原文地址:http://www.lanceyan.com/tech/arch/mongodb_shard1.html 在系统早期,数据量还小的时候不会引起太大的问题,但是随着数据量持续增多,后续迟早会 ...
- JQuery.Ajax()的data参数传递方式
最近,新学c# mvc,通过ajax post方式传递数据到controller.刚开始传递参数,controller中总是为null.现记录一下,可能不全,纯粹记个学习日记. 重点在于参数的方式,代 ...
- python-day18--匿名函数
一.lambda表达式 1.匿名函数的核心:一些简单的需要用函数去解决的问题,匿名函数的函数体只有一行 2.参数可以有多个,用逗号隔开 3.返回值和正常的函数一样可以是任意的数据类型 4.练习: 请把 ...
- JDBC连接SQLSERVER
package xhs;import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; im ...
- ORACLE workflow审批界面显示附件信息和附件的下载链接(转)
原文: ORACLE workflow审批界面显示附件信息和附件的下载链接 EBS获取附件URL 代码如下: CREATE OR REPLACE PACKAGE cux_attachment_util ...
- 对称点line
2 线 题⽬描述 有一天rax看到了男神,有时可爱美丽的她派ypq去把yyqx抓回来给rax欣赏,但ypq和yyqx间隔了一条线,她必须跳到yyqx以前待得点的对称点才有可能抓到yyqx给出⼀条直线, ...
- forget word out2
1★ dictionary / dik ʃ ən əri dict 2★ fy => faction f æk ʃ ən 派别
- Jquery中bind(), live(), on(), delegate()四种注册事件的优缺点,建议使用on()
jquery中注册的事件,注册事件很容易理解偏差,叫法不一样.我第一反应就是如何添加事件,使用onclick之类的,暂时不讨论js注册事件的方法. 也看到园内前辈写过相关的帖子,但不是很详细,我找到了 ...
- [转载]oracle游标概念讲解
原文URL:http://www.2cto.com/database/201203/122387.html ORACLE游标概念讲解 什么是游标? ①从表中检索出结果集,从中每次指向一条记录进行交互 ...