tmf: buf 495911 Fix timestamp transform fast for small timestamps
authorGeneviève Bastien <gbastien+lttng@versatic.net>
Mon, 13 Jun 2016 19:13:10 +0000 (15:13 -0400)
committerGenevieve Bastien <gbastien+lttng@versatic.net>
Wed, 15 Jun 2016 13:14:59 +0000 (09:14 -0400)
Change-Id: I64f3fc6c113fd240506a6d972430bda94ed05afb
Signed-off-by: Geneviève Bastien <gbastien+lttng@versatic.net>
Reviewed-on: https://git.eclipse.org/r/75187
Reviewed-by: Hudson CI
Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
tmf/org.eclipse.tracecompass.tmf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/synchronization/TsTransformFastTest.java
tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/synchronization/TmfTimestampTransformLinearFast.java

index 8e894e2ac53b507a17dbce25db3178b504fc3382..42853d95086fc302a4c27dac7a1debb4648a783d 100644 (file)
@@ -16,28 +16,104 @@ package org.eclipse.tracecompass.tmf.core.tests.synchronization;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
 
 import org.eclipse.tracecompass.internal.tmf.core.synchronization.TmfTimestampTransformLinear;
 import org.eclipse.tracecompass.internal.tmf.core.synchronization.TmfTimestampTransformLinearFast;
 import org.eclipse.tracecompass.tmf.core.synchronization.ITmfTimestampTransform;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
 /**
  * Tests for {@link TmfTimestampTransformLinearFast}
  *
  * @author Geneviève Bastien
  */
