Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: rework checksum benchmark #1241

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,46 +21,96 @@

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Test for {@link ChecksumEnforcingInputStream}. */
@RunWith(JUnit4.class)
public class ChecksumEnforcingInputStreamTest {
public void test(int payloadSize) throws Exception {
// read 1000 bytes at a time
// Since checksum should be correct, do not expect IOException
try (ChecksumEnforcingInputStream testInstance = setUpData(payloadSize)) {
byte[] buf = new byte[1000];
while (testInstance.read(buf, 0, 1000) != -1) {
public long[] test(int payloadSize) throws Exception {
int chunkSize = 10240;
byte[] payload = preparePayload(payloadSize);
long start = System.nanoTime();
String expectedChecksum = EndToEndChecksumHandler.computeChecksum(payload);
long computeTime = System.nanoTime() - start;
long checksumTime = 0, noChecksumTime = 0;
try (ChecksumEnforcingInputStream testInstance = createStream(expectedChecksum, payload)) {
byte[] buf = new byte[chunkSize];
start = System.nanoTime();
while (testInstance.read(buf, 0, chunkSize) != -1) {
// do nothing with the bytes read
}
checksumTime = System.nanoTime() - start;
} catch (IOException e) {
fail("checksum verification failed! " + e.getMessage());
}

try (ByteArrayInputStream testInstance = new ByteArrayInputStream(payload)) {
byte[] buf = new byte[chunkSize];
start = System.nanoTime();
while (testInstance.read(buf, 0, chunkSize) != -1) {
// do nothing with the bytes read
}
noChecksumTime = System.nanoTime() - start;
} catch (IOException e) {
fail("checksum verification failed! " + e.getMessage());
}

return new long[] {noChecksumTime, checksumTime, computeTime};
}

@Test
public void read_withValidChecksum_differentPayloadSizes() throws Exception {
// test with various payload sizes (1, 2, 2**2, 2**3 etc upto 2**28 = 256MB)
for (int i = 0, payloadSize = 1; i < 29; i++) {
long start = System.currentTimeMillis();
test(payloadSize);
payloadSize *= 2;
long duration = System.currentTimeMillis() - start;
// log test duration times for bigger payloads
if (i > 20) {
System.out.println("Test duration for payloadsize = 2** " + i + " is: " + duration + "ms");
int iterations = 3;
int median = iterations / 2;
int minPower = 15;
int maxPower = 29;
long[][] readNoChecksum = new long[maxPower][];
long[][] readAndChecksum = new long[maxPower][];
long[][] compute = new long[maxPower][];

for (int j = minPower - 1; j < maxPower; j++) {
readNoChecksum[j] = new long[iterations];
readAndChecksum[j] = new long[iterations];
compute[j] = new long[iterations];
}

for (int i = 0; i < iterations; i++) {
// test with various payload sizes (1, 2, 2**2, 2**3 etc upto 2**28 = 256MB)
for (int j = minPower - 1; j < maxPower; j++) {
long[] result = test((int) Math.pow(2, j));
readNoChecksum[j][i] = result[0];
readAndChecksum[j][i] = result[1];
compute[j][i] = result[2];
}
}

for (int j = minPower; j < maxPower; j++) {
Arrays.sort(readNoChecksum[j]);
Arrays.sort(readAndChecksum[j]);
Arrays.sort(compute[j]);
System.out.println(
"Payload "
+ (int) Math.pow(2, j) / 1024
+ " KB stream read: "
+ readNoChecksum[j][median] / 1000.0
+ " μs; stream read and calculate checksum: "
+ readAndChecksum[j][median] / 1000.0
+ " μs; stream checksum overhead: "
+ (readAndChecksum[j][median] - readNoChecksum[j][median]) / 1000.0
+ " μs; calculate checksum: "
+ compute[j][median] / 1000.0
+ " μs.");
}
}

@Test
public void read_withInvalidChecksum() {
// build a test instance with invalidchecksum
// read 1000 bytes at a time
// Since checksum should be correct, do not expect IOException
// Build a test instance with an invalid checksum.
// Read 1000 bytes at a time.
// Since checksum is invalid, do expect IOException.
try (ChecksumEnforcingInputStream instance =
new ChecksumEnforcingInputStream(
new ByteArrayInputStream("hello there".getBytes(UTF_8)), "this checksum is invalid")) {
Expand All @@ -72,17 +122,19 @@ public void read_withInvalidChecksum() {
// this is expected
return;
}
fail("should have failed");
fail("should have raised IOException");
}

@Test
public void markNotSupported() throws Exception {
try (ChecksumEnforcingInputStream testInstance = setUpData(1)) {
byte[] payload = preparePayload(1);
String expectedChecksum = EndToEndChecksumHandler.computeChecksum(payload);
try (ChecksumEnforcingInputStream testInstance = createStream(expectedChecksum, payload)) {
assertFalse(testInstance.markSupported());
}
}

private ChecksumEnforcingInputStream setUpData(int payloadSize) throws Exception {
private byte[] preparePayload(int payloadSize) {
// setup a String of size = input param: payloadSize
String str = "This is a repeating string.";
String payload;
Expand All @@ -96,8 +148,11 @@ private ChecksumEnforcingInputStream setUpData(int payloadSize) throws Exception
} else {
payload = str.substring(0, payloadSize);
}
byte[] bytes = payload.getBytes(UTF_8);
String expectedChecksum = EndToEndChecksumHandler.computeChecksum(bytes);
return new ChecksumEnforcingInputStream(new ByteArrayInputStream(bytes), expectedChecksum);
return payload.getBytes(UTF_8);
}

private ChecksumEnforcingInputStream createStream(String checksum, byte[] bytes)
throws Exception {
return new ChecksumEnforcingInputStream(new ByteArrayInputStream(bytes), checksum);
}
}