You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by al...@apache.org on 2019/08/14 18:41:13 UTC

[incubator-datasketches-java] 01/01: fixed direct union memory layout problem

This is an automated email from the ASF dual-hosted git repository.

alsay pushed a commit to branch array_of_doubles_union_fix
in repository https://gitbox.apache.org/repos/asf/incubator-datasketches-java.git

commit 80cfa51546ac6f4f384b10483017e71851cc3884
Author: AlexanderSaydakov <Al...@users.noreply.github.com>
AuthorDate: Wed Aug 14 11:40:57 2019 -0700

    fixed direct union memory layout problem
---
 .../tuple/ArrayOfDoublesSetOperationBuilder.java   |  4 +-
 .../yahoo/sketches/tuple/ArrayOfDoublesUnion.java  | 86 +++++--------------
 .../sketches/tuple/DirectArrayOfDoublesUnion.java  | 37 +++++++--
 .../sketches/tuple/HeapArrayOfDoublesUnion.java    | 22 +----
 .../sketches/tuple/SerializerDeserializer.java     | 31 -------
 .../sketches/tuple/ArrayOfDoublesUnionTest.java    | 96 +++++++++++++++++-----
 .../yahoo/sketches/tuple/ReadOnlyMemoryTest.java   | 17 ----
 7 files changed, 133 insertions(+), 160 deletions(-)

