2011-12-14 01:13:37| 分类: Linux/Windows | 标签: |举报 |字号大中小 订阅
自从工作了,再也没有更新过这个技术博客。一来工作了没什么好写的,二来确实也挺忙。最近稍微有点空闲,先开一个写一点吧。
记得在公司做新人习题的时候,题目是通过网络和本地分别读取一个约12G的大文件,从中读取每一行,对每行特定的几个字段,调用分词库分词并统计词频。当时遇到一个很郁闷的事情就是,12G的文件读取一次了之后,系统中有缓存;然后第二次再次运行的时候,因为有缓存的影响,性能差异挺大(本地读取几乎三倍性能差距)。但是当时的开发机器上,自己只有普通用户权限,无法通过修改/proc/sys/vm/drop_cache来达到目的。所以最后还是没有搞定这个问题。
后来发现Linux的一个系统调用:
#include <fcntl.h>
int posix_fadvise(int fd, off_t offset, off_t len, int advice);
有一个选项POSIX_FADV_DONTNEED可以做这件事情。网上找了下好像挺多人也遇到这个无问题的,所以就把我的解决办法放到这里。于是写了一个小工具,一次批量清除文件在系统中的缓存。
#define _FILE_OFFSET_BITS 64 #define __USE_XOPEN2K #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <getopt.h> const struct option dcache_options[] = { {"sync",0,NULL,'s'}, {"help",0,NULL,'h'}, {NULL,0,NULL,0} }; void usage(char* proc_name,int exit_code) { printf("dcache is an utility to drop file cache.\n" "usage:%s [-s] file\n" "\t-s,--sync, sync data before drop cache.\n" "\t-h,--help, print help.\n",proc_name); exit(exit_code); } int dcache(int fd, int sync_data) { off_t off,len; struct stat buf; int save_errno; save_errno = errno; if (sync_data) { if (fsync(fd) < 0) { printf("%s\n",strerror(errno)); errno = save_errno; return -1; } } if (fstat(fd,&buf) < 0) { printf("%s\n",strerror(errno)); errno = save_errno; return -1; } off = 0; len = buf.st_size; if (posix_fadvise(fd,off,len,POSIX_FADV_DONTNEED) < 0) { printf("%s\n",strerror(errno)); errno = save_errno; return -1; } return 0; } int main(int argc, char* argv[]) { int c,fd; char* file; int long_index = 0; int print_help = 0; int sync_data = 0; while ((c = getopt_long(argc,argv,"sh",dcache_options,&long_index)) != -1) { switch (c) { case 's': sync_data = 1; break; case 'h': print_help = 1; break; default: printf("unknown option -%c\n",c); usage(argv[0],EXIT_FAILURE); break; } } if (print_help) { usage(argv[0],EXIT_SUCCESS); } if (optind >= argc) { printf("file name required\n"); exit(EXIT_FAILURE); } for (c = optind; c < argc; ++c) { file = argv[c]; if ((fd = open(file,O_RDWR)) < 0) { printf("open %s failed.\n",file); } else { printf("drop cache of %s %s.\n",file,dcache(fd,sync_data) == 0?"success":"failed"); close(fd); } } exit(EXIT_SUCCESS); }
使用方法:
dcache -h
dcache is an utility to drop file cache.
usage:dcache [-s] file
-s,--sync, sync data before drop cache.
-h,--help, print help.
--sync选项用于将数据写回硬盘。因为man posix_fadvise说了:
POSIX_FADV_DONTNEED attempts to free cached pages associated with the specified region. This is useful, for example, whilestreaming large files. A program may periodically request the kernel to free cached data that has already been used, so that more useful cached pages are not discarded instead.
Pages that have not yet been written out will be unaffected, so if the application wishes to guarantee that pages will be
released, it should call fsync(2) or fdatasync(2) first.
说POSIX_FADV_DONTNEED只释放clean页面,dirty页面,并不受此影响,所以如果你是写了文件而没有用--sync选项的话,那么脏页面不会被释放,缓存也就不会被释放掉啦。所以使用dcache的时候应当清楚何时使用--sync选项。
在公司机器上做了一下实验,用一个4kw+行的文本文件,8GB做实验。
先 free -m看一下cached总数为48345M
total used free shared buffers cached
Mem: 64334 50469 13864 0 196 48345
然后wc -l 5kw.txt,读取一遍文件,wc输出文件行数为
44731963 5kw.txt
然后再free -m一遍看内存情况:
total used free shared buffers cached
Mem: 64334 58802 5532 0 204 56670
可以看到,cached page增加了8325M,与我们文件大小接近。然后使用dcache工具释放对应文件在系统中的缓存:
dcache 5kw.txt
drop cache of plsi_index.5kw.txt success.
再次使用free -m看到cached果然被释放了8GB,说明工具确实起到了作用。
free -m
total used free shared buffers cached
Mem: 64334 50477 13856 0 204 48346