+@RunWith(Parameterized.class)
 public class TsTransformFastTest {
 
     private static final long ts = 1361657893526374091L;
 
+    private static interface IFastTransformFactory {
+        public TmfTimestampTransformLinearFast create(double alpha, double beta);
+    }
+
+    private static final IFastTransformFactory fNewObject = (a, b) -> {
+        return new TmfTimestampTransformLinearFast(a, b);
+    };
+
+    private static final IFastTransformFactory fDeserialized = (a, b) -> {
+        TmfTimestampTransformLinearFast tt = new TmfTimestampTransformLinearFast(a, b);
+        /* Serialize the object */
+        String filePath = null;
+        try {
+            File temp = File.createTempFile("serialSyncAlgo", ".tmp");
+            filePath = temp.getAbsolutePath();
+        } catch (IOException e) {
+            fail("Could not create temporary file for serialization");
+        }
+        assertNotNull(filePath);
+
+        try (FileOutputStream fileOut = new FileOutputStream(filePath);
+                ObjectOutputStream out = new ObjectOutputStream(fileOut);) {
+            out.writeObject(tt);
+        } catch (IOException e) {
+            fail("Error serializing the synchronization algorithm " + e.getMessage());
+        }
+
+        TmfTimestampTransformLinearFast deserialTt = null;
+        /* De-Serialize the object */
+        try (FileInputStream fileIn = new FileInputStream(filePath);
+                ObjectInputStream in = new ObjectInputStream(fileIn);) {
+            deserialTt = (TmfTimestampTransformLinearFast) in.readObject();
+        } catch (IOException | ClassNotFoundException e) {
+            fail("Error de-serializing the synchronization algorithm " + e.getMessage());
+        }
+        return deserialTt;
+    };
+
+    private final IFastTransformFactory fTransformFactory;
+
+    /**
+     * Constructor
+     *
+     * @param name
+     *            The name of this parameterized test
+     * @param factory
+     *            Factory to create the timestamp transform
+     */
+    public TsTransformFastTest(String name, IFastTransformFactory factory) {
+        fTransformFactory = factory;
+    }
+
+    /**
+     * @return the test parameters
+     */
+    @Parameters(name = "Factory={0}")
+    public static Iterable<Object[]> parameters() {
+        return Arrays.asList(new Object[][] {
+                { "Object", fNewObject },
+                { "Deserialized", fDeserialized }
+        });
+    }
+
     /**
      * Test whether the fast linear transform always yields the same value for
      * the same timestamp
      */
     @Test
     public void testFLTRepeatability() {
-        TmfTimestampTransformLinearFast fast = new TmfTimestampTransformLinearFast(Math.PI, 0);
+        TmfTimestampTransformLinearFast fast = fTransformFactory.create(Math.PI, 0);
         // Access fDeltaMax to compute the cache range boundaries
         long deltaMax = fast.getDeltaMax();
         // Initialize the transform
@@ -68,8 +144,8 @@ public class TsTransformFastTest {
      */
     @Test
     public void testFLTEquivalence() {
-        TmfTimestampTransformLinearFast fast = new TmfTimestampTransformLinearFast(Math.PI, 0);
-        TmfTimestampTransformLinearFast fast2 = new TmfTimestampTransformLinearFast(Math.PI, 0);
+        TmfTimestampTransformLinearFast fast = fTransformFactory.create(Math.PI, 0);
+        TmfTimestampTransformLinearFast fast2 = fTransformFactory.create(Math.PI, 0);
 
         long deltaMax = fast.getDeltaMax();
 
@@ -84,7 +160,7 @@ public class TsTransformFastTest {
     @Test
     public void testFastTransformPrecision() {
         TmfTimestampTransformLinear precise = new TmfTimestampTransformLinear(Math.PI, 0);
-        TmfTimestampTransformLinearFast fast = new TmfTimestampTransformLinearFast(Math.PI, 0);
+        TmfTimestampTransformLinearFast fast = fTransformFactory.create(Math.PI, 0);
         int samples = 100;
         long start = (long) Math.pow(10, 18);
         long end = Long.MAX_VALUE;
@@ -106,11 +182,11 @@ public class TsTransformFastTest {
                         samples, fast.getCacheMisses()), samples >= fast.getCacheMisses());
             }
         }
-
     }
 
     /**
-     * Test that fast transform produces the same result for small and large slopes.
+     * Test that fast transform produces the same result for small and large
+     * slopes.
      */
     @Test
     public void testFastTransformSlope() {
@@ -120,22 +196,38 @@ public class TsTransformFastTest {
             for (int d = 0; d < dir.length; d++) {
                 double slope = Math.pow(10.0, ex);
                 TmfTimestampTransformLinear precise = new TmfTimestampTransformLinear(slope, 0);
-                TmfTimestampTransformLinearFast fast = new TmfTimestampTransformLinearFast(slope, 0);
+                TmfTimestampTransformLinearFast fast = fTransformFactory.create(slope, 0);
                 checkTime(precise, fast, 1000, start, dir[d]);
             }
         }
     }
 
+    /**
+     * Test that fast transform produces the same result with a slope and
+     * offset, for small and large values
+     */
+    @Test
+    public void testFastTransformSlopeAndOffset() {
+        double offset = 54321.0;
+        double slope = Math.pow(10.0, 4);
+        for (int ex = 0; ex <= Long.SIZE - 1; ex++) {
+            long start = 1 << ex;
+            TmfTimestampTransformLinear precise = new TmfTimestampTransformLinear(slope, offset);
+            TmfTimestampTransformLinearFast fast = fTransformFactory.create(slope, offset);
+            checkTime(precise, fast, 5, start, 1);
+        }
+    }
+
     /**
      * Check that the proper exception are raised for illegal slopes
      */
     @Test
     public void testFastTransformArguments() {
-        double[] slopes = new double[] { -1.0, ((double)Integer.MAX_VALUE) + 1, 1e-10 };
-        for (double slope: slopes) {
+        double[] slopes = new double[] { -1.0, ((double) Integer.MAX_VALUE) + 1, 1e-10 };
+        for (double slope : slopes) {
             Exception exception = null;
             try {
-                new TmfTimestampTransformLinearFast(slope, 0.0);
+                fTransformFactory.create(slope, 0.0);
             } catch (IllegalArgumentException e) {
                 exception = e;
             }
@@ -152,7 +244,7 @@ public class TsTransformFastTest {
             long act = fast.transform(time);
             long err = act - exp;
             // allow only two ns of error
-            assertTrue("[" + err + "]", Math.abs(err) < 3);
+            assertTrue("start: " + start + " [" + err + "]", Math.abs(err) < 3);
             if (i > 0) {
                 if (step > 0) {
                     assertTrue("monotonic error" + act + " " + prev, act >= prev);
index 30531a60f6e921b6988d91bad7a688a821755d6b..3e9c0f89d2d8152faa0dc79dafc6127f12773a4a 100644 (file)
@@ -13,6 +13,8 @@
 
 package org.eclipse.tracecompass.internal.tmf.core.synchronization;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.math.BigDecimal;
 import java.math.MathContext;
 
@@ -73,8 +75,7 @@ public class TmfTimestampTransformLinearFast implements ITmfTimestampTransformIn
     private final int fDeltaBits;
     private final int fHashCode;
 
-    private long fOffset;
-
+    private transient long fOffset;
     private transient long fRangeStart;
     private transient long fScaleMiss;
     private transient long fScaleHit;
@@ -151,8 +152,7 @@ public class TmfTimestampTransformLinearFast implements ITmfTimestampTransformIn
         fDeltaBits = Math.max(Math.min(width, DECIMAL_BITS), 0);
         fDeltaMax = 1 << fDeltaBits;
         fAlphaLong = fAlpha.multiply(BigDecimal.valueOf(fDeltaMax), MC).longValue();
-        fRangeStart = 0L;
-        fOffset = 0L;
+        rescale(0);
         fScaleMiss = 0;
         fScaleHit = 0;
         fHashCode = HASHER.newHasher()
@@ -185,8 +185,7 @@ public class TmfTimestampTransformLinearFast implements ITmfTimestampTransformIn
              *
              * TODO: use exact math arithmetic to detect overflow when switching to Java 8
              */
-            fRangeStart = timestamp - (timestamp % fDeltaMax);
-            fOffset = BigDecimal.valueOf(fRangeStart).multiply(fAlpha, MC).add(fBeta, MC).longValue();
+            rescale(timestamp);
             delta = Math.abs(timestamp - fRangeStart);
             fScaleMiss++;
         } else {
@@ -195,6 +194,11 @@ public class TmfTimestampTransformLinearFast implements ITmfTimestampTransformIn
         return ((fAlphaLong * delta) >> fDeltaBits) + fOffset;
     }
 
+    private void rescale(long timestamp) {
+        fRangeStart = timestamp - (timestamp % fDeltaMax);
+        fOffset = BigDecimal.valueOf(fRangeStart).multiply(fAlpha, MC).add(fBeta, MC).longValue();
+    }
+
     //-------------------------------------------------------------------------
     // Transform composition
     //-------------------------------------------------------------------------
@@ -308,4 +312,12 @@ public class TmfTimestampTransformLinearFast implements ITmfTimestampTransformIn
         return fHashCode;
     }
 
+    // Deserialization method, make sure there is a first scaling
+    private void readObject(ObjectInputStream stream)
+            throws IOException, ClassNotFoundException {
+        stream.defaultReadObject();
+
+        rescale(0);
+    }
+
 }
\ No newline at end of file
This page took 0.028226 seconds and 5 git commands to generate.