Omaha #3499 added sparse array memory optimization to grid
Change-Id: I1db409a565e371fe5aa90f3dc7f921ea1004baa9 Former-commit-id:c6fa6d0103
[formerly9b4a50cef9
] [formerly8dc30a64de
] [formerlyc6fa6d0103
[formerly9b4a50cef9
] [formerly8dc30a64de
] [formerlyfcb130e3f8
[formerly8dc30a64de
[formerly 3b6b13dcf270aac9d19dee095dfd6bd78f13137d]]]] Former-commit-id:fcb130e3f8
Former-commit-id:7cd33b0c40
[formerlyb37123e294
] [formerly 292e84b7442b67dc13c460bf6da7626e3cce86bb [formerlyf3edb035d4
]] Former-commit-id: 78e5d13d1a71e02d9e5b46edd328a8bfb1418532 [formerlybb0bb8dce0
] Former-commit-id:7b8253f02e
This commit is contained in:
parent
8ac0363ce3
commit
3e5879a335
1 changed files with 126 additions and 12 deletions
|
@ -36,6 +36,9 @@ import org.geotools.coverage.grid.GridGeometry2D;
|
|||
|
||||
import com.raytheon.uf.common.numeric.DataUtilities;
|
||||
import com.raytheon.uf.common.numeric.buffer.FloatBufferWrapper;
|
||||
import com.raytheon.uf.common.numeric.source.DataSource;
|
||||
import com.raytheon.uf.common.numeric.sparse.SparseArray;
|
||||
import com.raytheon.uf.common.numeric.sparse.SparseFloatArray;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||
|
@ -51,6 +54,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Feb 25, 2014 2791 bsteffen Initial creation
|
||||
* Aug 06, 2014 3499 bclement added sparse array optimization
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -77,6 +81,14 @@ public class GridMemoryManager {
|
|||
* the available direct memory.
|
||||
*/
|
||||
private static final double DIRECT_MEMORY_PERCENTAGE = 0.75f;
|
||||
|
||||
private static final int SPARSE_CHECK_THRESHOLD = Integer.getInteger(
|
||||
"grid.sparse.check.threshold", 100 * 1024 * 1024); // 100 MB
|
||||
|
||||
private static final int SPARSE_ARRAY_BLOCK_SIZE = Integer.getInteger(
|
||||
"grid.sparse.block.size", SparseArray.DEFAULT_BLOCK_SIZE);
|
||||
|
||||
private static final float SPARSE_FILL_VALUE = Float.NaN;
|
||||
|
||||
private static GridMemoryManager instance;
|
||||
|
||||
|
@ -128,8 +140,8 @@ public class GridMemoryManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* If there is free direct memory then copy data into direct memory.
|
||||
* Otherwise just return data as is.
|
||||
* Attempt to make memory optimizations if applicable. Otherwise just return
|
||||
* data as is.
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
|
@ -144,19 +156,31 @@ public class GridMemoryManager {
|
|||
sizeInBytes *= 2;
|
||||
}
|
||||
|
||||
long r = remainingDirectMemory.get();
|
||||
boolean makeDirect = false;
|
||||
while (r > sizeInBytes && makeDirect == false) {
|
||||
if (remainingDirectMemory.compareAndSet(r, r - sizeInBytes)) {
|
||||
makeDirect = true;
|
||||
}
|
||||
r = remainingDirectMemory.get();
|
||||
/*
|
||||
* TODO checking for memory optimizations could be moved to an external
|
||||
* class so things like GFE could take advantage of it
|
||||
*/
|
||||
if (sizeInBytes > SPARSE_CHECK_THRESHOLD && isSparse(data)) {
|
||||
data = convertToSparse(data);
|
||||
} else if (hasAvailableDirectMemory(sizeInBytes)) {
|
||||
data = convertToDirect(data, sizeInBytes, numGridPoints);
|
||||
}
|
||||
|
||||
if (!makeDirect) {
|
||||
return data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads grid data into direct memory buffers
|
||||
*
|
||||
* @param data
|
||||
* @param sizeInBytes
|
||||
* @param numGridPoints
|
||||
* @return a new grid data object with direct memory data sources
|
||||
*/
|
||||
private GeneralGridData convertToDirect(GeneralGridData data,
|
||||
int sizeInBytes, int numGridPoints) {
|
||||
GridGeometry2D gridGeometry = data.getGridGeometry();
|
||||
GridEnvelope2D gridRange = gridGeometry.getGridRange2D();
|
||||
try {
|
||||
ByteBuffer directBuffer = ByteBuffer.allocateDirect(sizeInBytes);
|
||||
livingRefs.add(new DirectBufferTrackingReference(directBuffer,
|
||||
|
@ -193,6 +217,96 @@ public class GridMemoryManager {
|
|||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sizeInBytes
|
||||
* @return true if there is enough direct memory for the provided grid size
|
||||
*/
|
||||
private boolean hasAvailableDirectMemory(int sizeInBytes) {
|
||||
long r = remainingDirectMemory.get();
|
||||
boolean makeDirect = false;
|
||||
while (r > sizeInBytes && makeDirect == false) {
|
||||
if (remainingDirectMemory.compareAndSet(r, r - sizeInBytes)) {
|
||||
makeDirect = true;
|
||||
}
|
||||
r = remainingDirectMemory.get();
|
||||
}
|
||||
return makeDirect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data
|
||||
* @param gridRange
|
||||
* @return true if the data is mostly comprised of NaNs
|
||||
*/
|
||||
private boolean isSparse(GeneralGridData data) {
|
||||
GridGeometry2D gridGeometry = data.getGridGeometry();
|
||||
GridEnvelope2D gridRange = gridGeometry.getGridRange2D();
|
||||
DataSource source;
|
||||
if (data.isVector()) {
|
||||
source = data.getUComponent();
|
||||
} else {
|
||||
source = data.getScalarData();
|
||||
}
|
||||
int nx = gridRange.width;
|
||||
int ny = gridRange.height;
|
||||
long nandCount = 0;
|
||||
long largestNandRun = Long.MIN_VALUE;
|
||||
long currentNandRun = 0;
|
||||
boolean inRun = false;
|
||||
for (int y = 0; y < ny; y += 1) {
|
||||
for (int x = 0; x < nx; x += 1) {
|
||||
if (Double.isNaN(source.getDataValue(x, y))) {
|
||||
if (!inRun){
|
||||
inRun = true;
|
||||
}
|
||||
nandCount += 1;
|
||||
currentNandRun += 1;
|
||||
} else {
|
||||
if (inRun){
|
||||
inRun = false;
|
||||
largestNandRun = Math.max(largestNandRun, currentNandRun);
|
||||
currentNandRun = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return largestNandRun > SPARSE_ARRAY_BLOCK_SIZE
|
||||
&& nandCount > ((nx * ny) / 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data into a sparse arrays.
|
||||
*
|
||||
* @param data
|
||||
* @return a new grid data object with sparse array data sources
|
||||
*/
|
||||
private GeneralGridData convertToSparse(GeneralGridData data) {
|
||||
GridGeometry2D gridGeometry = data.getGridGeometry();
|
||||
GridEnvelope2D gridRange = gridGeometry.getGridRange2D();
|
||||
int nx = gridRange.width;
|
||||
int ny = gridRange.height;
|
||||
if (data.isVector()) {
|
||||
DataSource uSource = data.getUComponent();
|
||||
DataSource vSource = data.getVComponent();
|
||||
SparseFloatArray uDest = new SparseFloatArray(nx, ny,
|
||||
SPARSE_FILL_VALUE, SPARSE_ARRAY_BLOCK_SIZE);
|
||||
SparseFloatArray vDest = new SparseFloatArray(nx, ny,
|
||||
SPARSE_FILL_VALUE, SPARSE_ARRAY_BLOCK_SIZE);
|
||||
DataUtilities.copy(uSource, uDest, nx, ny);
|
||||
DataUtilities.copy(vSource, vDest, nx, ny);
|
||||
data = GeneralGridData.createVectorDataUV(gridGeometry, uDest,
|
||||
vDest, data.getDataUnit());
|
||||
} else {
|
||||
DataSource source = data.getScalarData();
|
||||
SparseFloatArray dest = new SparseFloatArray(nx, ny,
|
||||
SPARSE_FILL_VALUE, SPARSE_ARRAY_BLOCK_SIZE);
|
||||
DataUtilities.copy(source, dest, nx, ny);
|
||||
data = GeneralGridData.createScalarData(gridGeometry, dest,
|
||||
data.getDataUnit());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private void free() {
|
||||
DirectBufferTrackingReference ref = (DirectBufferTrackingReference) refQueue
|
||||
.poll();
|
||||
|
|
Loading…
Add table
Reference in a new issue