The Kollected Kode Vicious

Kode Vicious - @kode_vicious

  下载本文的PDF版本 PDF

文件系统垃圾

快速有效地清理您的存储空间


尊敬的 KV,

我们最近在一个非常大的文件服务器上耗尽了存储空间——该服务器拥有数TB的空间——经过仔细检查,我们发现仅仅是一名员工就用完了所有空间。空间几乎完全被运行一些数据分析脚本产生的小文件占用。这些文件在被读取一次后就完全没有必要了。生成这些文件的代码没有在文件创建后清理它们的有效方法;它只是继续认为存储空间是无限的。现在我们不得不在文件服务器上设置配额,当然,还要处理每周要求更多磁盘空间的呼声。肯定有比因为害怕其中一人做错事而限制所有人的更好的方法来处理这个问题。

进退两难:空间不足


尊敬的 Caught,

是的,有更好的方法来处理这个问题,但请不要叫我 Shirley。您现在已经发现廉价存储的缺点之一(是的,那句老话是真的):文件总是会扩展以填满可用的存储空间,就像程序扩展以填满所有可用内存并产生更多线程直到您的所有 CPU 也被利用一样。

您正在处理的共享存储提出了最棘手的问题,因为它是共享的,而且,似乎——我相信本专栏的读者都意识到——人们根本不能被信任自我约束。实际上,大多数人可以做到自我约束,但正如您所发现的,只需要一个人就会“破坏所有人的好事”,就像我们的老师过去常说的那样。

您提出的关于脚本没有自我清理方法这一点很好。当您使用许多小的源文件构建程序时,您的工具也会生成中间文件——然后这些对象会被链接到最终的可执行文件中。然而,所有名副其实的构建系统都具有某种形式的“清理”目标。尽管此目标的最初创建是为了让您可以从头开始新的构建,但当项目完成或暂停时,它也是缩小工作区大小的一种便捷方法。拥有一个可以对中间数据文件执行相同工作的程序是一个好的开始,但还有其他一些可以改进情况的方法。

用稍后必须删除的文件来污染文件系统会导致性能问题。如果您需要通过文件系统的递归下降来查找所有文件才能删除它们,那么您将对文件系统进行大量操作。对于 NFS (网络文件系统) 挂载的系统,在尝试自我清理时,您还将对网络进行大量操作。尽管看起来最好的做法是在使用后立即删除文件,但这会阻止您调试数据分析中的问题。此外,如果您必须重新运行部分分析,那么您创建的派生对象可能会在加快第二次、第三次,或者——好吧,您知道的——第 n 次运行速度方面派上用场,直到您最终得到正确的结果。可能最好的折衷方案是将所有派生对象放置在它们自己的目录或目录集中,这样在需要释放文件系统上的空间时,可以轻松地定位和清除它们。

将所有文件放在一个地方意味着您不必递归下降文件系统来查找所有可以安全删除的文件。这将使过程更简单、更快速,因此更可能被系统上的人员使用。如果自我清理需要 30 ,您很可能会去做;如果需要 30 分钟,您会尽可能推迟它,通常会拖延到文件系统再次填满。

KV


尊敬的 KV,

您在之前的专栏中写过关于不使用printf来调试程序,并且您建议使用调试器,但您必须承认,有时print语句只是调试程序的一种更简单的方法,而使用调试器则有点过头了。

仍然坚持使用 Printf


尊敬的 Pounding,

没错,我在之前的专栏中写过关于不使用print语句进行调试的原因,并且我建议人们使用更精细的工具,例如调试器,来查找程序中的问题。在两种情况下,我同意print语句是一个更好的解决方案。

第一种情况,当print优于调试器的情况是,要么您没有调试器,要么调试器本身使用起来非常痛苦。我发现这在解释型语言中经常发生,可能是因为添加一个print语句并重新运行程序非常容易,以至于没有人会费心为该语言编写一个像样的调试器。另一方面,编译型语言通常有调试器,因为添加一个print语句并重新构建大型程序所需的时间比启动调试器所需的时间更长。我的首选脚本语言 Python 中就存在这个问题的一个例子。我喜欢用 Python 编写代码,但我不喜欢 Python 调试器。在过去的几年里,它有所改进,可能是因为越来越多的系统是用 Python 构建的,因此拥有调试器使查找错误更容易。然而,就调试器而言,Python 的调试器与编译型语言的调试器相比,根本不算什么。

