如何填充90%的可用内存?


181

我想进行一些低资源测试,为此,我需要有90%的可用内存已满。

如何在*nix系统上执行此操作?


3
它真的必须在任何 * nix系统上工作吗?
CVn

31
您可以创建内存有限的VM(使用docker,vagrant或类似工具),而不是突出填充内存吗?
abendigo

4
@abendigo对于QA,此处介绍的许多解决方案很有用:对于没有特定平台的通用OS,VM或内核引导参数可能会有用,但是对于嵌入式系统,如果您知道目标系统的内存规格,我会去填充空闲内存。
爱德华·弗洛里内斯库

2
如果其他人对这里的评分感到有些震惊:meta.unix.stackexchange.com/questions/1513/…
goldilocks 2013年

Answers:


156

Stress-ng是一个工作负载生成器,可模拟POSIX系统上的cpu / mem / io / hdd压力。在Linux <3.14上,此调用应该可以解决问题:

stress-ng --vm-bytes $(awk '/MemFree/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1

对于> = 3.14的Linux,您可以使用它MemAvailable来估计新进程的可用内存,而无需交换:

stress-ng --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.9;}' < /proc/meminfo)k --vm-keep -m 1

/proc/meminfo使用free(1)/ vm_stat(1)/ etc 修改呼叫。如果您需要便携的话。


3
压力--vm-bytes $(awk'/ MemFree / {printf“%d \ n”,$ 2 * 0.097;}'</ proc / meminfo)k --vm-keep -m 10
罗伯特,罗伯特,Robert

1
大多数MemFree由操作系统保留,因此我改用MemAvailable。这给了我92%的利用率来美分OS 7stress --vm-bytes $(awk '/MemAvailable/{printf "%d\n", $2 * 0.98;}' < /proc/meminfo)k --vm-keep -m 1
kujiy

众所周知,MemAvailable已添加到“估计无需启动即可启动新应用程序的可用内存量”中,请参见git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/ …git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/…–
tkrennwa

1
补充说明一下,两者--vm 1 and --vm-keep都非常重要。只是--vm-bytes什么都不做,您可能会误以为您可以根据需要/想要分配尽可能多的内存。我对此有所了解,直到尝试通过分配256G的内存来检查自己的状况。这不是答案中的缺陷,它提供了正确的标志,只是额外的警告。
凌晨12:56

这就是为什么-m 1。根据压力手册,-m N它的缩写是--vm N:产卵N工人旋转malloc()/free()
tkrennwa

92

您可以将C程序写入malloc()所需的内存,然后使用mlock()来防止内存被换出。

然后,只需让程序等待键盘输入,然后解锁内存,释放内存并退出即可。


25
很久以前,我不得不测试类似的用例。我观察到,除非您向该内存中写入内容,否则它实际上不会被分配(即直到发生页面错误)。我不确定mlock()是否会解决这个问题。
Poorna

2
我同意@siri; 但是,这取决于所使用的UNIX变体。
安东尼

2
该代码的一些启发。此外,我认为您不需要解锁/释放内存。流程结束后,操作系统将为您执行此操作。
塞巴斯蒂安

9
您可能必须实际写入内存,如果仅对内存进行分配,则内核可能会过量使用。如果配置为,例如Linux将让malloc成功返回而实际上没有可用的内存,并且仅在写入内存时才实际分配内存。参见win.tue.nl/~aeb/linux/lk/lk-9.html
Bjarke Freund-Hansen

7
@Sebastian:calloc将遇到相同的问题IIRC。所有内存将仅指向相同的只读清零页面。在尝试写入之前,它实际上不会被分配(由于它是只读的,因此不会起作用)。真正确定自己知道的唯一方法是对memset整个缓冲区执行操作。有关更多信息,请参见以下答案stackoverflow.com/a/2688522/713554
Leo)

45

我建议运行内存有限的VM并测试软件,这比尝试在主机上填充内存要更有效。

该方法还具有以下优势:如果内存不足情况在其他地方导致OOM错误并使整个OS挂起,则仅将正在测试的VM挂在您的计算机上而不挂在其他可能正在运行的有用进程上。

同样,如果您的测试不占用大量CPU或IO,则可以在具有各种低内存大小的VM系列上并发运行测试实例。


