Skip to content

Commit

Permalink
Merge pull request opensha#105 from GNS-Science/oakley/memory-perf
Browse files Browse the repository at this point in the history
SectIDRange memory usage improvements
  • Loading branch information
kevinmilner authored Apr 4, 2024
2 parents 160cc57 + 592db32 commit 068c52a
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import com.google.common.base.Preconditions;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* Range of section IDs, inclusive, for memory efficient tracking of unique ruptures and contains
* operations
Expand All @@ -10,53 +13,74 @@
*
*/
public abstract class SectIDRange implements Comparable<SectIDRange> {


private final static Map<SectIDRange, SectIDRange> cache = new ConcurrentHashMap<>();

public static SectIDRange build(int startID, int endID) {
if (startID == endID)
return new SingleID(endID);
if (endID < Short.MAX_VALUE)
SectIDRange range = construct(startID, endID);
// try to use non-blocking get operation before using blocking putIfAbsent
SectIDRange cached = cache.get(range);
if (cached == null) {
cached = cache.putIfAbsent(range, range);
}
return cached == null ? range : cached;
}

private static SectIDRange construct(int startID, int endID) {
if (endID < Short.MAX_VALUE) {
if (startID == endID) {
return new ShortSingleID(endID);
}
return new ShortIDRange(startID, endID);
}
if (startID == endID) {
return new SingleID(endID);
}
return new IntIDRange(startID, endID);
}

private static class ShortIDRange extends SectIDRange {

private final short[] values;


private final short startID;
private final short endID;

private ShortIDRange(int startID, int endID) {
super(startID, endID);
values = new short[] { (short)startID, (short)endID };
this.startID = (short) startID;
this.endID = (short) endID;
}

@Override
int getStartID() {
return values[0];
return startID;
}

@Override
int getEndID() {
return values[1];
return endID;
}

}

private static class IntIDRange extends SectIDRange {

private final int[] values;
private final int startID;
private final int endID;

private IntIDRange(int startID, int endID) {
super(startID, endID);
values = new int[] { startID, endID };
this.startID = startID;
this.endID = endID;
}

@Override
int getStartID() {
return values[0];
return startID;
}

@Override
int getEndID() {
return values[1];
return endID;
}

}
Expand All @@ -79,6 +103,25 @@ int getEndID() {
return id;
}
}

private static class ShortSingleID extends SectIDRange {
private final short id;

private ShortSingleID(int id) {
super(id, id);
this.id = (short) id;
}

@Override
int getStartID() {
return id;
}

@Override
int getEndID() {
return id;
}
}

private SectIDRange(int startID, int endID) {
Preconditions.checkArgument(startID >= 0, "startID=%s must be >= 0", startID);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

@RunWith(Suite.class)
@Suite.SuiteClasses({
UniqueRuptureTest.class,
UniqueRuptureTest.class,
SectIDRangeTest.class
})

public class RuptureUtilTestSuite {
public static void main(String args[]) {
org.junit.runner.JUnitCore.runClasses(RuptureUtilTestSuite.class);
org.junit.runner.JUnitCore.runClasses(RuptureUtilTestSuite.class, SectIDRangeTest.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.opensha.sha.earthquake.faultSysSolution.ruptures.util;

import org.junit.Test;

import static org.junit.Assert.*;

public class SectIDRangeTest {

@Test
public void testSingleShort() {
SectIDRange rangeA = SectIDRange.build(1, 1);

assertEquals(1, rangeA.getStartID());
assertEquals(1, rangeA.getEndID());
assertEquals(1, rangeA.size());

SectIDRange rangeB = SectIDRange.build(1, 1);

assertSame(rangeA, rangeB);
assertEquals(rangeA, rangeB);
assertEquals(rangeA.hashCode(), rangeB.hashCode());

rangeB = SectIDRange.build(2, 2);

assertEquals(1, rangeB.size());
assertNotSame(rangeA, rangeB);
assertNotEquals(rangeA, rangeB);
}

@Test
public void testSingleInt() {

SectIDRange rangeA = SectIDRange.build(Short.MAX_VALUE + 5, Short.MAX_VALUE + 5);

assertEquals(Short.MAX_VALUE + 5, rangeA.getStartID());
assertEquals(Short.MAX_VALUE + 5, rangeA.getEndID());
assertEquals(1, rangeA.size());

SectIDRange rangeB = SectIDRange.build(Short.MAX_VALUE + 5, Short.MAX_VALUE + 5);

assertSame(rangeA, rangeB);
assertEquals(rangeA, rangeB);
assertEquals(rangeA.hashCode(), rangeB.hashCode());

rangeB = SectIDRange.build(Short.MAX_VALUE + 6, Short.MAX_VALUE + 6);

assertNotSame(rangeA, rangeB);
assertNotEquals(rangeA, rangeB);
}

@Test
public void testRangeShort() {
SectIDRange rangeA = SectIDRange.build(1, 2);

assertEquals(1, rangeA.getStartID());
assertEquals(2, rangeA.getEndID());
assertEquals(2, rangeA.size());

SectIDRange rangeB = SectIDRange.build(1, 2);

assertSame(rangeA, rangeB);
assertEquals(rangeA, rangeB);
assertEquals(rangeA.hashCode(), rangeB.hashCode());

rangeB = SectIDRange.build(2, 3);

assertNotSame(rangeA, rangeB);
assertNotEquals(rangeA, rangeB);
}

@Test
public void testRangeInt() {

SectIDRange rangeA = SectIDRange.build(Short.MAX_VALUE + 5, Short.MAX_VALUE + 15);

assertEquals(Short.MAX_VALUE + 5, rangeA.getStartID());
assertEquals(Short.MAX_VALUE + 15, rangeA.getEndID());
assertEquals(11, rangeA.size());

SectIDRange rangeB = SectIDRange.build(Short.MAX_VALUE + 5, Short.MAX_VALUE + 15);

assertSame(rangeA, rangeB);
assertEquals(rangeA, rangeB);
assertEquals(rangeA.hashCode(), rangeB.hashCode());

rangeB = SectIDRange.build(Short.MAX_VALUE + 5, Short.MAX_VALUE + 16);

assertNotSame(rangeA, rangeB);
assertNotEquals(rangeA, rangeB);
}
}

0 comments on commit 068c52a

Please sign in to comment.