From: Geneviève Bastien Date: Mon, 13 Jun 2016 19:13:10 +0000 (-0400) Subject: tmf: buf 495911 Fix timestamp transform fast for small timestamps X-Git-Url: http://git.efficios.com/?p=deliverable%2Ftracecompass.git;a=commitdiff_plain;h=c338f3eb0180517ac140fe181f23e1916a21893f tmf: buf 495911 Fix timestamp transform fast for small timestamps Change-Id: I64f3fc6c113fd240506a6d972430bda94ed05afb Signed-off-by: Geneviève Bastien Reviewed-on: https://git.eclipse.org/r/75187 Reviewed-by: Hudson CI Reviewed-by: Marc-Andre Laperle Tested-by: Marc-Andre Laperle --- diff --git a/tmf/org.eclipse.tracecompass.tmf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/synchronization/TsTransformFastTest.java b/tmf/org.eclipse.tracecompass.tmf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/synchronization/TsTransformFastTest.java index 8e894e2ac5..42853d9508 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/synchronization/TsTransformFastTest.java +++ b/tmf/org.eclipse.tracecompass.tmf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/synchronization/TsTransformFastTest.java @@ -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 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); diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/synchronization/TmfTimestampTransformLinearFast.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/synchronization/TmfTimestampTransformLinearFast.java index 30531a60f6..3e9c0f89d2 100644 --- a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/synchronization/TmfTimestampTransformLinearFast.java +++ b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/synchronization/TmfTimestampTransformLinearFast.java @@ -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