31

来自此HN评论:https : //news.ycombinator.com/item? id =6695581

只需通过dd或类似名称填充/ dev / shm。

swapoff -a
dd if=/dev/zero of=/dev/shm/fill bs=1k count=1024k

8
并非所有* nix都具有/ dev / shm。还有其他可移植的想法吗?
Tadeusz A.Kadłubowski13年

如果pv已安装,则有助于查看计数:dd if=/dev/zero bs=1024 |pv -b -B 1024 | dd of=/dev/shm/fill bs=1024
Otheus

1
如果需要速度,此方法是正确的选择!因为它可以在几秒钟内分配所需的RAM量。不要在/ dev / urandom上中继,它将占用100%的CPU,如果您的RAM很大,则需要几分钟。但是,/ dev / shm在现代Ubuntu / Debian发行版中具有相对大小,其大小默认为物理RAM的50%。希望您可以重新挂载/ dev / shm或创建一个新的挂载点。只需确保它具有您要分配的实际大小即可。
develCuy

30
  1. 运行Linux;
  2. mem=nn[KMG]内核启动参数启动

(有关详细信息,请查看linux / Documentation / kernel-parameters.txt)。


24

如果你有基本的GNU工具(shgrepyeshead),你可以这样做:

yes | tr \\n x | head -c $BYTES | grep n
# Protip: use `head -c $((1024*1024*2))` to calculate 2MB easily

之所以可行,是因为grep将整个数据行加载到RAM中(我在复制磁盘映像时以一种非常不幸的方式学到了这一点)。线,通过所产生yes,替换新行,将是无限长的,但由不限head$BYTES字节,从而将grep的加载在存储器$字节。Grep本身为我使用了100-200KB,您可能需要减去它以获得更精确的数量。

如果您还想添加时间限制,可以在中轻松完成bash(在中无效sh):

cat <(yes | tr \\n x | head -c $BYTES) <(sleep $NumberOfSeconds) | grep n

<(command)件事似乎鲜为人知,但通常非常有用,有关更多信息,请参见:http : //tldp.org/LDP/abs/html/process-sub.html

然后使用catcat将等待输入完成直到退出,并且通过保持其中一个管道打开,它将使grep保持活动状态。

如果您有pv并且想要慢慢增加RAM使用量:

yes | tr \\n x | head -c $BYTES | pv -L $BYTESPERSEC | grep n

例如:

yes | tr \\n x | head -c $((1024*1024*1024)) | pv -L $((1024*1024)) | grep n

将以每秒1MB的速度使用多达1 GB的数据。另外,pv还会显示当前使用率和到目前为止的总使用率。当然,这也可以使用以前的变体来完成:

yes | tr \\n x | head -c $BYTES | pv | grep n

只需插入| pv |零件即可显示当前状态(默认情况下,吞吐量和总数,我想-否则请参见手册页)。


为什么还要另一个答案?可接受的答案建议安装一个软件包(我敢保证每个芯片组都有一个版本,而无需软件包管理器);票数最高的答案建议编译C程序(我没有安装可用于目标平台的编译器或工具链);第二个投票最高的答案建议在VM中运行该应用程序(是的,让我在USB或其他设备上dd这部手机的内部sdcard并创建一个virtualbox映像);第三个建议在启动顺序中修改某些内容,使其无法按需填充RAM;仅当/ dev / shm挂载点(1)存在且(2)很大时(挂载需要root用户),第四个才有效;第五部分结合了以上内容,没有示例代码;第六是一个很好的答案,但是在提出自己的方法之前,我没有看到这个答案,因此,我认为我会添加自己的,也是因为如果您看不到膜状线实际上是问题的症结所在,那么记住或键入内容的时间会更短;第七个再次不回答问题(使用ulimit限制进程);第八种尝试让您安装python;第九位认为我们都是非常无聊的,最后第十位认为自己编写了C ++程序,该程序导致了与最高投票答案相同的问题。


可爱的解决方案。唯一的毛病是该构造的退出代码为1,因为grep找不到匹配项。stackoverflow.com/questions/6550484/…的解决方案似乎都无法解决。
Holger Brandl

