什么时候应该使用/dev/shm/,什么时候应该使用/tmp/?

Del*_*ted 202 linux

我应该什么时候用/dev/shm/,什么时候用/tmp/?我可以一直依靠他们都在 Unices 上吗?

小智 149

/dev/shm是一个临时文件存储文件系统,即tmpfs,它使用 RAM 作为后备存储。它可以用作促进IPC的共享内存实现。

来自维基百科

最近的 2.6 Linux 内核构建已经开始以 ramdisk 的形式提供 /dev/shm 作为共享内存,更具体地说,作为一个世界可写目录,它存储在内存中,并在 /etc/default/tmpfs 中定义了限制。  /dev/shm 支持在内核配置文件中是完全可选的。  默认情况下,它包含在 Fedora 和 Ubuntu 发行版中,其中 Pulseaudio 应用程序最广泛地使用它。???????????? (加了重点。)

/tmpFilesystem Hierarchy Standard 中定义的临时文件的位置,几乎所有 Unix 和 Linux 发行版都遵循该标准

由于 RAM 比磁盘存储快得多,如果您的进程是 I/O 密集型并广泛使用临时文件,则可以使用/dev/shm代替 来/tmp提高性能

回答您的问题:不,您不能总是依赖于/dev/shm在场,当然也不能依赖于内存不足的机器。您应该使用/tmp,除非你有一个很好的理由使用/dev/shm

请记住,它/tmp可以是/文件系统的一部分而不是单独的挂载,因此可以根据需要增长。的大小/dev/shm受系统上多余 RAM 的限制,因此您更有可能用完此文件系统上的空间。

  • 使用 `/dev/shm` 没有性能提升。`/dev/shm` 是由磁盘(交换)支持的内存(tmpfs)。`/var/tmp` 是由磁盘(磁盘文件系统)支持的内存(磁盘缓存)。在实践中,性能大致相同(tmpfs 略有优势,但还不够重要)。`/tmp` 可能是 tmpfs 也可能不是 tmpfs,这取决于管理员如何配置它。没有充分的理由在脚本中使用 `/dev/shm`。 (10认同)
  • 在 Linux 2.6 及更高版本下,需要挂载 /dev/shm 以便 shm_open() 等 POSIX 共享内存系统调用工作。换句话说,如果未安装某些程序会中断 - 所以它应该是。它不仅仅是一个 RAM 磁盘。所以你应该确保 /dev/shm 的一些是免费的。 (5认同)
  • @GaretClaborn 使用由交换支持的内存有很多充分的理由,但这称为正常进程内存。如果您使用的是文件,则称为文件系统,并且所有文件系统都是内存(缓存),如果文件系统类似于 tmpfs,则由交换支持。在交换区和其他存储区之间分配磁盘空间通常是管理员的职责。如果应用程序希望文件倾向于保留在 RAM 中,`/tmp` 是正常位置(用 `$TMPDIR` 覆盖)。让`/tmp` 由交换、其他磁盘空间或什么都不支持的选择是管理员的。 (3认同)
  • 我还添加了对 /dev/shm 的最小大小和当前使用级别的检查,以防止无意中填满它。 (2认同)

use*_*284 98

tmpfs可能性降序排列:

?????????????????????????????????????????????
? /dev/shm  ? always tmpfs ? Linux specific ?
?????????????????????????????????????????????
? /tmp      ? can be tmpfs ? FHS 1.0        ?
?????????????????????????????????????????????
? /var/tmp  ? never tmpfs  ? FHS 1.0        ?
?????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

由于您问的是 Linux 特定的tmpfs挂载点与可能是 tmpfs的可移植定义的目录(取决于您的系统管理员和您的发行版的默认设置),您的问题有两个方面,其他答案强调了不同的方面:

  1. 适当使用各种tmp目录
  2. 适当使用tmpfs

适当使用各种tmp目录

