1
angelface 2015-12-05 10:49:21 +08:00
iNotify
|
2
angelface 2015-12-05 10:50:06 +08:00
|
3
RemRain 2015-12-05 10:53:22 +08:00 via iPhone
tail -f
程序实现的话, 2.6.32 内核以上用 inotify ,也可以直接用 libev |
4
clino 2015-12-05 11:00:42 +08:00
tail -f +1
|
5
xufang 2015-12-05 11:09:15 +08:00
awk 比 perl 要快的,楼主你没用对。
不信的话,楼主可以把你这个发到 ChinaUnix 的 Shell 板块,一堆人会给出更快的方案。 不过我现在喜欢用 golang 来做这样的事情,因为楼主你注意到没有,这些脚本写得再高效,也只能单核运行,很难利用多核上。 而 golang 的话,天然支持多核,用起来很方便。 http://rodaine.com/2015/04/async-split-io-reader-in-golang 用这种模式处理大文件话,立马层次就不一样了。 |
6
xufang 2015-12-05 11:09:50 +08:00
楼上给出 tail 的,明显是看帖不回帖的,楼主不用理他们。
|
9
xufang 2015-12-05 11:19:30 +08:00
而且 golang 的正则引擎虽然残废不完备,但是比较快。秒杀了很多脚本语言。
具体可以见 russ cox (golang 主要贡献者)的论文 《 Regular Expression Matching Can Be Simple And Fast 》 https://swtch.com/~rsc/regexp/regexp1.html 这标题,啧啧,狠狠的打脸啊。 |
10
skydiver 2015-12-05 11:22:34 +08:00
@vus520 可以。 tail -n +N 就是从头第 N 行开始,想从头开始直接 tail -f -n +1 就可以了
|
12
skydiver 2015-12-05 11:25:10 +08:00
@xufang 吹 Go 没关系,用不着靠贬低 tail 来说事儿,不觉得拿 Go 和 tail 比太 low 了么。
另外不要养成没事儿扣帽子的习惯。 |
14
skydiver 2015-12-05 11:28:08 +08:00
@xufang 另外 lz 题目里写了最好是命令,回复 tail 怎么就成了回帖不看贴了
哦,你说的看贴不回贴。我们这不是回帖了么,怎么叫不回贴了 |
16
xufang 2015-12-05 11:29:09 +08:00
|
18
skydiver 2015-12-05 11:31:41 +08:00
|
22
Andiry 2015-12-05 11:48:38 +08:00
500w+行,每行算 100bytes ,也就是 500MB ,也不算什么大文件,全部读进内存,然后开多线程用 seek 分段处理就完了
|
24
vus520 OP |
25
vus520 OP @skydiver 是的,我的需求跟你说的是一致的。不管文件多大,我每次只处理一行,直接扔给外部程序处理,这里只关注遍历文件的速度,外部程序处理的速度暂时不关注
|
28
xufang 2015-12-05 12:07:42 +08:00
@Andiry 补上 https://blog.klauspost.com/an-async-read-ahead-package-for-go/
这套东东比手动撸 c++/java 舒服多了。至于脚本语言,有了 GIL 就别想啦。 |
31
ryd994 2015-12-05 12:26:17 +08:00
问题是为什么不用 tail -f 解决原始需求而是用这种绕路的方法解决一个人为的需求?
对于新需求, BC 和 EF 之间是否有顺序关系, BC 是否一定在 EF 之前, EF 是否只出现一次?如果是: sed 还有,如果你有多核的话,可以直接 seek 到 1/n 大小处,找到最近的换行,然后就可以并行化了。注意处理好边界问题。 你现在的方法估计还有个瓶颈在 IO 上,因为修改的部分不大,但要复制一份的 IO 不小。直接写个 C 程序处理并不复杂,直接在当前位置写入,表面上看是随机写,但有缓存的情况下不需要担心。 |
32
xufang 2015-12-05 12:28:53 +08:00 via Android
@ryd994 楼主这需求其实是离线收集日志,估计还用上了 fabric ansible 这些工具。所以才会这样,你琢磨一下。
|
34
xufang 2015-12-05 12:33:39 +08:00 via Android
嗯,不过我现在成了 go 粉了,在不遗余力地游说楼主呢。
|
35
ryd994 2015-12-05 12:33:48 +08:00
这个任务,瓶颈是 IO ,有条件的话上 SSD 或者全部放内存
|
43
xufang 2015-12-05 13:51:29 +08:00
|
45
clino 2015-12-05 13:59:09 +08:00
@xufang 有点莫名其妙 什么伸手党
我没有要吃饭 你硬塞给我个 go 的玩意说是喂饭 然后说我伸手党 是有什么问题? 难道是 go 教里的原教旨主义? 我是说楼主一样的原始文件那两种方法都有测试时间结果 那要有 go 的方法对比测试一下时间才是实际 |
47
xufang 2015-12-05 14:04:14 +08:00
诸位觉得我的理论无懈可击了,所以逼我 show 代码了吗?
老实说,这块代码我也是花了一些心思写的,觉得是业内前沿的技术。不愿意白给的哦。 反正思路我也指出了,看客们自己判断。 |
48
kotokz 2015-12-05 14:17:19 +08:00
这种我肯定会用 nim +mmap
|
49
pright 2015-12-05 15:58:55 +08:00
#一粉顶十黑的绝佳例子#
|
51
xufang 2015-12-05 16:07:48 +08:00
|
52
5thcat 2015-12-05 16:53:27 +08:00
顺序读文件还要并行真是醉了, 真是给 golang 抹黑
|
53
undeflife 2015-12-05 16:55:20 +08:00 1
楼上这位还真是 手里拿着锤子,看什么都像是钉子 ...
golang 没什么,golang 教徒就很让人烦了 |
57
xufang 2015-12-05 16:57:21 +08:00
来来来,让我看下 V2EX 今天又多少小学生在线。 :)
|
59
xufang 2015-12-05 16:59:41 +08:00
诸位小学生,回帖先看贴,我在前讲过 N 次我的观点了,不要略过。
|
60
xufang 2015-12-05 17:22:12 +08:00
舌战了一下午,除了这幅图,没有其他可以表达我此刻的感受了。
|
61
looyao 2015-12-05 18:25:15 +08:00
这里可以粘帖代码么,额
//tail_demo.c #include <stdio.h> #include <strings.h> #include <stdlib.h> #include <unistd.h> #include <sys/inotify.h> int tail(char *path, long *pos); int main(int argc, char *argv[]) { int inotify_fd, watch_fd, n; long pos; struct inotify_event event; void *evp; char *path; if (argc != 2) { return -1; } path = argv[1]; pos = 0; if (tail(path, &pos) < 0) { return -2; } evp = &event; inotify_fd = inotify_init(); watch_fd = inotify_add_watch(inotify_fd, path, IN_MODIFY | IN_DELETE_SELF | IN_MOVE_SELF); if (watch_fd <= 0) { fprintf(stderr, "inotify_add_watch error:%s\n", path); return -3; } //这里可以使用 select, poll 轮询下 inotify_fd while (1) { bzero(&event, sizeof(struct inotify_event)); n = read(inotify_fd, evp, sizeof(struct inotify_event)); if (n <= 0) { fprintf(stderr, "read error\n"); break; } if (event.mask & IN_MODIFY) { tail(path, &pos); } } } int tail(char *path, long *pos) { FILE *handle; char buf[1024]; handle = fopen(path, "r"); if (!handle) { fprintf(stderr, "can't open file:%s\n", path); return -1; } fseek(handle, *pos, SEEK_SET); while (!feof(handle)) { bzero(buf, sizeof(buf)); fgets(buf, sizeof(buf), handle); printf("%s", buf); *pos = ftell(handle); } fclose(handle); } 编译: gcc tail_demo.c -o tail_demo 使用: ./tail_demo 文件路径 |
62
xufang 2015-12-05 18:39:20 +08:00
牛哄哄喷我的小学生呢,不要停啊。继续喷,来拓展我的世界观。
|
63
vus520 OP |
64
looyao 2015-12-05 18:58:15 +08:00
@vus520 不好意思, Linux 才可以,没有说明。代码临时写的,可能不够严谨,其实就是这个意思,默认读取文件,全部读取完成后监控文件改变再读,这样。不用怕大文件,其实没什么关系。 PS :代码粘上来米有缩进,好丑,下次不粘了,哈哈。
|
65
neoblackcap 2015-12-05 18:59:17 +08:00
@vus520 inotify 是 linux 内核特性, Mac 自然没有。
|
66
aku 2015-12-05 19:33:07 +08:00 via Android
|
67
clino 2015-12-05 19:37:34 +08:00
@neoblackcap 为什么 tail 不需要用到 inotify 就可以监控文件改变呢
|
70
xufang 2015-12-05 19:41:59 +08:00
@clino 一个小技巧就是 read(n) 每每读不到数据的时候,以斐波那契数列的时间来 sleep ,当然这个技巧有无效果就见仁见智了。 10 年前,国外的邮件列表就对这个讨论得很充分了。
|
72
xufang 2015-12-05 19:49:29 +08:00
|
76
xufang 2015-12-05 20:04:25 +08:00
终于有人使出 block 大法了,我还以为小学生们会比较好面子的死撑的呢。
|
79
xufang 2015-12-05 20:34:40 +08:00 via Android
一个简单的事实: tail 的历史比 inotify 要老,所以小学生哪来的如此的自信满满?
|
80
wjchen 2015-12-05 20:52:19 +08:00
可以 hook 写文件的 api 。
|
81
msg7086 2015-12-06 07:33:36 +08:00
好好的 V2EX 搞得乌烟瘴气,能不能消停下?
|
83
RemRain 2015-12-06 12:22:57 +08:00
@xufang
LZ 的需求是: 1. 监控文件增加的每一行; 2. 简单的字符串替换; 3. 最好是命令行 需求里面监控文件增加才是难点,字符串替换怎么来都不是问题,所以楼下的建议都是 tail -f 作监控,管道来处理字符串替换,你这假装很有经验,不给出有帮助的回答并强行与所有人撕逼是为哪般? 另外你答的几个看起来很厉害,实际没任何用的技术点,我可以给你分析下: 1. awk 比 Perl 快, LZ 没用对, ChinaUnix 上很多人可以给出更快的方案 事实上在文本简单处理上,各语言在效率上没有太大差异,处理速度完全取决于 IO 操作。 Linux 是有文件缓存的, LZ 之所以发现 Perl 比 awk 快,很有可能是 awk 后文件被缓存了一部分,之后 Perl IO 操作变快了。不看脚本内容,直接断言 LZ 没用对,而且不说哪里不对,说明你压根没意识到文件缓存的问题,或者说不知道有这个东西。 2. 脚本写得再高效,只能单核运行,应该用 golang , golang 天然支持多核 我以为 LZ 需求的效率取决于 IO 性能是有目共睹的,多核处理并不能加快 IO 处理速度,@5thcat 已经说明了。你回复说`你能在等 IO 的时候,把 CPU 也用上吗?` 我反问你一句,你把 CPU 都用上了,就不用等 IO 吗? 3. golang 的正则引擎秒杀很多脚本语言,打了很多语言的脸 那又如何? LZ 关心的是遍历,标题说明了,回复中也强调了。正则引擎快有啥用?另外真计较性能的话,你不觉得应该用普通的字符串查找、替换函数吗?锤子是好使,可这是螺丝啊 |
85
xufang 2015-12-06 12:26:36 +08:00
我敢打赌,你们这些乱喷的小学生根本没看我贴的两篇的文章。
|
88
xufang 2015-12-06 12:35:59 +08:00
只会爬楼,不看各楼引用的帖子,真是够了。我下午还要出去玩,有什么干货赶紧说。
|
90
xufang 2015-12-06 12:45:23 +08:00
|
91
xufang 2015-12-06 12:45:49 +08:00
s/我们反对 /我没反对 /
|
92
xufang 2015-12-06 13:02:23 +08:00
出门了,最后我甩个半干货出来。
并行处理存在理论上的优势,但是实现的时候要考虑 locality 的问题, golang 还有 gc 方面需要针对性优化。 总之,知易行难。写代码其实是个技术活。 |
93
xufang 2015-12-06 21:48:35 +08:00
周末在这贴帖子我关注了两天,最终还是没有人提到 parallel 命令,这个让我进一步确认了在 V2EX 的技术自信
https://en.wikipedia.org/wiki/GNU_parallel parallel 命令的思想和我说的这个初衷类似,不过有两点毛病 1. 需要处理的数据行要上下文无关。 2. 最要命的是 locality 不行,进程间通信比 golang 实现的原子操作慢多了。 不过,在 CPU 操作很密集的情况下,不愿意自己撸代码的,可以考虑用它。 |
94
xufang 2015-12-06 21:49:48 +08:00
最后送本楼乱喷我的小学生们一句话,除了对新技术保持谦虚之外,回帖要看贴。
以上。 |