From 51a2d0ed79a32b40ce42609520fec11ff86666d2 Mon Sep 17 00:00:00 2001 From: brinn <brinn> Date: Mon, 10 Dec 2012 09:31:45 +0000 Subject: [PATCH] [CCS-22/SP-398] Genedata Performance Tuning (improve loading speed of images through the API) Close the HDF5ContainerReader on cache expiration. Add a mode for unit tests where caching is disabled and use it for all use cases with containers as they do not treat the files as immutable. SVN: 27889 --- .../openbis/common/hdf5/HDF5Container.java | 9 +++ .../common/hdf5/HDF5ContainerReader.java | 72 +++++++++++++++---- .../common/hdf5/HDF5ContainerTest.java | 7 ++ ...icalStructureDuplicatorFileToHDF5Test.java | 7 ++ .../ConcatenatedContentInputStreamTest.java | 8 +++ ...faultFileBasedHierarchicalContentTest.java | 7 ++ 6 files changed, 96 insertions(+), 14 deletions(-) diff --git a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5Container.java b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5Container.java index efc7aea1c73..cf449d9ab0c 100644 --- a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5Container.java +++ b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5Container.java @@ -29,6 +29,15 @@ import ch.systemsx.cisd.hdf5.IHDF5SimpleWriter; */ public class HDF5Container { + /** + * Disable caching for unit testing where the same file name is reused but the file content + * changes between tests. + */ + public static void disableCaching() + { + HDF5ContainerReader.disableCaching(); + } + private final File hdf5Container; /** diff --git a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5ContainerReader.java b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5ContainerReader.java index 01c3e0e0fb5..e1b2c650f79 100644 --- a/openbis-common/source/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5ContainerReader.java +++ b/openbis-common/source/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5ContainerReader.java @@ -48,12 +48,15 @@ final class HDF5ContainerReader implements IHDF5ContainerReader private final IHDF5ArchiveReader archiveReader; + private final File archiveFile; + private long lastAccessed; private int referenceCount; - Reader(IHDF5ArchiveReader archiveReader) + Reader(File archiveFile, IHDF5ArchiveReader archiveReader) { + this.archiveFile = archiveFile; this.archiveReader = archiveReader; this.lastAccessed = System.currentTimeMillis(); this.referenceCount = 1; @@ -65,6 +68,11 @@ final class HDF5ContainerReader implements IHDF5ContainerReader return archiveReader; } + File getArchiveFile() + { + return archiveFile; + } + void incCount() { ++referenceCount; @@ -75,37 +83,64 @@ final class HDF5ContainerReader implements IHDF5ContainerReader --referenceCount; } + boolean isUnreferenced() + { + return referenceCount == 0; + } + boolean isExpired() { return (referenceCount == 0 && (System.currentTimeMillis() - lastAccessed) > RETENTION_TIME_MILLIS); } } - + static { final Timer t = new Timer("HDF5ContainerReader - Cache Cleaner", true); - t.schedule(new TimerTask() { - @Override - public void run() + t.schedule(new TimerTask() { - synchronized (fileToReaderMap) + @Override + public void run() { - final Iterator<Reader> it = fileToReaderMap.values().iterator(); - while (it.hasNext()) + synchronized (fileToReaderMap) { - final Reader container = it.next(); - if (container.isExpired()) + final Iterator<Reader> it = fileToReaderMap.values().iterator(); + while (it.hasNext()) { - it.remove(); + final Reader container = it.next(); + if (container.isExpired()) + { + container.getArchiveReader().close(); + it.remove(); + } } } } - } } , CACHE_CLEANER_INTERVAL_MILLIS, CACHE_CLEANER_INTERVAL_MILLIS); + }, CACHE_CLEANER_INTERVAL_MILLIS, CACHE_CLEANER_INTERVAL_MILLIS); } private static final Map<File, Reader> fileToReaderMap = new HashMap<File, HDF5ContainerReader.Reader>(); - + + private static boolean noCaching = false; + + /** + * Disable caching for unit testing where the same file name is reused but the file content + * changes between tests. + */ + static void disableCaching() + { + noCaching = true; + synchronized (fileToReaderMap) + { + for (Reader r : fileToReaderMap.values()) + { + r.getArchiveReader().close(); + } + fileToReaderMap.clear(); + } + } + private static Reader openReader(File hdf5Container) { Reader entryOrNull; @@ -114,7 +149,8 @@ final class HDF5ContainerReader implements IHDF5ContainerReader entryOrNull = fileToReaderMap.get(hdf5Container); if (entryOrNull == null) { - entryOrNull = new Reader(HDF5ArchiverFactory.openForReading(hdf5Container)); + entryOrNull = + new Reader(hdf5Container, HDF5ArchiverFactory.openForReading(hdf5Container)); fileToReaderMap.put(hdf5Container, entryOrNull); } else { @@ -135,6 +171,14 @@ final class HDF5ContainerReader implements IHDF5ContainerReader public void close() { reader.decCount(); + if (noCaching && reader.isUnreferenced()) + { + synchronized (fileToReaderMap) + { + reader.getArchiveReader().close(); + fileToReaderMap.remove(reader.getArchiveFile()); + } + } } @Override diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5ContainerTest.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5ContainerTest.java index 3a4f58f3f04..b893a49caf1 100644 --- a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5ContainerTest.java +++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/hdf5/HDF5ContainerTest.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; @@ -35,6 +36,12 @@ public class HDF5ContainerTest extends AbstractFileSystemTestCase { private final static int KB = 1024; + @BeforeTest + public void disableHDF5ContainerCaching() + { + HDF5Container.disableCaching(); + } + @Override @BeforeMethod public void setUp() throws IOException diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/hdf5/HierarchicalStructureDuplicatorFileToHDF5Test.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/hdf5/HierarchicalStructureDuplicatorFileToHDF5Test.java index 817986f8698..e5e6c91579d 100644 --- a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/hdf5/HierarchicalStructureDuplicatorFileToHDF5Test.java +++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/hdf5/HierarchicalStructureDuplicatorFileToHDF5Test.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; @@ -34,6 +35,12 @@ public class HierarchicalStructureDuplicatorFileToHDF5Test extends AbstractFileS private HDF5Container container; + @BeforeTest + public void disableHDF5ContainerCaching() + { + HDF5Container.disableCaching(); + } + @BeforeMethod @Override public void setUp() throws IOException diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/io/ConcatenatedContentInputStreamTest.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/io/ConcatenatedContentInputStreamTest.java index f5cdd68f87e..bd908f938ba 100644 --- a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/io/ConcatenatedContentInputStreamTest.java +++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/io/ConcatenatedContentInputStreamTest.java @@ -23,11 +23,13 @@ import java.util.ArrayList; import java.util.List; import org.testng.AssertJUnit; +import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked; import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; import ch.systemsx.cisd.common.io.ConcatenatedFileOutputStreamWriter; +import ch.systemsx.cisd.openbis.common.hdf5.HDF5Container; import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContentNode; /** @@ -37,6 +39,12 @@ import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchical */ public class ConcatenatedContentInputStreamTest extends AbstractFileSystemTestCase { + @BeforeTest + public void disableHDF5ContainerCaching() + { + HDF5Container.disableCaching(); + } + @Test public void testNoFiles() throws IOException { diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentTest.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentTest.java index 90e6889e439..144b2b974da 100644 --- a/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentTest.java +++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/openbis/common/io/hierarchical_content/DefaultFileBasedHierarchicalContentTest.java @@ -29,6 +29,7 @@ import org.jmock.Expectations; import org.jmock.Mockery; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked; @@ -76,6 +77,12 @@ public class DefaultFileBasedHierarchicalContentTest extends AbstractFileSystemT private IDelegatedAction onCloseAction; + @BeforeTest + public void disableHDF5ContainerCaching() + { + HDF5Container.disableCaching(); + } + @BeforeMethod public void beforeMethod() throws Exception { -- GitLab