diff --git a/src/main/java/com/yahoo/sketches/tuple/ArrayOfDoublesSetOperationBuilder.java b/src/main/java/com/yahoo/sketches/tuple/ArrayOfDoublesSetOperationBuilder.java
index c590977..fc1a658 100644
--- a/src/main/java/com/yahoo/sketches/tuple/ArrayOfDoublesSetOperationBuilder.java
+++ b/src/main/java/com/yahoo/sketches/tuple/ArrayOfDoublesSetOperationBuilder.java
@@ -32,8 +32,8 @@ public class ArrayOfDoublesSetOperationBuilder {
   private int numValues_;
   private long seed_;
 
-  private static final int DEFAULT_NOMINAL_ENTRIES = 4096;
-  private static final int DEFAULT_NUMBER_OF_VALUES = 1;
+  public static final int DEFAULT_NOMINAL_ENTRIES = 4096;
+  public static final int DEFAULT_NUMBER_OF_VALUES = 1;
 
   /**
    * Creates an instance of the builder with default parameters
diff --git a/src/main/java/com/yahoo/sketches/tuple/ArrayOfDoublesUnion.java b/src/main/java/com/yahoo/sketches/tuple/ArrayOfDoublesUnion.java
index 415685f..929511d 100644
--- a/src/main/java/com/yahoo/sketches/tuple/ArrayOfDoublesUnion.java
+++ b/src/main/java/com/yahoo/sketches/tuple/ArrayOfDoublesUnion.java
@@ -51,18 +51,10 @@ public abstract class ArrayOfDoublesUnion {
   static final int SEED_HASH_SHORT = 6;
   static final int THETA_LONG = 8;
 
-  final int nomEntries_;
-  final int numValues_;
-  final long seed_;
-  final short seedHash_;
   ArrayOfDoublesQuickSelectSketch sketch_;
   long theta_;
 
   ArrayOfDoublesUnion(final ArrayOfDoublesQuickSelectSketch sketch) {
-    nomEntries_ = sketch.getNominalEntries();
-    numValues_ = sketch.getNumValues();
-    seed_ = sketch.getSeed();
-    seedHash_ = Util.computeSeedHash(seed_);
     sketch_ = sketch;
     theta_ = sketch.getThetaLong();
   }
@@ -102,7 +94,7 @@ public abstract class ArrayOfDoublesUnion {
    * @return an ArrayOfDoublesUnion
    */
   public static ArrayOfDoublesUnion wrap(final Memory mem, final long seed) {
-    return wrapUnionImpl((WritableMemory) mem, seed, false);
+    return DirectArrayOfDoublesUnion.wrapUnion((WritableMemory) mem, seed, false);
   }
 
   /**
@@ -121,7 +113,7 @@ public abstract class ArrayOfDoublesUnion {
    * @return an ArrayOfDoublesUnion
    */
   public static ArrayOfDoublesUnion wrap(final WritableMemory mem, final long seed) {
-    return wrapUnionImpl(mem, seed, true);
+    return DirectArrayOfDoublesUnion.wrapUnion(mem, seed, true);
   }
 
   /**
@@ -130,16 +122,24 @@ public abstract class ArrayOfDoublesUnion {
    */
   public void update(final ArrayOfDoublesSketch sketchIn) {
     if (sketchIn == null) { return; }
-    Util.checkSeedHashes(seedHash_, sketchIn.getSeedHash());
+    Util.checkSeedHashes(sketch_.getSeedHash(), sketchIn.getSeedHash());
     if (sketch_.getNumValues() != sketchIn.getNumValues()) {
       throw new SketchesArgumentException("Incompatible sketches: number of values mismatch "
           + sketch_.getNumValues() + " and " + sketchIn.getNumValues());
     }
     if (sketchIn.isEmpty()) { return; }
-    if (sketchIn.getThetaLong() < theta_) { theta_ = sketchIn.getThetaLong(); }
+    if (sketchIn.getThetaLong() < theta_) {
+      setThetaLong(sketchIn.getThetaLong());
+    }
     final ArrayOfDoublesSketchIterator it = sketchIn.iterator();
     while (it.next()) {
-      sketch_.merge(it.getKey(), it.getValues());
+      if (it.getKey() < theta_) {
+        sketch_.merge(it.getKey(), it.getValues());
+      }
+    }
+    // keep the union theta as low as low as possible for performance
+    if (sketch_.getThetaLong() < theta_) {
+      setThetaLong(sketch_.getThetaLong());
     }
   }
 
@@ -149,13 +149,14 @@ public abstract class ArrayOfDoublesUnion {
    * @return compact sketch representing the union (off-heap if memory is provided)
    */
   public ArrayOfDoublesCompactSketch getResult(final WritableMemory dstMem) {
+    long theta = theta_;
     if (sketch_.getRetainedEntries() > sketch_.getNominalEntries()) {
-      theta_ = Math.min(theta_, sketch_.getNewTheta());
+      theta = Math.min(theta, sketch_.getNewTheta());
     }
     if (dstMem == null) {
-      return new HeapArrayOfDoublesCompactSketch(sketch_, theta_);
+      return new HeapArrayOfDoublesCompactSketch(sketch_, theta);
     }
-    return new DirectArrayOfDoublesCompactSketch(sketch_, theta_, dstMem);
+    return new DirectArrayOfDoublesCompactSketch(sketch_, theta, dstMem);
   }
 
   /**
@@ -169,7 +170,10 @@ public abstract class ArrayOfDoublesUnion {
   /**
    * Resets the union to an empty state
    */
-  public abstract void reset();
+  public void reset() {
+    sketch_.reset();
+    setThetaLong(sketch_.getThetaLong());
+  }
 
   /**
    * @return a byte array representation of this object
@@ -194,57 +198,11 @@ public abstract class ArrayOfDoublesUnion {
    * @return maximum required storage bytes given nomEntries and numValues
    */
   public static int getMaxBytes(final int nomEntries, final int numValues) {
-    return ArrayOfDoublesQuickSelectSketch.getMaxBytes(nomEntries, numValues);
+    return ArrayOfDoublesQuickSelectSketch.getMaxBytes(nomEntries, numValues) + PREAMBLE_SIZE_BYTES;
   }
 
   void setThetaLong(final long theta) {
     theta_ = theta;
   }
 
-  static ArrayOfDoublesUnion wrapUnionImpl(final WritableMemory mem, final long seed,
-      final boolean isWritable) {
-    final SerializerDeserializer.SketchType type = SerializerDeserializer.getSketchType(mem);
-    final ArrayOfDoublesQuickSelectSketch sketch;
-    final ArrayOfDoublesUnion union;
-
-    // compatibility with version 0.9.1 and lower
-    if (type == SerializerDeserializer.SketchType.ArrayOfDoublesQuickSelectSketch) {
-      if (isWritable) {
-        sketch = new DirectArrayOfDoublesQuickSelectSketch(mem, seed);
-        union = new DirectArrayOfDoublesUnion(sketch, mem);
-      } else {
-        sketch = new DirectArrayOfDoublesQuickSelectSketchR(mem, seed);
-        union = new DirectArrayOfDoublesUnionR(sketch, mem);
-      }
-      return union; //Do not need to set theta_
-    }
-    //versions > 0.9.1
-
-    //sanity checks
-    final byte version = mem.getByte(ArrayOfDoublesUnion.SERIAL_VERSION_BYTE);
-    if (version != ArrayOfDoublesUnion.serialVersionUID) {
-      throw new SketchesArgumentException("Serial version mismatch. Expected: "
-        + ArrayOfDoublesUnion.serialVersionUID + ", actual: " + version);
-    }
-    SerializerDeserializer.validateFamily(mem.getByte(ArrayOfDoublesUnion.FAMILY_ID_BYTE),
-        mem.getByte(ArrayOfDoublesUnion.PREAMBLE_LONGS_BYTE));
-    SerializerDeserializer.validateType(mem.getByte(ArrayOfDoublesUnion.SKETCH_TYPE_BYTE),
-        SerializerDeserializer.SketchType.ArrayOfDoublesUnion);
-
-    if (isWritable) {
-      final WritableMemory sketchMem = mem.writableRegion(ArrayOfDoublesUnion.PREAMBLE_SIZE_BYTES,
-          mem.getCapacity() - ArrayOfDoublesUnion.PREAMBLE_SIZE_BYTES);
-      sketch = new DirectArrayOfDoublesQuickSelectSketch(sketchMem, seed);
-      union = new DirectArrayOfDoublesUnion(sketch, mem);
-
-    } else {
-      final Memory sketchMem = mem.region(ArrayOfDoublesUnion.PREAMBLE_SIZE_BYTES,
-          mem.getCapacity() - ArrayOfDoublesUnion.PREAMBLE_SIZE_BYTES);
-      sketch = new DirectArrayOfDoublesQuickSelectSketchR(sketchMem, seed);
-      union = new DirectArrayOfDoublesUnionR(sketch, mem);
-    }
-    union.theta_ = mem.getLong(ArrayOfDoublesUnion.THETA_LONG);
-    return union;
-  }
-
 }
diff --git a/src/main/java/com/yahoo/sketches/tuple/DirectArrayOfDoublesUnion.java b/src/main/java/com/yahoo/sketches/tuple/DirectArrayOfDoublesUnion.java
index 82e13b9..0b52954 100644
--- a/src/main/java/com/yahoo/sketches/tuple/DirectArrayOfDoublesUnion.java
+++ b/src/main/java/com/yahoo/sketches/tuple/DirectArrayOfDoublesUnion.java
@@ -19,7 +19,10 @@
 
 package com.yahoo.sketches.tuple;
 
+import com.yahoo.memory.Memory;
 import com.yahoo.memory.WritableMemory;
+import com.yahoo.sketches.Family;
+import com.yahoo.sketches.SketchesArgumentException;
 
 /**
  * Direct Union operation for tuple sketches of type ArrayOfDoubles.
@@ -41,19 +44,20 @@ class DirectArrayOfDoublesUnion extends ArrayOfDoublesUnion {
    */
   DirectArrayOfDoublesUnion(final int nomEntries, final int numValues, final long seed, 
       final WritableMemory dstMem) {
-    super(new DirectArrayOfDoublesQuickSelectSketch(nomEntries, 3, 1f, numValues, seed, dstMem));
+    super(new DirectArrayOfDoublesQuickSelectSketch(nomEntries, 3, 1f, numValues, seed,
+        dstMem.writableRegion(PREAMBLE_SIZE_BYTES, dstMem.getCapacity() - PREAMBLE_SIZE_BYTES)));
     mem_ = dstMem;
+    mem_.putByte(PREAMBLE_LONGS_BYTE, (byte) 1); // unused, always 1
+    mem_.putByte(SERIAL_VERSION_BYTE, serialVersionUID);
+    mem_.putByte(FAMILY_ID_BYTE, (byte) Family.TUPLE.getID());
+    mem_.putByte(SKETCH_TYPE_BYTE, (byte) SerializerDeserializer.SketchType.ArrayOfDoublesUnion.ordinal());
+    mem_.putLong(THETA_LONG, sketch_.getThetaLong());
   }
 
   DirectArrayOfDoublesUnion(final ArrayOfDoublesQuickSelectSketch sketch, final WritableMemory mem) {
     super(sketch);
     mem_ = mem;
-  }
-
-  @Override
-  public void reset() {
-    sketch_ = new DirectArrayOfDoublesQuickSelectSketch(nomEntries_, 3, 1f, numValues_, seed_, mem_);
-    setThetaLong(sketch_.getThetaLong());
+    theta_ = mem.getLong(THETA_LONG);
   }
 
   @Override
@@ -62,4 +66,23 @@ class DirectArrayOfDoublesUnion extends ArrayOfDoublesUnion {
     mem_.putLong(THETA_LONG, theta);
   }
 
+  static ArrayOfDoublesUnion wrapUnion(final WritableMemory mem, final long seed, final boolean isWritable) {
+    final byte version = mem.getByte(ArrayOfDoublesUnion.SERIAL_VERSION_BYTE);
+    if (version != ArrayOfDoublesUnion.serialVersionUID) {
+      throw new SketchesArgumentException("Serial version mismatch. Expected: "
+        + serialVersionUID + ", actual: " + version);
+    }
+    SerializerDeserializer.validateFamily(mem.getByte(FAMILY_ID_BYTE), mem.getByte(PREAMBLE_LONGS_BYTE));
+    SerializerDeserializer.validateType(mem.getByte(SKETCH_TYPE_BYTE),
+        SerializerDeserializer.SketchType.ArrayOfDoublesUnion);
+
+    if (isWritable) {
+      final WritableMemory sketchMem = mem.writableRegion(PREAMBLE_SIZE_BYTES,
+          mem.getCapacity() - PREAMBLE_SIZE_BYTES);
+      return new DirectArrayOfDoublesUnion(new DirectArrayOfDoublesQuickSelectSketch(sketchMem, seed), mem);
+    }
+    final Memory sketchMem = mem.region(PREAMBLE_SIZE_BYTES, mem.getCapacity() - PREAMBLE_SIZE_BYTES);
+    return new DirectArrayOfDoublesUnionR(new DirectArrayOfDoublesQuickSelectSketchR(sketchMem, seed), mem);
+  }
+
 }