基于古老的Filesystem Hierarchy StandardSystemd 关于此事的说法

  • 如有疑问,请使用/tmp.
  • 使用/var/tmp该应持续到重新引导数据。
  • 使用/var/tmp大数据可能不容易适应RAM(假设/var/tmp有更多的可用空间-通常是一个合理的假设)。
  • 使用/dev/shm仅作为调用的副作用shm_open()。目标受众是无限覆盖的有界缓冲区。所以这适用于内容不稳定且不是特别大的长期文件。
  • 绝对不要/dev/shm用于(任何类型的)可执行文件,因为它通常是 mount 的noexec
  • 如果仍有疑问,请为用户提供覆盖的方法。为了最少的惊喜,请喜欢mktemp并尊重TMPDIR环境变量。

tmpfs 的优势所在

tmpfs性能具有欺骗性。您会发现 tmpfs 上的工作负载更快,这并不是因为 RAM 比磁盘快:所有文件系统都缓存在 RAM 中——页面缓存!相反,它表明工作负载正在做一些破坏页面缓存的事情。一个进程在这方面可以做的更糟糕的事情是比必要的更频繁地同步到磁盘。

fsync是 tmpfs 上的空操作。这个系统调用告诉操作系统刷新与文件关联的页面缓存,一直到刷新相关存储设备的写缓存,同时阻止发出它的程序取得任何进展——这是一个非常粗糙的写屏障. 它是一个必要的工具,只是因为存储协议没有考虑到事务。缓存首先是为了让程序可以对文件执行数百万次小写入,而不会注意到写入存储设备的实际速度有多慢——所有实际写入都是异步发生的,或者直到fsync被调用,这是程序直接感受到写入性能的唯一地方。

因此,如果您发现自己使用 tmpfs(或eatmydata) 只是为了打败 fsync,那么您(或链中的其他开发人员)就做错了。这意味着针对您的目的,对存储设备的交易是不必要的细粒度 - 您显然愿意跳过一些保存点以提高性能,因为您现在已经走到了破坏所有保存点的极端 - 很少是最好的妥协。此外,正是在事务性能领域,拥有 SSD 的一些最大好处是 – 与旋转磁盘可能承受的能力相比,任何物有所值的 SSD 都将表现出超乎寻常的性能(7200 rpm = 120 Hz,如果没有其他人正在访问它)。闪存卡在这个指标上也有很大差异(这是与顺序性能的权衡,SD 卡等级只考虑后者)。所以请注意,拥有超快 SSD 的开发人员,

想听一个荒诞的故事吗?我的第一fsync堂课:我有一份工作,涉及定期将一堆 Sqlite 数据库(保留为测试用例)“升级”为不断变化的当前格式。“升级”框架将运行一堆脚本,每个脚本至少进行一个事务,以升级一个数据库。当然,我并行升级了我的数据库(8 个并行,因为我拥有强大的 8 核 CPU)。但正如我发现的那样,没有任何并行化加速(而是轻微的打击),因为该过程完全受 IO 限制。有趣的是,将升级框架包装在一个脚本中,该脚本将每个数据库/dev/shm复制到. 作为奖励,PC是可用的 在升级数据库时也是如此。

tmpfs 适合的地方

tmpfs 的适当使用是为了避免对易失性数据进行不必要的写入。有效禁用writeback,例如/proc/sys/vm/dirty_writeback_centisecs在常规文件系统上设置为无穷大。

这与性能几乎没有关系,失败这比滥用 fsync 的问题要小得多:写回超时决定了页面缓存内容后磁盘内容更新的延迟程度,默认 5 秒对于计算机来说是很长的时间– 应用程序可以在页面缓存中任意频繁地覆盖文件,但磁盘上的内容大约每 5 秒更新一次。除非应用程序使用 fsync 强制它通过,否则。考虑一下应用程序在这段时间内可以输出多少次小文件,您就会明白为什么对每个文件进行 fsync 会是一个更大的问题。

什么 tmpfs 帮不了你

  • 读取性能。如果您的数据很热(如果您考虑将其保存在 tmpfs 中,最好是这样),无论如何您都会访问页面缓存。不同之处在于不访问页面缓存时;如果是这种情况,请转到下面的“Where tmpfs sux”。
  • 短命文件。这些可以在被写出之前一直存在于页面缓存中(作为页面)。fsync当然,除非你强迫它。

