From 92280b4068e80bf17b6d4a615e6604a6ad6e8be1 Mon Sep 17 00:00:00 2001 From: Eric Banks Date: Fri, 8 Jun 2012 13:54:37 -0400 Subject: [PATCH] BQSR optimization: cache the BitSetUtils.bitSetFrom() calls since they are called over and over again with the same values. Another 10% reduction in runtime. --- .../gatk/walkers/bqsr/BQSRKeyManager.java | 21 ++++++++++++++----- .../sting/utils/BitSetUtils.java | 11 +++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRKeyManager.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRKeyManager.java index c1449c5b3..728d1a8d4 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRKeyManager.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/bqsr/BQSRKeyManager.java @@ -66,7 +66,7 @@ public class BQSRKeyManager { for (Covariate optional : optionalCovariates) { int nBits = optional.numberOfBits(); // number of bits used by this covariate nOptionalBits = Math.max(nOptionalBits, nBits); // optional covariates are represented by the number of bits needed by biggest covariate - BitSet optionalID = BitSetUtils.bitSetFrom(id); // calculate the optional covariate ID for this covariate + BitSet optionalID = bitSetFromId(id); // calculate the optional covariate ID for this covariate optionalCovariatesInfo.add(new OptionalCovariateInfo(optionalID, optional)); // optional covariates have standardized mask and number of bits, so no need to store in the RequiredCovariateInfo object String covariateName = optional.getClass().getSimpleName().split("Covariate")[0]; // get the name of the covariate (without the "covariate" part of it) so we can match with the GATKReport covariateNameToIDMap.put(covariateName, id); @@ -100,7 +100,7 @@ public class BQSRKeyManager { public List bitSetsFromAllKeys(BitSet[] allKeys, EventType eventType) { List allBitSets = new ArrayList(); // Generate one key per optional covariate - BitSet eventBitSet = BitSetUtils.bitSetFrom(eventType.index); // create a bitset with the event type + BitSet eventBitSet = bitSetFromEvent(eventType); // create a bitset with the event type int eventTypeBitIndex = nRequiredBits + nOptionalBits + nOptionalIDBits; // Location in the bit set to add the event type bits int covariateIndex = 0; @@ -257,9 +257,20 @@ public class BQSRKeyManager { eventKey.set(i - firstBitIndex); return EventType.eventFrom(BitSetUtils.shortFrom(eventKey)); } - - private BitSet bitSetFromEvent(EventType eventType) { - return BitSetUtils.bitSetFrom(eventType.index); + + // cache the BitSet representing an event since it's otherwise created a massive amount of times + private static final Map eventTypeCache = new HashMap(EventType.values().length); + static { + for (final EventType eventType : EventType.values()) + eventTypeCache.put(eventType, BitSetUtils.bitSetFrom(eventType.index)); + } + + private BitSet bitSetFromEvent(final EventType eventType) { + return eventTypeCache.get(eventType); + } + + private BitSet bitSetFromId(final short id) { + return BitSetUtils.bitSetFrom(id); } private int bitsInEventType() { diff --git a/public/java/src/org/broadinstitute/sting/utils/BitSetUtils.java b/public/java/src/org/broadinstitute/sting/utils/BitSetUtils.java index 41889e2f5..aa7cd4b37 100644 --- a/public/java/src/org/broadinstitute/sting/utils/BitSetUtils.java +++ b/public/java/src/org/broadinstitute/sting/utils/BitSetUtils.java @@ -5,6 +5,8 @@ import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.util.BitSet; +import java.util.HashMap; +import java.util.Map; /** * Utilities for bitset conversion @@ -71,8 +73,15 @@ public class BitSetUtils { * @return a bitset representation of the short */ public static BitSet bitSetFrom(short number) { - return bitSetFrom(number, NBITS_SHORT_REPRESENTATION); + BitSet result = shortCache.get(number); + if (result == null) { + result = bitSetFrom(number, NBITS_SHORT_REPRESENTATION); + shortCache.put(number, result); + } + return result; } + // use a static cache for shorts (but not for longs, because there could be a lot of entries) + private static final Map shortCache = new HashMap(2 * Short.MAX_VALUE); /** * Creates a BitSet representation of an arbitrary integer (number of bits capped at 64 -- long precision)