diff --git a/src/main/java/com/yahoo/sketches/tuple/HeapArrayOfDoublesUnion.java b/src/main/java/com/yahoo/sketches/tuple/HeapArrayOfDoublesUnion.java
index 7608d43..590eaba 100644
--- a/src/main/java/com/yahoo/sketches/tuple/HeapArrayOfDoublesUnion.java
+++ b/src/main/java/com/yahoo/sketches/tuple/HeapArrayOfDoublesUnion.java
@@ -39,8 +39,9 @@ final class HeapArrayOfDoublesUnion extends ArrayOfDoublesUnion {
     super(new HeapArrayOfDoublesQuickSelectSketch(nomEntries, 3, 1f, numValues, seed));
   }
 
-  HeapArrayOfDoublesUnion(final ArrayOfDoublesQuickSelectSketch sketch) {
+  HeapArrayOfDoublesUnion(final ArrayOfDoublesQuickSelectSketch sketch, final long theta) {
     super(sketch);
+    theta_ = theta;
   }
 
   /**
@@ -50,14 +51,6 @@ final class HeapArrayOfDoublesUnion extends ArrayOfDoublesUnion {
    * @return a ArrayOfDoublesUnion on the Java heap
    */
   static ArrayOfDoublesUnion heapifyUnion(final Memory mem, final long seed) {
-    final SerializerDeserializer.SketchType type = SerializerDeserializer.getSketchType(mem);
-
-    // compatibility with version 0.9.1 and lower
-    if (type == SerializerDeserializer.SketchType.ArrayOfDoublesQuickSelectSketch) {
-      final ArrayOfDoublesQuickSelectSketch sketch = new HeapArrayOfDoublesQuickSelectSketch(mem, seed);
-      return new HeapArrayOfDoublesUnion(sketch);
-    }
-
     final byte version = mem.getByte(SERIAL_VERSION_BYTE);
     if (version != serialVersionUID) {
       throw new SketchesArgumentException("Serial version mismatch. Expected: "
@@ -67,18 +60,9 @@ final class HeapArrayOfDoublesUnion extends ArrayOfDoublesUnion {
     SerializerDeserializer.validateType(mem.getByte(SKETCH_TYPE_BYTE),
         SerializerDeserializer.SketchType.ArrayOfDoublesUnion);
 
-    final long unionTheta = mem.getLong(THETA_LONG);
     final Memory sketchMem = mem.region(PREAMBLE_SIZE_BYTES, mem.getCapacity() - PREAMBLE_SIZE_BYTES);
     final ArrayOfDoublesQuickSelectSketch sketch = new HeapArrayOfDoublesQuickSelectSketch(sketchMem, seed);
-    final ArrayOfDoublesUnion union = new HeapArrayOfDoublesUnion(sketch);
-    union.theta_ = unionTheta;
-    return union;
-  }
-
-  @Override
-  public void reset() {
-    sketch_ = new HeapArrayOfDoublesQuickSelectSketch(nomEntries_, 3, 1f, numValues_, seed_);
-    theta_ = sketch_.getThetaLong();
+    return new HeapArrayOfDoublesUnion(sketch, mem.getLong(THETA_LONG));
   }
 
 }
diff --git a/src/main/java/com/yahoo/sketches/tuple/SerializerDeserializer.java b/src/main/java/com/yahoo/sketches/tuple/SerializerDeserializer.java
index de59ecb..facb08e 100644
--- a/src/main/java/com/yahoo/sketches/tuple/SerializerDeserializer.java
+++ b/src/main/java/com/yahoo/sketches/tuple/SerializerDeserializer.java
@@ -62,35 +62,4 @@ final class SerializerDeserializer {
     return SketchType.values()[sketchTypeByte];
   }
 
-  // Deprecated methods below. Retained here to support reading legacy data.
-
-  //  private static final Map<String, Method> deserializeMethodCache = new HashMap<>();
-
-  //  static <T> DeserializeResult<T> deserializeFromMemory(final Memory mem, final int offset) {
-  //    final int classNameLength = mem.getByte(offset);
-  //    final byte[] classNameBuffer = new byte[classNameLength];
-  //    mem.getByteArray(offset + 1, classNameBuffer, 0, classNameLength);
-  //    final String className = new String(classNameBuffer, UTF_8);
-  //    final DeserializeResult<T> result =
-  //        deserializeFromMemory(mem, offset + classNameLength + 1, className);
-  //    return new DeserializeResult<>(result.getObject(), result.getSize() + classNameLength + 1);
-  //  }
-
-  //  @SuppressWarnings("unchecked")
-  //  static <T> DeserializeResult<T>
-  //      deserializeFromMemory(final Memory mem, final int offset, final String className) {
-  //    try {
-  //      Method method = deserializeMethodCache.get(className);
-  //      if (method == null) {
-  //          method = Class.forName(className).getMethod("fromMemory", Memory.class);
-  //          deserializeMethodCache.put(className, method);
-  //      }
-  //      return (DeserializeResult<T>)
-  //          method.invoke(null, mem.region(offset, mem.getCapacity() - offset));
-  //    } catch (final IllegalAccessException | SketchesArgumentException | InvocationTargetException
-  //        | NoSuchMethodException | SecurityException | ClassNotFoundException e) {
-  //      throw new SketchesArgumentException("Failed to deserialize class " + className + " " + e);
-  //    }
-  //  }
-
 }
diff --git a/src/test/java/com/yahoo/sketches/tuple/ArrayOfDoublesUnionTest.java b/src/test/java/com/yahoo/sketches/tuple/ArrayOfDoublesUnionTest.java
index 0a6237d..47cb28d 100644
--- a/src/test/java/com/yahoo/sketches/tuple/ArrayOfDoublesUnionTest.java
+++ b/src/test/java/com/yahoo/sketches/tuple/ArrayOfDoublesUnionTest.java
@@ -48,8 +48,10 @@ public class ArrayOfDoublesUnionTest {
     ArrayOfDoublesUnion union = new ArrayOfDoublesSetOperationBuilder().buildUnion();
     union.update(sketch1);
     union.update(sketch2);
-    int maxBytes = ArrayOfDoublesUnion.getMaxBytes(union.nomEntries_, union.numValues_);
-    Assert.assertEquals(maxBytes, 131104);
+    int maxBytes = ArrayOfDoublesUnion.getMaxBytes(
+        ArrayOfDoublesSetOperationBuilder.DEFAULT_NOMINAL_ENTRIES,
+        ArrayOfDoublesSetOperationBuilder.DEFAULT_NUMBER_OF_VALUES);
+    Assert.assertEquals(maxBytes, 131120); // 48 bytes preamble + 2 * nominal entries * (key size + value size)
     ArrayOfDoublesCompactSketch result = union.getResult();
     Assert.assertEquals(result.getEstimate(), 3.0);
     double[][] values = result.getValues();
@@ -198,25 +200,18 @@ public class ArrayOfDoublesUnionTest {
     }
   }
 
-  @Test
-  public void heapDeserializeV0_9_1() throws Exception {
-    byte[] bytes = TestUtil.readBytesFromFile(getClass().getClassLoader().getResource("ArrayOfDoublesUnion_v0.9.1.bin").getFile());
-    ArrayOfDoublesUnion union2 = ArrayOfDoublesUnion.heapify(Memory.wrap(bytes));
-    ArrayOfDoublesCompactSketch result = union2.getResult();
-    Assert.assertEquals(result.getEstimate(), 12288.0, 12288 * 0.01);
+  @Test(expectedExceptions = SketchesArgumentException.class)
+  public void noSupportHeapifyV0_9_1() throws Exception {
+    final byte[] bytes = TestUtil.readBytesFromFile(
+        getClass().getClassLoader().getResource("ArrayOfDoublesUnion_v0.9.1.bin").getFile());
+    ArrayOfDoublesUnion.heapify(Memory.wrap(bytes));
+  }
 
-    union2.reset();
-    result = union2.getResult();
-    Assert.assertTrue(result.isEmpty());
-    Assert.assertFalse(result.isEstimationMode());
-    Assert.assertEquals(result.getEstimate(), 0.0);
-    Assert.assertEquals(result.getUpperBound(1), 0.0);
-    Assert.assertEquals(result.getLowerBound(1), 0.0);
-    Assert.assertEquals(result.getTheta(), 1.0);
-    double[][] values = result.getValues();
-    for (int i = 0; i < values.length; i++) {
-      Assert.assertEquals(values[i][0], 2.0);
-    }
+  @Test(expectedExceptions = SketchesArgumentException.class)
+  public void noSupportWrapV0_9_1() throws Exception {
+    final byte[] bytes = TestUtil.readBytesFromFile(
+        getClass().getClassLoader().getResource("ArrayOfDoublesUnion_v0.9.1.bin").getFile());
+    ArrayOfDoublesUnion.wrap(WritableMemory.wrap(bytes));
   }
 
   @Test
@@ -457,4 +452,65 @@ public class ArrayOfDoublesUnionTest {
     union.update(sketch);
   }
 
+  @Test
+  public void directDruidUsageOneSketch() {
+    final WritableMemory mem = WritableMemory.wrap(new byte[1000000]);
+    new ArrayOfDoublesSetOperationBuilder().buildUnion(mem); // just set up memory to wrap later
+
+    final int n = 100000; // estimation mode
+    final ArrayOfDoublesUpdatableSketch sketch = new ArrayOfDoublesUpdatableSketchBuilder().build();
+    for (int i = 0; i < n; i++) {
+      sketch.update(i, new double[] {1.0});
+    }
+    sketch.trim(); // pretend this is a result from a union
+
+    // as Druid wraps memory
+    ArrayOfDoublesSketches.wrapUnion(mem).update(sketch.compact(WritableMemory.wrap(new byte[1000000])));
+
+    ArrayOfDoublesSketch result = ArrayOfDoublesUnion.wrap(mem).getResult();
+    Assert.assertEquals(result.getEstimate(), sketch.getEstimate());
+    Assert.assertEquals(result.isEstimationMode(), sketch.isEstimationMode());
+  }
+
+  @Test
+  public void directDruidUsageTwoSketches() {
+    final WritableMemory mem = WritableMemory.wrap(new byte[1000000]);
+    new ArrayOfDoublesSetOperationBuilder().buildUnion(mem); // just set up memory to wrap later
+
+    int key = 0;
+
+    final int n1 = 100000; // estimation mode
+    final ArrayOfDoublesUpdatableSketch sketch1 = new ArrayOfDoublesUpdatableSketchBuilder().build();
+    for (int i = 0; i < n1; i++) {
+      sketch1.update(key++, new double[] {1.0});
+    }
+    // as Druid wraps memory
+    ArrayOfDoublesSketches.wrapUnion(mem).update(sketch1.compact(WritableMemory.wrap(new byte[1000000])));
+
+    final int n2 = 1000000; // estimation mode
+    final ArrayOfDoublesUpdatableSketch sketch2 = new ArrayOfDoublesUpdatableSketchBuilder().build();
+    for (int i = 0; i < n2; i++) {
+      sketch2.update(key++, new double[] {1.0});
+    }
+    // as Druid wraps memory
+    ArrayOfDoublesSketches.wrapUnion(mem).update(sketch2.compact(WritableMemory.wrap(new byte[1000000])));
+
+    // build one sketch that must be the same as union
+    key = 0; // reset to have the same keys
+    final int n = n1 + n2;
+    final ArrayOfDoublesUpdatableSketch expected = new ArrayOfDoublesUpdatableSketchBuilder().build();
+    for (int i = 0; i < n; i++) {
+      expected.update(key++, new double[] {1.0});
+    }
+    expected.trim(); // union result is trimmed, so we need to trim this sketch for valid comparison
+
+    ArrayOfDoublesSketch result = ArrayOfDoublesUnion.wrap(mem).getResult();
+    Assert.assertEquals(result.getEstimate(), expected.getEstimate());
+    Assert.assertEquals(result.isEstimationMode(), expected.isEstimationMode());
+    Assert.assertEquals(result.getUpperBound(1), expected.getUpperBound(1));
+    Assert.assertEquals(result.getLowerBound(1), expected.getLowerBound(1));
+    Assert.assertEquals(result.getRetainedEntries(), expected.getRetainedEntries());
+    Assert.assertEquals(result.getNumValues(), expected.getNumValues());
+  }
+
 }
diff --git a/src/test/java/com/yahoo/sketches/tuple/ReadOnlyMemoryTest.java b/src/test/java/com/yahoo/sketches/tuple/ReadOnlyMemoryTest.java
index 67dc5a8..c15c17b 100644
--- a/src/test/java/com/yahoo/sketches/tuple/ReadOnlyMemoryTest.java
+++ b/src/test/java/com/yahoo/sketches/tuple/ReadOnlyMemoryTest.java
@@ -113,21 +113,4 @@ public class ReadOnlyMemoryTest {
     union2.update(sketch2);
   }
 
-  @Test
-  public void wrapAndTryUpdatingUnionV0_9_1() throws Exception {
-    byte[] bytes = TestUtil.readBytesFromFile(getClass().getClassLoader()
-        .getResource("ArrayOfDoublesUnion_v0.9.1.bin").getFile());
-    ArrayOfDoublesUnion union2 = ArrayOfDoublesUnion.wrap(Memory.wrap(bytes));
-    ArrayOfDoublesCompactSketch result = union2.getResult();
-    Assert.assertEquals(result.getEstimate(), 12288.0, 12288 * 0.01);
-
-    boolean thrown = false;
-    try {
-      union2.reset();
-    } catch (SketchesReadOnlyException e) {
-      thrown = true;
-    }
-    Assert.assertTrue(thrown);
-  }
-
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org