Skip to content

Commit 925067a

Browse files
committed
Add benchmark that compares different coding loops.
1 parent 7958e48 commit 925067a

File tree

4 files changed

+160
-0
lines changed

4 files changed

+160
-0
lines changed

src/main/java/com/backblaze/erasure/CodingLoop.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ public interface CodingLoop {
1414
new IndexShardInputTableCodingLoop()
1515
};
1616

17+
/**
18+
* Returns the human-readable name for this codec.
19+
*/
20+
String getName();
21+
1722
/**
1823
* Multiplies a subset of rows from a coding matrix by a full set of
1924
* input shards to produce some output shards.

src/main/java/com/backblaze/erasure/IndexShardInputExpCodingLoop.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99
public class IndexShardInputExpCodingLoop implements CodingLoop {
1010

11+
@Override
12+
public String getName() {
13+
return "index/shard/input (exp table)";
14+
}
15+
1116
@Override
1217
public void codeSomeShards(
1318
byte[][] matrixRows,

src/main/java/com/backblaze/erasure/IndexShardInputTableCodingLoop.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99
public class IndexShardInputTableCodingLoop implements CodingLoop {
1010

11+
@Override
12+
public String getName() {
13+
return "index/shard/input (mult table)";
14+
}
15+
1116
@Override
1217
public void codeSomeShards(
1318
byte[][] matrixRows,
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/**
2+
* Benchmark of Reed-Solomon encoding.
3+
*
4+
* Copyright 2015, Backblaze, Inc. All rights reserved.
5+
*/
6+
7+
package com.backblaze.erasure;
8+
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
import java.util.Random;
12+
13+
/**
14+
* Benchmark of Reed-Solomon encoding.
15+
*
16+
* Counts the number of bytes of input data that can be processed per
17+
* second.
18+
*
19+
* The set of data the test runs over is twice as big as the L3 cache
20+
* in a Xeon processor, so it should simulate the case where data has
21+
* been read in from a socket.
22+
*/
23+
public class ReedSolomonBenchmark {
24+
25+
private static final int DATA_COUNT = 17;
26+
private static final int PARITY_COUNT = 3;
27+
private static final int TOTAL_COUNT = DATA_COUNT + PARITY_COUNT;
28+
private static final int BUFFER_SIZE = 200 * 1000;
29+
private static final int PROCESSOR_CACHE_SIZE = 10 * 1024 * 1024;
30+
private static final int TWICE_PROCESSOR_CACHE_SIZE = 2 * PROCESSOR_CACHE_SIZE;
31+
private static final int NUMBER_OF_BUFFER_SETS = TWICE_PROCESSOR_CACHE_SIZE / DATA_COUNT / BUFFER_SIZE + 1;
32+
33+
private static final long MEASUREMENT_DURATION = 2 * 1000;
34+
35+
private static final Random random = new Random();
36+
37+
private int nextBuffer = 0;
38+
39+
public static void main(String [] args) {
40+
(new ReedSolomonBenchmark()).run();
41+
}
42+
43+
public void run() {
44+
45+
System.out.println("preparing...");
46+
final BufferSet [] bufferSets = new BufferSet [NUMBER_OF_BUFFER_SETS];
47+
for (int iBufferSet = 0; iBufferSet < NUMBER_OF_BUFFER_SETS; iBufferSet++) {
48+
bufferSets[iBufferSet] = new BufferSet();
49+
}
50+
51+
List<String> summaryLines = new ArrayList<String>();
52+
for (CodingLoop codingLoop : CodingLoop.ALL_CODING_LOOPS) {
53+
System.out.println("\nTEST: " + codingLoop.getName());
54+
ReedSolomon codec = new ReedSolomon(DATA_COUNT, PARITY_COUNT, codingLoop);
55+
System.out.println(" warm up...");
56+
doOneMeasurement(codec, bufferSets);
57+
doOneMeasurement(codec, bufferSets);
58+
System.out.println(" testing...");
59+
Measurement total = new Measurement();
60+
for (int iMeasurement = 0; iMeasurement < 10; iMeasurement++) {
61+
total.add(doOneMeasurement(codec, bufferSets));
62+
}
63+
System.out.println(String.format("\nAVERAGE: %s", total));
64+
summaryLines.add(String.format(" %35s %s", codingLoop.getName(), total));
65+
}
66+
67+
System.out.println("\nSummary:\n");
68+
for (String line : summaryLines) {
69+
System.out.println(line);
70+
}
71+
}
72+
73+
private Measurement doOneMeasurement(ReedSolomon codec, BufferSet [] bufferSets) {
74+
long bytesEncoded = 0;
75+
long passesCompleted = 0;
76+
long encodingTime = 0;
77+
while (encodingTime < MEASUREMENT_DURATION) {
78+
BufferSet bufferSet = bufferSets[nextBuffer];
79+
nextBuffer = (nextBuffer + 1) % bufferSets.length;
80+
byte[][] shards = bufferSet.buffers;
81+
long startTime = System.currentTimeMillis();
82+
codec.encodeParity(shards, 0, BUFFER_SIZE);
83+
long endTime = System.currentTimeMillis();
84+
encodingTime += (endTime - startTime);
85+
bytesEncoded += BUFFER_SIZE * DATA_COUNT;
86+
passesCompleted += 1;
87+
}
88+
double seconds = ((double)encodingTime) / 1000.0;
89+
double megabytes = ((double)bytesEncoded) / 1000000.0;
90+
Measurement result = new Measurement(megabytes, seconds);
91+
System.out.println(String.format(" %s passes, %s", passesCompleted, result));
92+
return result;
93+
}
94+
95+
private static class BufferSet {
96+
97+
public byte [] [] buffers;
98+
99+
public byte [] bigBuffer;
100+
101+
public BufferSet() {
102+
buffers = new byte [TOTAL_COUNT] [BUFFER_SIZE];
103+
for (int iBuffer = 0; iBuffer < TOTAL_COUNT; iBuffer++) {
104+
byte [] buffer = buffers[iBuffer];
105+
for (int iByte = 0; iByte < BUFFER_SIZE; iByte++) {
106+
buffer[iByte] = (byte) random.nextInt(256);
107+
}
108+
}
109+
110+
bigBuffer = new byte [TOTAL_COUNT * BUFFER_SIZE];
111+
for (int i = 0; i < TOTAL_COUNT * BUFFER_SIZE; i++) {
112+
bigBuffer[i] = (byte) random.nextInt(256);
113+
}
114+
}
115+
}
116+
117+
private static class Measurement {
118+
private double megabytes;
119+
private double seconds;
120+
121+
public Measurement() {
122+
this.megabytes = 0.0;
123+
this.seconds = 0.0;
124+
}
125+
126+
public Measurement(double megabytes, double seconds) {
127+
this.megabytes = megabytes;
128+
this.seconds = seconds;
129+
}
130+
131+
public void add(Measurement other) {
132+
megabytes += other.megabytes;
133+
seconds += other.seconds;
134+
}
135+
136+
public double getRate() {
137+
return megabytes / seconds;
138+
}
139+
140+
@Override
141+
public String toString() {
142+
return String.format("%5.1f MB/s", getRate());
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)