哪里 tmpfs sux

保持数据。您可能会认为从交换中提供文件与普通文件系统一样有效,但有以下几个原因:

  • 最简单的原因:当代存储设备(无论是基于硬盘还是基于闪存)最喜欢阅读由适当的文件系统整齐地组织起来的相当顺序的文件。交换 4KiB 块不太可能改善这一点。
  • 在隐性成本:交换出去。Tmpfs 页面是脏的——它们需要被写入某个地方(以交换)以从页面缓存中驱逐,而不是可以立即删除的文件支持的干净页面。这是对内存竞争的所有其他内容的额外写入惩罚 - 在与使用那些 tmpfs 页不同的时间影响其他内容。

  • @jarno 首先,节省 tmpfs 挂载点的数量,我称之为实现细节。其次,不要让设备名称混淆你——查看 /proc/mounts(这是查看的正确位置),你会看到类型是“tmpfs”,而 _device_ 在这里是“none”。是的,设备名称在 tmpfs 中没有任何意义——如果你愿意,你可以`mount -t tmpfs "jarno is great" /mnt/jarno`!第三,默认大小是 RAM 量的一半——我敢打赌你有 4GiB RAM。 (3认同)
  • sqlite 升级脚本可能已启用自动提交?还是犯得太频繁了?我发现有和没有自动提交的 sqlite 性能存在巨大差异。在内存 (/dev/shm) 上运行可以缓解过于频繁的提交。 (2认同)

小智 23

好吧,这就是现实。

tmpfs 和普通文件系统都是磁盘上的内存缓存。

tmpfs 使用内存和交换空间,因为它的后备存储文件系统使用磁盘的特定区域,文件系统的大小也不受限制,如果在 1GB 内存的机器上有 200GB 的 tmpfs,则很可能你有足够的交换空间。

不同之处在于数据写入磁盘的时间。对于 tmpfs,仅当内存太满或数据不太可能很快被使用时才写入数据。OTOH 大多数普通的 Linux 文件系统被设计成在磁盘上始终具有或多或少一致的数据集,因此如果用户拔掉插头,他们不会丢失所有内容。

就个人而言,我习惯于使用不会崩溃的操作系统和 UPS 系统(例如:笔记本电池),所以我认为 ext2/3 文件系统的 5-10 秒检查点间隔过于偏执。ext4 文件系统最好有 10 分钟的检查点,除了它将用户数据视为第二类并且不保护它。(ext3 是相同的,但由于 5 秒检查点,您没有注意到它)

这种频繁的检查点意味着不必要的数据不断写入磁盘,即使是 /tmp。

因此,结果是您需要创建与 /tmp 所需大小一样大的交换空间(即使您必须创建交换文件),并使用该空间将所需大小的 tmpfs 安装到 /tmp 上。

永远不要使用 /dev/shm。

除非,您将它用于非常小的(可能是 mmap 的)IPC 文件,并且您确定它存在(它不是标准)并且机器有足够的内存 + 可用交换。

  • 同意,除了结论“永远不要使用 /dev/shm”。如果您根本不希望将文件写入磁盘,并且希望最小化磁盘 i/o,则您希望使用 /dev/shm。例如,我需要从 FTP 服务器下载非常大的 zip 文件,解压缩它们,然后将它们导入数据库。我解压缩到 /dev/shm 以便对于解压缩和导入操作,HDD 只需要执行一半的操作,而不是在源和目标之间来回移动。它极大地加快了这个过程。这是众多示例中的一个,但我同意它是一种利基工具。 (30认同)

Cap*_*ult 5

将 /tmp/ 用于临时文件。当您需要共享内存(即通过文件进行进程间通信)时,请使用 /dev/shm/。

你可以依赖 /tmp/ 存在,但 /dev/shm/ 是一个相对较新的 Linux 唯一的东西。