@HolgerBrandl好点,我不知道该如何解决。这是我第一次听说set -e,所以我刚刚学到了一些东西:)
吕克(Luc)

$ SECONDS似乎不是一个好选择,因为它是一个内置变量,反映了启动Shell以来的时间。参见tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html
Holger Brandl,

@HolgerBrandl很好,我不知道。Kinda很高兴找到一个当前打开时间超过300万秒的终端:D。我更新了帖子。
卢克,

酷技术!time yes | tr \\n x | head -c $((1024*1024*1024*10)) | grep n(使用10 GiB内存)需要1分46秒。在github.com/julman99/eatmemory运行julman99的eatmemory程序需要6秒钟。嗯,再加上下载和编译时间,但是在我的RHEL6.4机器上编译起来没有问题,而且很快。不过,我还是喜欢这种解决方案。为什么要重新发明轮子?
Mike S

18

我保留了在点文件中执行类似操作的功能。 https://github.com/sagotsky/.dotfiles/blob/master/.functions#L248

function malloc() {
  if [[ $# -eq 0 || $1 -eq '-h' || $1 -lt 0 ]] ; then
    echo -e "usage: malloc N\n\nAllocate N mb, wait, then release it."
  else 
    N=$(free -m | grep Mem: | awk '{print int($2/10)}')
    if [[ $N -gt $1 ]] ;then 
      N=$1
    fi
    sh -c "MEMBLOB=\$(dd if=/dev/urandom bs=1MB count=$N) ; sleep 1"
  fi
}

1
恕我直言,这是最好的解决方案,因为它基本上只需要dd即可工作,其他所有东西都可以在任何shell中解决。请注意,它实际上至少是临时地声明了比数据dd生成的两倍的内存。在debian 9上测试,破折号0.5.8-2.4。如果使用bash运行MEMBLOB部件,它将变得非常缓慢,并且使用的是dd生成量的四倍。
P.Péter

16

一个简单的python解决方案有多出色?

#!/usr/bin/env python

import sys
import time

if len(sys.argv) != 2:
    print "usage: fillmem <number-of-megabytes>"
    sys.exit()

count = int(sys.argv[1])

megabyte = (0,) * (1024 * 1024 / 8)

data = megabyte * count

while True:
    time.sleep(1)

7
那可能很快就会被交换掉,对内存压力的实际影响很小(除非您也填满所有交换,这通常需要一段时间)
Joachim Sauer

1
在有可用RAM的情况下,为什么要进行unix交换?实际上,这是在需要时驱逐磁盘缓存的一种可行方法。
Alexander Shcheblikin

@AlexanderShcheblikin这个问题与驱逐磁盘缓存无关(这对性能测试很有用,但对低资源测试则无用)。
吉尔斯2013年

1
尽管我没有试图强调自己的记忆力,但该解决方案在我的测试中努力弥补了一个或两个的问题。但是,@ JoachimSauer可以将sysctl vm.swappiness=0vm.min_free_kbytes设置为一个较小的数字,例如1024。确实可以使其变得非常缓慢,以至于导致计算机出现OOM状态。参见kernel.org/doc/Documentation/sysctl/vm.txtkernel.org/doc/gorman/html/understand/understand005.html
Mike S

只需一个1GB的衬板:python -c“ x =(1 * 1024 * 1024 *
1024/8

10

如果存在,ramfs呢?挂载并复制大文件?如果没有/dev/shm,也没有ramfs-我猜一个很小的C程序会根据一些输入值来执行大型malloc吗?可能必须在具有大量内存的32位系统上一次运行几次。


8

如果要使用有限的内存测试特定进程,则最好使用ulimit限制可分配内存的数量。


2
实际上,这在linux上不起作用(关于其他* nixes的名称不知道)。man setrlimitRLIMIT_RSS Specifies the limit (in pages) of the process's resident set (the number of virtual pages resident in RAM). This limit only has effect in Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED.
Patrick

4

我认为这是一个提出错误问题的案例,理智被争夺最有创意的答案的人们淹没。如果只需要模拟OOM条件,则不需要填充内存。只需使用自定义分配器,并在分配一定数量后失败。对于SQLite来说,这种方法似乎效果很好。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.