按tmpfs
可能性的大小排序:
┌───────────┬──────────────┬────────────────┐
│ /dev/shm │ always tmpfs │ Linux specific │
├───────────┼──────────────┼────────────────┤
│ /tmp │ can be tmpfs │ FHS 1.0 │
├───────────┼──────────────┼────────────────┤
│ /var/tmp │ never tmpfs │ FHS 1.0 │
└───────────┴──────────────┴────────────────┘
由于你问的是Linux特定的tmpfs挂载点,而不是一个可移植定义的目录,这个目录_可能是tmpfs(取决于你的sysadmin和你的发行版的默认值),你的问题有两个方面,其他答案强调的不一样。
1.什么时候使用这些目录,基于_良好的实践 2. 什么时候适合使用tmpfs
保守版(混合了 FHS 的惯例和常用的惯例):
/tmp
。/var/tmp
。/var/tmp
来保存有益于重启期间的数据(如缓存)。/dev/shm
作为调用shm_open()
的副作用。预期的受众是无休止地被覆盖的有界缓冲区。所以这适用于内容不稳定且体积不是很大的长寿文件。
–如果仍有疑问,提供一种方法让用户覆盖。例如,mktemp
程序尊重TMPDIR
环境变量。实用版。
当需要使用tmpfs时使用/dev/shm
,当不需要时使用/var/tmp
,否则使用/tmp
。
fsync
在tmpfs上是没有操作的。这个syscall是(IO)性能(和flash寿命的头号敌人,如果你关心这个的话),不过如果你发现自己使用tmpfs(或者eatmydata )只是为了打败fsync,那么你(或者产业链上的其他开发者)就做错了。这意味着朝向存储设备的事务对于你的目的来说是不必要的细化–你显然愿意为了性能而跳过一些保存点,因为你现在已经走到了破坏所有保存点的极端–这很少是最好的妥协。此外,在交易性能方面,拥有SSD的最大好处就在于此–任何像样的SSD的性能都会比旋转的磁盘所能承受的要高得多(7200 rpm = 120 Hz,如果没有别的东西在访问它的话),更不用说闪存卡了,它们在这一指标上有很大的不同(尤其是因为这是与顺序性能的权衡,而顺序性能是它们的评级,例如SD卡的等级)。所以,拥有超快固态硬盘的开发者们要注意了,不要把你的用户强加到这个用例中去!
想听一个可笑的故事吗?我的第一个fsync
教训:我有一份工作,涉及到经常性地 “升级 "一堆Sqlite数据库(作为测试用例保存)到不断变化的当前格式。"升级 "框架会运行一堆脚本,每个脚本至少做一个事务,来升级一个数据库。当然,我是并行升级我的数据库的(8个并行,因为我有一个强大的8核CPU)。但我发现,由于这个过程完全是IO绑定的,所以没有任何并行化的加速(而是轻微的hit)。可笑的是,将升级框架封装在一个脚本中,将每个数据库复制到/dev/shm
,在那里升级,然后再复制到磁盘上,速度快了100倍(仍然是8核并行)。作为奖励,在升级数据库的同时,PC也是_可用的。
tmpfs合适的使用是为了避免不必要的易失性数据的写入。有效地禁止了回写,就像在普通文件系统上设置`/proc/sys/vm/dirtywriteback_centisecs`为无穷大一样。
这个和性能关系不大,失败了比滥用fsync小得多。写回超时决定了在pagecache内容之后,磁盘内容更新的速度有多慢,默认的5秒对于计算机来说是个很长的时间–一个应用程序可以在pagecache中随意覆盖一个文件,但磁盘上的内容大约每5秒才更新一次。除非应用程序用fsync强制完成,否则就是这样。想想一个应用程序在这段时间内能输出多少次小文件,你就会明白为什么对每一个文件进行fsync会是一个更大的问题。
-读取性能。如果你的数据很热(如果你考虑把数据保存在tmpfs中,最好是这样),你无论如何都会打到pagecache。不同的是在不打pagecache的时候,如果是这种情况,请去看下面的 "tmpfs的糟糕之处"。
–短命文件。这些文件在被写出来之前,可能会在pagecache中生活一辈子(作为dirty页)。当然,除非你用fsync
强迫它。
保留 cold数据。你可能会认为,从交换区提供文件服务和普通的文件系统一样高效,但有几个原因说明它不是:
好吧,这里是实际情况。
tmpfs和普通的文件系统都是在磁盘上进行内存缓存。
临时文件系统使用内存和swap空间作为它的后备存储一个文件系统使用磁盘的特定区域,两者的文件系统大小都不受限制,如果你有足够的swap空间,在一台内存不足GB的机器上拥有一个200GB的临时文件系统是完全可能的。
区别在于数据写入磁盘的时间。对于tmpfs来说,只有当内存太满或数据不可能很快被使用时,才会将数据写入磁盘。OTOH大多数普通的Linux文件系统都被设计成在磁盘上有一组或多或少一致的数据,所以如果用户拔掉插头,他们不会失去所有的数据。
就我个人而言,我习惯于拥有不会崩溃的操作系统和UPS系统(例如:笔记本电池),所以我认为ext2/3文件系统的5-10秒检查点间隔太偏执了。ext4文件系统比较好,有10分钟的检查点,只是它把用户数据当成二等兵,不保护。(ext3也是一样的,但因为有5秒的检查点,所以你不会注意到)
这种频繁的检查点意味着不必要的数据被不断地写入磁盘,甚至对于/tmp来说也是如此。
所以结果就是你需要创建一个和你的/tmp一样大的交换空间(即使你必须创建一个交换文件),然后用这个空间来挂载一个所需大小的tmpfs到/tmp上。
永远不要使用/dev/shm。
除非,你用它来处理非常小的(可能是mmap'd)IPC文件,并且你确定它的存在(它不是一个标准),而且机器有足够的内存+swap可用。
使用/tmp/作为临时文件。当你需要共享内存时,使用 /dev/shm/ (即通过文件进行进程间通信)。
你可以依赖/tmp/在那里,但/dev/shm/是相对较新的Linux才有的东西。
另一个应该使用 /dev/shm (适用于 Linux 2.6 及以上版本)的情况是,当你需要一个有保证的 tmpfs 文件系统时,因为你不知道你是否能够_写入磁盘。
我熟悉的一个监控系统在建立报告提交给中央服务器时需要写出临时文件。在实践中,更有可能出现的情况是,有些东西会阻止对文件系统的写入(要么是磁盘空间不够了,要么是底层的RAID故障把系统推到了硬件只读模式),但你仍然能够跛着脚走,以提醒它,而不是如果有些东西把所有可用的内存都弄坏了,以至于tmpfs无法使用(而且盒子也不会死)。在这样的情况下,监控系统会更倾向于向RAM写入数据,这样就有可能在磁盘满了或者硬件死了/垂死的情况下发出警报。
/dev/shm用于共享虚拟内存系统特定设备驱动程序和程序。
如果你正在创建一个需要虚拟内存堆的程序,该程序应该被映射到虚拟内存。如果你需要多个进程或线程能够安全地访问该内存,这就会加倍。
事实上,仅仅因为驱动程序为它使用了特殊版本的tmpfs,并不意味着你应该把它作为一个通用的tmpfs分区。相反,如果你想为你的临时目录创建一个tmpfs分区,你应该再创建一个tmpfs分区。
在PERL中,在任何机器上都有8GB的最小容量(都在运行Linux Mint),我的习惯是,我认为是一个很好的习惯,用/dev/shm
做基于DB/File(文件中的数据结构)的复杂算法,用/dev/shm
在其他语言中,而不是到处都有gigether。为了避免在网络传输中的起起落落(在客户端-服务器环境下,在本地对位于服务器上的文件进行工作),我将使用某种类型的批处理文件,一次性将整个(300-900MB)文件复制到/dev/shm中,运行程序并输出到/dev/shm,将结果写回服务器,并从/dev/shm中删除
当然,如果我的内存较少,我不会这样做。通常,/dev/shm的内存文件系统读取的大小是你可用RAM的一半。然而,普通的RAM使用是恒定的。所以在2GB以下的设备上,你真的无法做到这一点。把解读变成夸张,RAM中经常有一些连系统都报不好的东西。