diff --git a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponentIntegrationTest.java b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponentIntegrationTest.java index f34e10bac..e549a2de1 100644 --- a/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponentIntegrationTest.java +++ b/main/filesystem-crypto/src/test/java/org/cryptomator/filesystem/crypto/CryptoFileSystemComponentIntegrationTest.java @@ -1,5 +1,6 @@ package org.cryptomator.filesystem.crypto; +import java.io.IOException; import java.nio.ByteBuffer; import java.util.Arrays; @@ -14,11 +15,15 @@ import org.cryptomator.filesystem.inmem.InMemoryFileSystem; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class CryptoFileSystemComponentIntegrationTest { private static final CryptoFileSystemComponent cryptoFsComp = DaggerCryptoFileSystemComponent.builder().cryptoEngineModule(new CryptoEngineTestModule()).build(); + private static final Logger LOG = LoggerFactory.getLogger(CryptoFileSystemComponentIntegrationTest.class); + private FileSystem ciphertextFs; private FileSystem cleartextFs; @@ -72,6 +77,37 @@ public class CryptoFileSystemComponentIntegrationTest { } } + @Test(timeout = 2000000) // assuming a minimum speed of 10mb/s during encryption and decryption 20s should be enough + public void testEncryptionAndDecryptionSpeed() throws InterruptedException, IOException { + File file = cleartextFs.file("benchmark.test"); + + final long encStart = System.nanoTime(); + try (WritableFile writable = file.openWritable()) { + final ByteBuffer cleartext = ByteBuffer.allocate(100000); // 100k + for (int i = 0; i < 1000; i++) { // 100M total + cleartext.rewind(); + writable.write(cleartext); + } + } + final long encEnd = System.nanoTime(); + LOG.debug("Encryption of 100M took {}ms", (encEnd - encStart) / 1000 / 1000); + + final long decStart = System.nanoTime(); + try (ReadableFile readable = file.openReadable()) { + final ByteBuffer cleartext = ByteBuffer.allocate(100000); // 100k + for (int i = 0; i < 1000; i++) { // 100M total + cleartext.clear(); + readable.read(cleartext); + cleartext.flip(); + Assert.assertEquals(cleartext.get(), 0x00); + } + } + final long decEnd = System.nanoTime(); + LOG.debug("Decryption of 100M took {}ms", (decEnd - decStart) / 1000 / 1000); + + file.delete(); + } + @Test public void testRandomAccess() { File cleartextFile = cleartextFs.file("test"); diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java index f58b5b579..711d68cea 100644 --- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java +++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryFile.java @@ -23,11 +23,18 @@ import org.cryptomator.filesystem.WritableFile; class InMemoryFile extends InMemoryNode implements File { + /** 1000kb */ + static final int INITIAL_SIZE = 100 * 1024; + + /** 140% */ + static final double GROWTH_RATE = 1.4; + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - private ByteBuffer content = ByteBuffer.allocate(0); + private volatile ByteBuffer content = ByteBuffer.allocate(INITIAL_SIZE); public InMemoryFile(InMemoryFolder parent, String name, Instant lastModified, Instant creationTime) { super(parent, name, lastModified, creationTime); + content.flip(); } @Override diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryReadableFile.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryReadableFile.java index 19dc10040..e7055f200 100644 --- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryReadableFile.java +++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryReadableFile.java @@ -22,7 +22,7 @@ class InMemoryReadableFile implements ReadableFile { private final Supplier contentGetter; private final ReadLock readLock; private boolean open = true; - private int position = 0; + private volatile int position = 0; public InMemoryReadableFile(Supplier contentGetter, ReadLock readLock) { this.contentGetter = contentGetter; diff --git a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryWritableFile.java b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryWritableFile.java index acc00a9e2..d16278510 100644 --- a/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryWritableFile.java +++ b/main/filesystem-inmemory/src/main/java/org/cryptomator/filesystem/inmem/InMemoryWritableFile.java @@ -28,7 +28,7 @@ public class InMemoryWritableFile implements WritableFile { private final WriteLock writeLock; private boolean open = true; - private int position = 0; + private volatile int position = 0; public InMemoryWritableFile(Consumer lastModifiedSetter, Consumer creationTimeSetter, Supplier contentGetter, Consumer contentSetter, Consumer deleter, WriteLock writeLock) { @@ -74,15 +74,19 @@ public class InMemoryWritableFile implements WritableFile { @Override public int write(ByteBuffer source) throws UncheckedIOException { ByteBuffer destination = contentGetter.get(); + int oldFileSize = destination.limit(); int requiredSize = position + source.remaining(); + int newFileSize = Math.max(oldFileSize, requiredSize); if (destination.capacity() < requiredSize) { ByteBuffer old = destination; - old.rewind(); - destination = ByteBuffer.allocate(requiredSize); + old.clear(); + int newBufferSize = Math.max(requiredSize, (int) (destination.capacity() * InMemoryFile.GROWTH_RATE)); + destination = ByteBuffer.allocate(newBufferSize); ByteBuffers.copy(old, destination); contentSetter.accept(destination); } destination.position(position); + destination.limit(newFileSize); int numWritten = ByteBuffers.copy(source, destination); this.position += numWritten; return numWritten;