前置于一个千兆字节的文件

时间:2010-04-22 12:45:26

标签: performance file

将单个字符添加到多GB文件(在我的实际情况下是40GB文件)中,性能最佳的方法是什么。

执行此操作没有限制。这意味着它可以通过工具,shell脚本,任何编程语言的程序,......

9 个答案:

答案 0 :(得分:8)

没有真正简单的解决方案。没有系统调用来预先添加数据,只是附加或重写。

但是根据你对文件的处理方式,你可能会侥幸逃脱。 如果按顺序使用文件,您可以创建named pipe并放置cat onecharfile.txt bigfile > namedpipe,然后使用“namedpipe”作为文件。如果您的程序将stdin作为输入,则cat onecharfile.txt bigfile | program可以实现相同的目的。

对于随机访问,可以完成FUSE文件系统,但可能对此过于复杂。

如果你想让自己的手真的很脏,请弄明白如何

  • 分配数据块(about inode and datablock structure
  • 将其插入文件的链中作为第二个块(或者首先,然后你已经完成了)
  • 将文件的开头写入该块
  • 将单个字符写为文件
  • 中的第一个字符
  • 将第一个块标记为仅使用一个可用有效负载的字节(这对于 last 块是可能的,我不知道文件链中间的块是否可能)。

这有可能严重破坏你的文件系统,所以不推荐;很有趣。

答案 1 :(得分:4)

让文件有一个初始的空字符块。在前置字符时,读取块,从右到左插入字符,然后写回块。当块已满时,然后执行更昂贵的完全重写以便预先添加另一个空块。这样,您可以减少必须进行完全重写的大部分因素。

补充:将文件保存在两个子文件中:A(短一个)和B(长一个)。以你喜欢的任何方式前置A.当A变得“足够大”时,将A添加到B(通过重写),然后清除A。

另一种方法:将文件保存为小文件目录...,A000003,A000002,A000001。
只是前置到编号最大的文件。当它足够大时,按顺序制作下一个文件 当您需要读取文件时,只需按降序读取它们。

答案 2 :(得分:2)

您可能可以根据您的问题反转您的实现:将单个字符附加到文件的末尾。到了读取文件的时候,请在 reverse 中读取它。

将此隐藏在足够的抽象层之后,它可能不会对您的代码如何物理存储字节产生影响。

答案 3 :(得分:1)

如果您使用linux,您可以尝试使用加载了LD_PRELOAD的自定义版本的READ(2),并在第一次读取时将其添加到数据之前。

请参阅https://zlibc.linux.lu/zlibc.html了解实施灵感。

答案 4 :(得分:0)

如果你的意思是将该字符预先添加到整个文件的开头,单向

$ echo "C" > tmp
$ cat my40gbfile >> tmp
$ mv tmp my40gbfile

或使用sed

$ sed -i '1i C' my40gbfile

如果你的意思是将字符前置到文件的每一行

$ awk '{print "C"$0}' my40gbfile > temp && mv temp my40gbfile

答案 5 :(得分:0)

据我所知,这是在文件系统级别处理的,这意味着如果您将数据添加到文件中,它会有效地重写文件。这与MP3文件中的ID3标签零填充的原因相同,因此未来的更新不会重写整个文件,只是更新那些保留的字节。

因此,无论您使用哪种方式,都会得到大致相似的结果。您可以尝试使用自定义复制功能进行一些测试,该功能以比默认系统副本更大的块(例如2MB或5MB)进行读/写,这可能会提高性能。最终,您的磁盘I / O是此处的瓶颈。

答案 6 :(得分:0)

也许你不需要实际上将characer物理地添加到文件中,只是虚拟。可能存在一个文件系统驱动程序,它能够将多个文件(1byte + 40gb)虚拟映射到一个虚拟文件中。

答案 7 :(得分:0)

这是Windows命令行(“DOS”)方式:

将您的1个字符放入prepend.txt

copy /b prepend.txt + myHugeFile fileNameOfCombinedFile

答案 8 :(得分:0)

绝对最高性能的方式似乎是进入扇区级别以及文件的实际存储方式。我不确定操作系统是否会成为一个因素,但目标平台可能,无论如何,我们知道你运行的是有用的。

我认为这是一个明显的选择,这种低级别的东西正是系统编程语言

你能告诉我们你最终做了什么,会很有趣。