Skip to content

Commit a900b7c

Browse files
author
Lee Rhodes
committed
Updates to Quantiles to allow down sampling.
Refined the Memory interface for get/set MemoryRequest
1 parent fb8c745 commit a900b7c

11 files changed

Lines changed: 585 additions & 170 deletions

File tree

src/main/java/com/yahoo/sketches/memory/AllocMemory.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
import static com.yahoo.sketches.memory.UnsafeUtil.unsafe;
88

9-
import java.util.Arrays;
10-
119
/**
1210
* The AllocMemory class is a subclass of NativeMemory and is used to allocate direct, off-heap
1311
* native memory, which is then accessed by the NativeMemory methods.
@@ -26,7 +24,9 @@ public class AllocMemory extends NativeMemory {
2624
* @param capacityBytes the size in bytes of the native memory
2725
*/
2826
public AllocMemory(long capacityBytes) {
29-
super(0L, null, null, unsafe.allocateMemory(capacityBytes), capacityBytes);
27+
super(0L, null, null);
28+
super.nativeRawStartAddress_ = unsafe.allocateMemory(capacityBytes);
29+
super.capacityBytes_ = capacityBytes;
3030
super.memReq_ = null;
3131
}
3232

@@ -38,7 +38,9 @@ public AllocMemory(long capacityBytes) {
3838
* @param memReq The MemoryRequest callback
3939
*/
4040
public AllocMemory(long capacityBytes, MemoryRequest memReq) {
41-
super(0L, null, null, unsafe.allocateMemory(capacityBytes), capacityBytes);
41+
super(0L, null, null);
42+
super.nativeRawStartAddress_ = unsafe.allocateMemory(capacityBytes);
43+
super.capacityBytes_ = capacityBytes;
4244
super.memReq_ = memReq;
4345
}
4446

@@ -52,14 +54,15 @@ public AllocMemory(long capacityBytes, MemoryRequest memReq) {
5254
* The OS is free to just expand the capacity of the current allocation at the same native
5355
* address, or reassign a completely different native address in which case the origMem will be
5456
* freed by the OS.
55-
* The origMem internals will be reset to zero or nulls and must not be used again.
57+
* The origMem capacity will be set to zero and must not be used again.
5658
*
5759
* @param newCapacityBytes the desired new capacity of the newly allocated memory in bytes
5860
* @param memReq The MemoryRequest callback, which may be null.
5961
*/
6062
public AllocMemory(NativeMemory origMem, long newCapacityBytes, MemoryRequest memReq) {
61-
super(0L, null, null,
62-
unsafe.reallocateMemory(origMem.nativeRawStartAddress_, newCapacityBytes), newCapacityBytes);
63+
super(0L, null, null);
64+
super.nativeRawStartAddress_ = unsafe.reallocateMemory(origMem.nativeRawStartAddress_, newCapacityBytes);
65+
super.capacityBytes_ = newCapacityBytes;
6366
this.memReq_ = memReq;
6467
origMem.nativeRawStartAddress_ = 0; //does not require freeMem
6568
origMem.capacityBytes_ = 0; //Cannot be used again
@@ -71,17 +74,18 @@ public AllocMemory(NativeMemory origMem, long newCapacityBytes, MemoryRequest me
7174
* zero to copyToBytes; clear the new memory from copyToBytes to capacityBytes.
7275
* @param origMem The original NativeMemory, a portion of which will be copied to the
7376
* newly allocated Memory.
74-
* The reference must not be null.
77+
* The reference must not be null.
7578
* This origMem is not modified in any way, may be reused and must be freed appropriately.
7679
* @param copyToBytes the upper limit of the region to be copied from origMem to the newly
7780
* allocated memory.
7881
* @param capacityBytes the desired new capacity of the newly allocated memory in bytes and the
7982
* upper limit of the region to be cleared.
8083
* @param memReq The MemoryRequest callback, which may be null.
8184
*/
82-
public AllocMemory(NativeMemory origMem, long copyToBytes, long capacityBytes,
83-
MemoryRequest memReq) {
84-
super(0L, null, null, unsafe.allocateMemory(capacityBytes), capacityBytes);
85+
public AllocMemory(NativeMemory origMem, long copyToBytes, long capacityBytes, MemoryRequest memReq) {
86+
super(0L, null, null);
87+
super.nativeRawStartAddress_ = unsafe.allocateMemory(capacityBytes);
88+
super.capacityBytes_ = capacityBytes;
8589
this.memReq_ = memReq;
8690
MemoryUtil.copy(origMem, 0, this, 0, copyToBytes);
8791
this.clear(copyToBytes, capacityBytes-copyToBytes);
@@ -102,7 +106,10 @@ protected void finalize() {
102106
System.err.println(
103107
"ERROR: freeMemory() has not been called: Address: "+ nativeRawStartAddress_ +
104108
", capacity: " + capacityBytes_);
105-
System.err.println(Arrays.toString(Thread.currentThread().getStackTrace()));
109+
java.lang.StackTraceElement[] arr = Thread.currentThread().getStackTrace();
110+
for (int i=0; i<arr.length; i++) {
111+
System.err.println(arr[i].toString());
112+
}
106113
}
107114
}
108115

src/main/java/com/yahoo/sketches/memory/Memory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,12 @@ public interface Memory {
434434
*/
435435
Object getParent();
436436

437+
/**
438+
* Sets a MemoryRequest
439+
* @param memReq the MemoryRequest
440+
*/
441+
void setMemoryRequest(MemoryRequest memReq);
442+
437443
/**
438444
* Returns a formatted hex string of an area of this Memory.
439445
* Used primarily for testing.

src/main/java/com/yahoo/sketches/memory/MemoryRegion.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public class MemoryRegion implements Memory {
3838
private final Memory mem_;
3939
private volatile long memOffsetBytes_;
4040
private volatile long capacityBytes_;
41-
private MemoryRequest memReq_ = null;
41+
private volatile MemoryRequest memReq_ = null;
4242

4343
/**
4444
* Defines a region of the given parent Memory by defining an offset and capacity that are
@@ -431,14 +431,23 @@ public Object getParent() {
431431
return mem_;
432432
}
433433

434+
@Override
435+
public void setMemoryRequest(MemoryRequest memReq) {
436+
memReq_ = memReq;
437+
}
438+
434439
@Override
435440
public String toHexString(String header, long offsetBytes, int lengthBytes) {
436441
assertBounds(offsetBytes, lengthBytes, capacityBytes_);
437442
StringBuilder sb = new StringBuilder();
438443
sb.append(header).append("\n");
439-
String s1 = String.format("(%d, %d)", offsetBytes, lengthBytes);
440-
sb.append(this.getClass().getName());
441-
sb.append(".toHexString").append(s1).append(", hash: ").append(this.hashCode()).append(":");
444+
String s1 = String.format("(..., %d, %d)", offsetBytes, lengthBytes);
445+
sb.append(this.getClass().getSimpleName()).append(".toHexString").
446+
append(s1).append(", hash: ").append(this.hashCode()).append("\n");
447+
sb.append(" MemoryRequest: ");
448+
if (memReq_ != null) {
449+
sb.append(memReq_.getClass().getSimpleName()).append(", hash: ").append(memReq_.hashCode());
450+
} else sb.append("null");
442451
return mem_.toHexString(sb.toString(), getAddress(offsetBytes), lengthBytes);
443452
}
444453

src/main/java/com/yahoo/sketches/memory/NativeMemory.java

Lines changed: 65 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -46,71 +46,77 @@
4646
*/
4747
@SuppressWarnings("restriction")
4848
public class NativeMemory implements Memory {
49-
protected final long objectBaseOffset_; //only non-zero for on-heap objects. freeMemory sets to 0.
50-
protected final Object memArray_; //null for off-heap, valid for on-heap.
51-
protected MemoryRequest memReq_ = null; //set via AllocMemory
49+
/*
50+
Class Case ObjBaseOff MemArr byteBuf rawAdd CapacityBytes ReqFree Direct
51+
NativeMemory byteArr >0 valid null 0 >0 FALSE FALSE
52+
NativeMemory longArr >0 valid null 0 >0 FALSE FALSE
53+
NativeMemory ByteBuffer Direct 0 null valid >0 >0 FALSE TRUE
54+
NativeMemory ByteBuffer not Direct >0 valid valid 0 >0 FALSE FALSE
55+
AllocMemory All cases 0 null null >0 >0 TRUE TRUE
56+
*/
57+
protected final long objectBaseOffset_;
58+
protected final Object memArray_;
5259
//holding on to this to make sure that it is not garbage collected before we are done with it.
5360
protected final ByteBuffer byteBuf_;
54-
55-
protected long nativeRawStartAddress_; //only non-zero for native
56-
protected long capacityBytes_; //only non-zero if allocated and class still valid
57-
58-
protected NativeMemory(long objectBaseOffset, Object memArray, ByteBuffer byteBuf,
59-
long nativeRawStartAddress, long capacityBytes) {
60-
this.objectBaseOffset_ = objectBaseOffset;
61-
this.memArray_ = memArray;
62-
this.byteBuf_ = byteBuf;
63-
this.nativeRawStartAddress_ = nativeRawStartAddress;
64-
this.capacityBytes_ = capacityBytes;
61+
protected volatile long nativeRawStartAddress_;
62+
protected volatile long capacityBytes_;
63+
protected volatile MemoryRequest memReq_ = null; //set via AllocMemory
64+
65+
//only sets the finals
66+
protected NativeMemory(long objectBaseOffset, Object memArray, ByteBuffer byteBuf) {
67+
objectBaseOffset_ = objectBaseOffset;
68+
memArray_ = memArray;
69+
byteBuf_ = byteBuf;
6570
}
6671

6772
/**
6873
* Provides access to the given byteArray using Memory interface
6974
* @param byteArray an on-heap byte array
7075
*/
7176
public NativeMemory(byte[] byteArray) {
72-
int arrLen = byteArray.length;
73-
memArray_ = byteArray;
74-
objectBaseOffset_ = BYTE_ARRAY_BASE_OFFSET;
77+
this(BYTE_ARRAY_BASE_OFFSET, byteArray, null);
78+
if ((byteArray == null) || (byteArray.length == 0)) {
79+
throw new IllegalArgumentException(
80+
"Array must must not be null and have a length greater than zero.");
81+
}
7582
nativeRawStartAddress_ = 0L;
76-
capacityBytes_ = arrLen;
77-
byteBuf_ = null;
83+
capacityBytes_ = byteArray.length;
84+
7885
}
7986

8087
/**
8188
* Provides access to the given longArray using Memory interface
8289
* @param longArray an on-heap long array
8390
*/
8491
public NativeMemory(long[] longArray) {
85-
int arrLen = longArray.length;
86-
if (arrLen <= 0) {
92+
this(LONG_ARRAY_BASE_OFFSET, longArray, null);
93+
if ((longArray == null) || (longArray.length == 0)) {
8794
throw new IllegalArgumentException(
88-
"longArray must have a length greater than zero.");
95+
"Array must must not be null and have a length greater than zero.");
8996
}
90-
memArray_ = longArray;
91-
objectBaseOffset_ = LONG_ARRAY_BASE_OFFSET;
9297
nativeRawStartAddress_ = 0L;
93-
capacityBytes_ = arrLen << LONG_SHIFT;
94-
byteBuf_ = null;
98+
capacityBytes_ = longArray.length << LONG_SHIFT;
9599
}
96100

97101
/**
98102
* Provides access to the backing store of the given ByteBuffer using Memory interface
99103
* @param byteBuf the given ByteBuffer
100104
*/
101105
public NativeMemory(ByteBuffer byteBuf) {
102-
capacityBytes_ = byteBuf.capacity();
103-
byteBuf_ = byteBuf;
104-
if (byteBuf_.isDirect()) {
105-
memArray_ = null;
106+
if (byteBuf.isDirect()) {
106107
objectBaseOffset_ = 0L;
108+
memArray_ = null;
109+
byteBuf_ = byteBuf;
107110
nativeRawStartAddress_ = ((sun.nio.ch.DirectBuffer)byteBuf).address();
108111
}
109112
else { //must have array
110-
memArray_ = byteBuf_.array();
111113
objectBaseOffset_ = BYTE_ARRAY_BASE_OFFSET;
114+
memArray_ = byteBuf.array();
115+
byteBuf_ = byteBuf;
112116
nativeRawStartAddress_ = 0L;
113117
}
118+
capacityBytes_ = byteBuf.capacity();
119+
114120
}
115121

116122
@Override
@@ -557,13 +563,22 @@ public Object getParent() {
557563
return memArray_;
558564
}
559565

566+
@Override
567+
public void setMemoryRequest(MemoryRequest memReq) {
568+
memReq_ = memReq;
569+
}
570+
560571
@Override
561572
public String toHexString(String header, long offsetBytes, int lengthBytes) {
562573
StringBuilder sb = new StringBuilder();
563574
sb.append(header).append("\n");
564-
String s1 = String.format("(%d, %d)", offsetBytes, lengthBytes);
565-
sb.append(this.getClass().getName());
566-
sb.append(".toHexString").append(s1).append(", hash: ").append(this.hashCode()).append(":");
575+
String s1 = String.format("(..., %d, %d)", offsetBytes, lengthBytes);
576+
sb.append(this.getClass().getSimpleName()).append(".toHexString").
577+
append(s1).append(", hash: ").append(this.hashCode()).append("\n");
578+
sb.append(" MemoryRequest: ");
579+
if (memReq_ != null) {
580+
sb.append(memReq_.getClass().getSimpleName()).append(", hash: ").append(memReq_.hashCode());
581+
} else sb.append("null");
567582
return toHex(sb.toString(), offsetBytes, lengthBytes);
568583
}
569584

@@ -586,15 +601,28 @@ public ByteBuffer byteBuffer() {
586601
}
587602

588603
/**
589-
* Frees this Memory. If direct, off-heap native memory is allocated via the AllocMemory
590-
* sub-class this method must be called in either the NativeMemory class or the AllocMemory class.
604+
* Returns true if this NativeMemory is accessing native (off-heap) memory directly.
605+
* This includes the case of a Direct ByteBuffer.
606+
* @return true if this NativeMemory is accessing native (off-heap) memory directly.
607+
*/
608+
public boolean isDirect() {
609+
return nativeRawStartAddress_ > 0;
610+
}
611+
612+
/**
613+
* This frees this Memory only if it is required. This always sets the capacity to zero
614+
* and the reference to MemoryRequest to null, which effectively disables this class.
615+
* However,
616+
*
617+
* It is always safe to call this method when you are done with this class.
591618
*/
592619
public void freeMemory() {
593620
if (requiresFree()) {
594621
unsafe.freeMemory(nativeRawStartAddress_);
595622
nativeRawStartAddress_ = 0L;
596623
}
597624
capacityBytes_ = 0L;
625+
memReq_ = null;
598626
}
599627

600628
/**
@@ -664,7 +692,7 @@ private String toHex(String header, long offsetBytes, int lengthBytes) {
664692
* @return true if the object should be freed when it is no longer needed
665693
*/
666694
protected boolean requiresFree() {
667-
return nativeRawStartAddress_ != 0L && (byteBuf_ == null);
695+
return (nativeRawStartAddress_ != 0L) && (byteBuf_ == null);
668696
}
669697

670698
}

0 commit comments

Comments
 (0)