#!/usr/bin/perl use strict; my $usegb = 1000*shift; my $timeout = shift || 10; my $giga = 2**30; my $forks = 1; my $free; my $memtotal = $usegb || int( qx{ awk '/^(MemTotal):/ { sum += \$2} END { print sum }' /proc/meminfo } / 1024); my $total = 1; # 1 MB random data so it is not compressed my $onemb = pack("L*", map { rand(2**32) } 1..(2**18)); my ($thisround, $sofar,$timediff, %buf, $pid,$shift); do { my $start = time; $free = int ( qx{ awk '/^((Swap)?Cached|MemFree|Buffers):/ { sum += \$2} END { print sum }' /proc/meminfo } / 1024) or int ( qx{ awk '/^MemAvailable:/ { sum += \$2 } END { print sum }' /proc/meminfo } / 1024); print "Free $free "; if($free <= 1) { print "\nFree < 1\n"; exit(1); } # Use at most 1 GB per round $thisround = min(1000,int($free/100)); $total += $thisround; for(1..$thisround) { # Shift every block 1 byte, so no blocks have the same content $buf{$forks}{$total}{$_} = "x"x(++$shift) . $onemb; if($shift > 4095) { # If shifted a full page: Recompute 1mb random $shift -= 4096; $onemb = pack("L*", map { rand(2**32) } 1..(2**18)); } } $timediff = time - $start; print "Chunk size: $thisround Time for swapping: $timediff seconds. Total memory used: $total\n"; if($total * 1048576 > $forks * $giga) { if($pid = fork()) { print "child spawn ",$forks,"\n"; wait; print "child exit ",$forks,"\n"; } else { $buf{$forks} = 1; $forks++; } } } until ($pid or $timediff > $timeout or $total > $memtotal); print "exit ",$forks,"\n"; sub min { # Returns: # Minimum value of array my $min; for (@_) { # Skip undefs defined $_ or next; defined $min or do { $min = $_; next; }; # Set $_ to the first non-undef $min = ($min < $_) ? $min : $_; } return $min; }