From 9feb263deaf34e7cae9260c97e644cfff304a842 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Mon, 8 Dec 2014 18:05:44 +0100 Subject: [PATCH] tests: Add benchmark.pl - benchmark EncFS against eCryptfs Example Results * Seagate Barracuda 7200.9, model ST3250824AS * Linux 3.16.3 * EncFS 1c5c75c44fd4ad83535280858c6be7a64b172f22 Test | EncFS | eCryptfs | EncFS advantage ----------------|--------------|--------------|---------------- stream_write | 32 MiB/s | 38 MiB/s | 0.84 extract | 28744 ms | 30027 ms | 1.04 du | 495 MB | 784 MB | 1.58 rsync | 3319 ms | 62486 ms | 18.83 delete | 6462 ms | 74652 ms | 11.55 (eCryptfs is very slow for stat() on a classical HDD) --- tests/benchmark.pl | 194 ++++++++++++++++++++++++++++++++++++ tests/mount-ecryptfs.expect | 22 ++++ 2 files changed, 216 insertions(+) create mode 100755 tests/benchmark.pl create mode 100644 tests/mount-ecryptfs.expect diff --git a/tests/benchmark.pl b/tests/benchmark.pl new file mode 100755 index 0000000..d81dbda --- /dev/null +++ b/tests/benchmark.pl @@ -0,0 +1,194 @@ +#!/usr/bin/perl + +# Benchmark EncFS against eCryptfs + +use Time::HiRes qw( time ); +use File::Temp; +use warnings; + +require("tests/common.pl"); + +# Download linux-3.0.tar.gz unless it already exists ("-c" flag) +sub dl { + our $linuxgz = "/tmp/linux-3.0.tar.gz"; + print "# downloading linux-3.0.tar.gz... "; + system("wget -nv -c https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.0.tar.gz -O $linuxgz"); + print "done\n"; +} + +# Create a new empty working directory +sub newWorkingDir { + my $prefix = shift; + my $workingDir = mkdtemp("$prefix/encfs-performance-XXXX") + || die("Could not create temporary directory"); + + return $workingDir; +} + +sub cleanup { + print "cleaning up..."; + my $workingDir = shift; + system("umount $workingDir/ecryptfs_plaintext"); + system("fusermount -u $workingDir/encfs_plaintext"); + system("rm -Rf $workingDir"); + print "done\n"; +} + +sub mount_encfs { + my $workingDir = shift; + + my $c = "$workingDir/encfs_ciphertext"; + my $p = "$workingDir/encfs_plaintext"; + + mkdir($c); + mkdir($p); + + delete $ENV{"ENCFS6_CONFIG"}; + system("./encfs/encfs --extpass=\"echo test\" --standard $c $p > /dev/null"); + waitForFile("$c/.encfs6.xml") or die("Control file not created"); + + print "# encfs mounted on $p\n"; + + return $p; +} + +sub mount_ecryptfs { + my $workingDir = shift; + + my $c = "$workingDir/ecryptfs_ciphertext"; + my $p = "$workingDir/ecryptfs_plaintext"; + + mkdir($c); + mkdir($p); + + system("expect -c \"spawn mount -t ecryptfs $c $p\" ./tests/mount-ecryptfs.expect > /dev/null") == 0 + or die("ecryptfs mount failed - are you root?"); + + print "# ecryptfs mounted on $p\n"; + + return $p; +} + +# Returns integer $milliseconds from float $seconds +sub ms { + my $seconds = shift; + my $milliseconds = int( $seconds * 1000 ); + return $milliseconds; +} + +sub benchmark { + my $dir = shift; + my $start; + our $linuxgz; + my $delta; + my $line; + + my @results = (); + + system("sync"); + print("# stream_write... "); + $start = time(); + writeZeroes( "$dir/zero", 1024 * 1024 * 100 ); + system("sync"); + $delta = time() - $start; + push( @results, [ 'stream_write', int( 100 / $delta ), "MiB/s" ] ); + printf("done\n"); + unlink("$dir/zero"); + + system("sync"); + system("cat $linuxgz > /dev/null"); + print("# extract... "); + $start = time(); + system("tar xzf $linuxgz -C $dir"); + system("sync"); + $delta = ms( time() - $start ); + push( @results, [ 'extract', $delta, "ms" ] ); + print("done\n"); + + $du = qx(du -sm $dir | cut -f1); + push( @results, [ 'du', $du, 'MB' ] ); + printf( "# disk space used: %d MB\n", $du ); + + system("echo 3 > /proc/sys/vm/drop_caches"); + $start = time(); + system("rsync -an $dir /tmp"); + $delta = time() - $start; + push( @results, [ 'rsync', ms($delta), 'ms' ] ); + printf( "# rsync took %d ms\n", ms($delta) ); + + system("echo 3 > /proc/sys/vm/drop_caches"); + system("sync"); + $start = time(); + system("rm -Rf $dir/*"); + system("sync"); + $delta = time() - $start; + push( @results, [ 'delete', ms($delta), 'ms' ] ); + printf( "# delete took %d ms\n", ms($delta) ); + + return \@results; +} + +sub tabulate { + my $r; + + $r = shift; + my @encfs = @{$r}; + $r = shift; + my @ecryptfs = @{$r}; + + print "Test | EncFS | eCryptfs | EncFS advantage\n"; + print "----------------|--------------|--------------|----------------\n"; + + for ( my $i = 0 ; $i <= $#encfs ; $i++ ) { + my $test = $encfs[$i][0]; + my $unit = $encfs[$i][2]; + + my $en = $encfs[$i][1]; + my $ec = $ecryptfs[$i][1]; + + my $ratio = $ec / $en; + if ( $unit =~ m!/s! ) { + $ratio = $en / $ec; + } + printf( "%-15s | %6d %-5s | %6d %-5s | %2.2f\n", + $test, $en, $unit, $ec, $unit, $ratio ); + } +} + +sub main { + if ( $#ARGV < 0 ) { + print "Usage: test/benchmark.pl MOUNTPOINT [MOUNTPOINT] [...]\n"; + exit(1); + } + + if ( $> != 0 ) { + print("This test must be run as root!\n"); + exit(2); + } + + dl(); + my $workingDir; + my $mountpoint; + my $prefix; + + while ( $prefix = shift(@ARGV) ) { + $workingDir = newWorkingDir($prefix); + + print "# mounting encfs\n"; + $mountpoint = mount_encfs($workingDir); + my $encfs_results = benchmark($mountpoint); + + print "# mounting ecryptfs\n"; + $mountpoint = mount_ecryptfs($workingDir); + my $ecryptfs_results = benchmark($mountpoint); + + cleanup($workingDir); + + print "\nResults for $prefix\n"; + print "==============================\n\n"; + tabulate( $encfs_results, $ecryptfs_results ); + print "\n"; + } +} + +main(); diff --git a/tests/mount-ecryptfs.expect b/tests/mount-ecryptfs.expect new file mode 100644 index 0000000..a2d3ba7 --- /dev/null +++ b/tests/mount-ecryptfs.expect @@ -0,0 +1,22 @@ +#!/bin/expect -f + +# Passed by controlling process via "-c" +#spawn mount -t ecryptfs ecryptfs_ciphertext ecryptfs_plaintext + +expect "Selection: " +send "1\n" +expect "Passphrase: " +send "test\n" +expect "Selection \\\[aes\\\]: " +send "aes\n" +expect "Selection \\\[16\\\]: " +send "16\n" +expect "Enable plaintext passthrough (y/n) \\\[n\\\]: " +send "n\n" +expect "Enable filename encryption (y/n) \\\[n\\\]: " +send "y\n" +# Filename Encryption Key (FNEK) Signature [d395309aaad4de06]: +expect "\\\]: " +send "\n" +expect "Mounted eCryptfs" +send_user "\n"