大文件重定向和管道的效率对比
微博上的@拉风_zhang提出了个问题:
@淘宝褚霸 请教个问题,#1. cat huge_dump.sql | mysql -uroot ;#2. mysql -uroot < huge_dump.sql ;#1效率要高,在linux中通过管道传输 和 < 这种方式有什么差别呢?谢谢!#AskBaye#
这个问题挺有意思的,我的第一反应是:
没比较过,应该是一样的,一个是cat负责打开文件,一个是bash
这种场景在MySQL运维操作里面应该比较多,所以就花了点时间做了个比较和原理上的分析:
我们先构造场景:
首先准备一个程序b.out来模拟mysql对数据的消耗:
$ cat b.c #include <stdio.h> int main(int argc, char *argv[]) { char buf[4096]; while(fread(buf, sizeof(buf), 1, stdin) > 0); return 0; } $ gcc -o b.out b.c $ ls|./b.out
编译好再顺手我们的程序功能是正确的:纯消耗流。
再来写个systemtap脚本用来方便观察程序的行为。
$ cat test.stp function should_log(){ return (execname() == "cat" || execname() == "b.out" || execname() == "bash") ; } probe syscall.open, syscall.close, syscall.read, syscall.write, syscall.pipe, syscall.fork, syscall.execve, syscall.dup, syscall.wait4 { if (!should_log()) next; printf("%s -> %s\n", thread_indent(0), probefunc()); } probe kernel.function("pipe_read"), kernel.function("pipe_readv"), kernel.function("pipe_write"), kernel.function("pipe_writev") { if (!should_log()) next; printf("%s -> %s: file ino %d\n", thread_indent(0), probefunc(), __file_ino($filp)); } probe begin { println(":~") }
这个脚本重点观察几个系统调用的顺序和pipe的读写情况,
然后再准备个419M的大文件huge_dump.sql,在我们几十G内存的机器很容易在内存里放下:
$ sudo dd if=/dev/urandom of=huge_dump.sql bs=4096 count=102400 102400+0 records in 102400+0 records out 419430400 bytes (419 MB) copied, 63.9886 seconds, 6.6 MB/s
因为这个文件是用bufferio写的,所以它的内容都cache在pagecahce内存里面,不会涉及到磁盘。
好了,场景齐全了,我们接着来比较下二种情况下的速度:
Read more…
Recent Comments