由于某种奇怪的原因,我得到了一个未排序的100GB日志文件(实际上它是部分排序的),而我尝试使用的算法需要排序的数据。日志文件中的一行如下所示:
data <date> data data more data
我有一台工作站,可以使用C# 4.0和大约4GB的RAM。我想,在这里最好使用某种归并排序算法,但除了自己实现这些算法之外,我想问是否有一些捷径可走。
顺带一提,使用DateTime.Parse()解析日期字符串非常缓慢,并且会占用大量CPU时间-速率仅为10 MB/sec。以下是否有更快的方法?
public static DateTime Parse(string data)
{
int year, month, day;
int.TryParse(data.Substring(0, 4), out year);
int.TryParse(data.Substring(5, 2), out month);
int.TryParse(data.Substring(8, 2), out day);
return new DateTime(year, month, day);
}
我写了一个程序来加速 DateTime.Parse()
,它确实起到了作用,但仍然需要大量的计算周期。
请注意,对于当前的日志文件,我也需要关注小时、分钟和秒。我知道我可以为 DateTime.Parse() 提供格式,但似乎并没有显著提高速度。
我正在寻找正确的方向,谢谢您的帮助。
编辑:有些人建议我使用字符串比较来比较日期。这对排序阶段是有效的,但我确实需要解析日期以进行算法处理。我仍然不知道如何在只有 4GB 可用内存的情况下手动排序 100GB 的文件。
编辑2:多亏了一些人建议我使用 Windows sort,我发现了一款类似 Linux 工具。基本上你调用 sort 命令,它就会为你解决所有问题。目前它正在执行某些操作,我希望它能尽快完成。我正在使用的命令是:
sort -k 2b 2008.log > 2008.sorted.log
-k表示我要按照第二行排序,这一行是一个通常的YYYY-MM-DD hh:mm:ss.msek
格式的日期时间字符串。我必须承认man手册没有解释所有的选项,但我通过运行info coreutils 'sort invocation'
找到了很多示例。
我会回报结果和时间。这部分日志大约有27GB。我正在考虑分别对2009年和2010年进行排序,然后使用sort -m选项将结果合并成一个文件。
编辑3检查iotop表明它正在读取数据文件的小块,然后疯狂地做某些事情以处理它们。这个过程似乎相当缓慢。=(
sort
没有使用任何内存,只有一个核心。当它从驱动器中读取数据时,它没有处理任何东西。我做错了什么吗?
编辑4三个小时过去了,它还在做同样的事情。现在我已经到了想尝试调整函数参数的阶段,但我已经投入了三个小时......我将在四个小时内放弃它,并尝试使用更智能的内存和空间参数进行整夜计算......
编辑5在回家之前,我使用了以下命令重新启动了这个过程:
sort -k 2b --buffer-size=60% -T ~/temp/ -T "/media/My Passport" 2010.log -o 2010.sorted.log
今天早上它返回了这个:
sort: write failed: /media/My Passport/sortQAUKdT: File too large
哇啦哇啦!我本以为只要添加尽可能多的硬盘就能加快这个过程。但是,添加USB驱动器似乎是最糟糕的想法。目前,我甚至无法确定它是否与FAT/NTFS等有关,因为fdisk告诉我USB驱动器是一个“错误的设备”……不是开玩笑吗?稍后我会再试一次,现在让我们把这个项目放到可能失败的堆里。
最终通知 这一次成功了,使用与上面相同的命令,但没有问题的外部硬盘。谢谢大家的帮助!
基准测试
使用两个工作站级别(至少70MB/秒读/写IO)的硬盘在同一个SATA控制器上,花费了我162分钟来排序一个30GB的日志文件。今晚我还需要排序另一个52 GB的文件,我会发布进展情况。