我有一个大约400 GB的大文件。每天由外部封闭系统生成。它是一个二进制文件,格式如下:
byte[8]byte[4]byte[n]
其中n等于byte [4]的int32值。
此文件没有分隔符,要读取整个文件,您只需重复直到EOF。每个“项”表示为byte [8] byte [4] byte [n]。
该文件看起来像
byte[8]byte[4]byte[n]byte[8]byte[4]byte[n]...EOF
byte [8]是一个64位数字,表示由.NET Ticks表示的一段时间。我需要对这个文件进行排序,但似乎无法找出最快的方法。
现在,我将Ticks加载到struct中,并将byte [n]的开始和结束位置加载到文件的末尾。在此之后,我通过Ticks属性在内存中对List进行排序,然后打开BinaryReader并以Ticks顺序查找每个位置,读取byte [n]值,并写入外部文件。
在流程结束时,我最终得到一个已排序的二进制文件,但它需要FOREVER。我正在使用C#.NET和一个非常强大的服务器,但磁盘IO似乎是一个问题。
服务器规格:
我看了整个互联网,只能找到一个巨大的文件是1GB的例子(让我轻笑)。
有没有人有任何建议?
答案 0 :(得分:7)
加速这种文件访问的好方法是memory-map the entire file into address space,让操作系统负责从文件中读取所需的任何位。所以你现在正在做同样的事情,除了从内存中读取而不是使用BinaryReader
/ seek / read。
你有很多主内存,所以这应该提供相当不错的性能(只要你使用的是64位操作系统)。
答案 1 :(得分:5)
使用合并排序。 它在线并且很好地并行化。
答案 2 :(得分:3)
如果您可以学习Erlang或Go,它们可以非常强大并且可以非常好地扩展,因为您有24个线程。利用异步I / O.合并排序。 而且由于你有32GB的Ram,尝试尽可能多地将加载到RAM中并在那里进行排序然后写回磁盘。
答案 3 :(得分:1)
我会在几次传球中这样做。在第一遍,我会创建一个刻度列表,然后将它们均匀地分配到许多(数百?)桶中。如果您提前知道滴答均匀分布,则可以跳过此初始传递。在第二遍,我会将记录分成几百个大小相同的单独文件(这些小得多的文件按照你想要的顺序代表刻度组)。然后我会在内存中分别对每个文件进行排序。然后连接文件。
它有点类似于hashsort(我认为)。