Skip to content

Commit

Permalink
Enable IntelInflater (#1885)
Browse files Browse the repository at this point in the history
* Fix longstanding bug so we use the Intel Inflater when it is requested

*  We have been using the Java Inflater even when the Intel one was available and requested
   due to a bug in the configuration of the default inflater.
   The fix is fairly brittle because it depends on the order of initialization of various things.
*  This will be fixed more generally by samtools/htsjdk#1666
* Add a test
  • Loading branch information
lbergelson authored Jun 2, 2023
1 parent e67fe94 commit 983e073
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/main/java/picard/cmdline/CommandLineProgram.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ public int instanceMain(final String[] argv) {
this.defaultHeaders.add(new StringHeader("Started on: " + startDate));

Log.setGlobalLogLevel(VERBOSITY);
SamReaderFactory.setDefaultValidationStringency(VALIDATION_STRINGENCY);

// Set the compression level everywhere we can think of
BlockCompressedOutputStream.setDefaultCompressionLevel(COMPRESSION_LEVEL);
Expand Down Expand Up @@ -257,6 +256,10 @@ public int instanceMain(final String[] argv) {
BlockGunzipper.setDefaultInflaterFactory(new IntelInflaterFactory());
}

// This has to happen after the inflater factory is set because it causes a reinitialization of the static
// default reader factory. At least until https:/samtools/htsjdk/issues/1666 is resolved
SamReaderFactory.setDefaultValidationStringency(VALIDATION_STRINGENCY);

if (!QUIET) {
System.err.println("[" + new Date() + "] " + commandLine);

Expand Down
57 changes: 57 additions & 0 deletions src/test/java/picard/IntelInflaterDeflaterLoadTest.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
package picard;

import com.intel.gkl.compression.IntelDeflater;
import com.intel.gkl.compression.IntelDeflaterFactory;
import com.intel.gkl.compression.IntelInflater;
import com.intel.gkl.compression.IntelInflaterFactory;
import htsjdk.samtools.SAMFileWriterFactory;
import htsjdk.samtools.SamReaderFactory;
import htsjdk.samtools.util.zip.DeflaterFactory;
import htsjdk.samtools.util.zip.InflaterFactory;
import org.apache.commons.lang3.SystemUtils;
import org.broadinstitute.barclay.argparser.CommandLineProgramProperties;
import org.testng.Assert;
import org.testng.SkipException;
import org.testng.annotations.Test;
import picard.cmdline.CommandLineProgram;
import picard.cmdline.programgroups.OtherProgramGroup;
import picard.cmdline.programgroups.Testing;

import java.lang.reflect.Field;

/**
* Test that the Intel Inflater and Deflater can be loaded successfully.
Expand All @@ -25,6 +37,20 @@ public void testIntelDeflaterIsAvailable() {
"Intel shared library was not loaded. This could be due to a configuration error, or your system might not support it.");
}

@Test
public void testIntelInflaterIsUsed(){
final InflaterDeflaterTester cmd = new InflaterDeflaterTester();
cmd.instanceMain(new String[]{});
Assert.assertEquals(cmd.inflaterFactory.getClass(), IntelInflaterFactory.class);
}

@Test
public void testDeflaterIsUsed(){
final InflaterDeflaterTester cmd = new InflaterDeflaterTester();
cmd.instanceMain(new String[]{});
Assert.assertEquals(cmd.deflaterFactory.getClass(), IntelDeflaterFactory.class);
}

private void checkIntelSupported(final String componentName) {
if (!SystemUtils.IS_OS_LINUX && !SystemUtils.IS_OS_MAC) {
throw new SkipException(componentName + " is not available on this platform");
Expand All @@ -34,4 +60,35 @@ private void checkIntelSupported(final String componentName) {
throw new SkipException(componentName + " is not available for this architecture");
}
}


@CommandLineProgramProperties(summary = "test program for checking if the intel optimized inflater/deflater are active",
oneLineSummary = "test program please ignore",
programGroup = Testing.class,
omitFromCommandLine = true)
public static class InflaterDeflaterTester extends CommandLineProgram {
public InflaterFactory inflaterFactory;
public DeflaterFactory deflaterFactory;

@Override
protected int doWork() {
final SamReaderFactory samReaderFactory = SamReaderFactory.makeDefault();
inflaterFactory = getFieldValue(samReaderFactory, "inflaterFactory", InflaterFactory.class);

final SAMFileWriterFactory samFileWriterFactory = new SAMFileWriterFactory();
deflaterFactory = getFieldValue(samFileWriterFactory, "deflaterFactory", DeflaterFactory.class);

return 0;
}

private <T,R> R getFieldValue(final T obj,final String fieldName, Class<R> clazz) {
try {
final Field deflaterFactoryField = obj.getClass().getDeclaredField(fieldName);
deflaterFactoryField.setAccessible(true);
return clazz.cast(deflaterFactoryField.get(obj));
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}

0 comments on commit 983e073

Please sign in to comment.