第二种情况,当print优于调试器的情况是,我的大多数读者可能没有经历过的情况:启动新的硬件。在不久的过去,除了设备驱动程序编写者之外,任何人都不必担心启动新硬件。然而,随着越来越多的人使用开源操作系统,对新硬件进行某种程度的工作变得越来越普遍。我最近在购买新笔记本电脑时就经历了这种情况。在我安装我选择的操作系统时,所有不工作的东西中,恰好是内置键盘无法与操作系统的键盘驱动程序一起工作。事实证明,我可以插入 USB 键盘并在禁用内部键盘的情况下启动,但这与我设想的使用我的新款轻薄时尚笔记本电脑的方式——连接 USB 键盘——不太一样。

我通常不从事键盘驱动程序的工作,但我认识从事这项工作的人,并且我知道没有什么比收到一个抱怨的用户发送电子邮件说“键盘不起作用”更令人沮丧的了。驱动程序本身并不长,我知道代码中可能发生挂起的位置,所以我只是从我认为的挂起点回溯,并使用了我为这种情况编写的 Emacs 宏。


(defun dbgprintf ()
 "Insert a debug printf for  kernel debugging."
 (interactive "*")
 (indent-for-tab-command)
 (insert "printf(\"reached  function %s file %s line %d\\n\",\n")
 (indent-for-tab-command)
 (insert "__func__, __FILE__,  __LINE__);\n"))

将此代码附加到键序列后,我可以插入一个print语句,无论在代码中的哪个位置,当执行到该语句时,它都会打印出已到达的函数、文件名和行号。使用这种原始方法,我能够追踪到是什么导致系统挂起,从而可以避免它,并向驱动程序维护者发送更详细的错误报告。

当然,这个宏还可以做更多的事情。例如


(defun debug-block ()
 "Insert a debug printf inside  a C ifdef debug block."
 (interactive "*")
 (insert "#if defined(DEBUG)\n")
 (indent-for-tab-command)
 (dbgprintf)
 (insert "#endif /* DEBUG  */\n")
 (indent-for-tab-command)
)

此代码以上一个代码为基础,将print语句包含在一个调试块中,该调试块可以从 makefile 或命令行打开和关闭。

是的,有时您需要或想要printf, 或者print语句,但我仍然认为,希望这些时候很少发生。

KV


KODE VICIOUS,凡人称之为 George V. Neville-Neil,以网络和操作系统代码为乐和盈利。他还教授与编程相关的各种主题的课程。他的兴趣领域是代码探险、操作系统和重写您的糟糕代码(好吧,也许不是最后一个)。他在马萨诸塞州波士顿的东北大学获得计算机科学学士学位,并且是 、Usenix 协会和 IEEE 的成员。他是一位狂热的自行车爱好者和旅行者,目前居住在纽约市。

© 2011 1542-7730/11/0700 $10.00

acmqueue

最初发表于 Queue 第 9 卷,第 7 期
数字图书馆 中评论这篇文章





更多相关文章

Pat Helland - 关注您的状态,为了您的心境
随着应用程序进入分布式和可扩展的世界,它们经历了有趣的演变。同样,存储及其近亲数据库也与应用程序并肩发展。很多时候,存储和应用程序的语义、性能和故障模型都在微妙地变化,以支持不断变化的业务需求和环境挑战。将规模化添加到组合中确实引起了轰动。本文着眼于其中的一些问题及其对系统的影响。


Alex Petrov - 现代存储系统背后的算法
本文深入探讨了现代数据库中常用的两种存储系统设计方法(读优化 B 树和写优化 LSM(日志结构合并)树),并描述了它们的使用场景和权衡。


Mihir Nanavati, Malte Schwarzkopf, Jake Wires, Andrew Warfield - 非易失性存储
对于大多数执业计算机科学家的整个职业生涯来说,一个基本观察结果始终成立:CPU 的性能明显高于 I/O 设备,价格也更高。CPU 可以以极高的速率处理数据,同时服务于多个 I/O 设备,这一事实对各种规模系统的硬件和软件设计产生了深远的影响,几乎在我们构建它们的整个历史中都是如此。


Thanumalayan Sankaranarayana Pillai, Vijay Chidambaram, Ramnatthan Alagappan, Samer Al-Kiswany, Andrea C. Arpaci-Dusseau, Remzi H. Arpaci-Dusseau - 崩溃一致性
数据的读取和写入,作为任何冯·诺依曼计算机最基本的方面之一,出人意料地微妙且充满细微差别。例如,考虑在具有多个处理器的系统中访问共享内存。虽然一种称为强一致性的简单直观方法最容易被程序员理解,但许多较弱的模型也得到了广泛应用(例如,x86 总存储顺序);这些方法提高了系统性能,但代价是使系统行为的推理更加复杂且容易出错。





© All Rights Reserved.

© . All rights reserved.