Skip to content

Commit 0721f37

Browse files
committed
Optimized appendDouble0() and refined tests
1 parent cef4802 commit 0721f37

File tree

2 files changed

+54
-59
lines changed

2 files changed

+54
-59
lines changed

chronicle/src/main/java/com/higherfrequencytrading/chronicle/impl/AbstractExcerpt.java

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,10 @@ public abstract class AbstractExcerpt implements Excerpt {
5656
private static final byte[] Infinity = "Infinity".getBytes();
5757
private static final byte[] NaN = "NaN".getBytes();
5858
private static final long MAX_VALUE_DIVIDE_5 = Long.MAX_VALUE / 5;
59-
private static final int MAX_NUMBER_LENGTH = 128;
59+
private static final int MAX_NUMBER_LENGTH = 512;
6060
private static final int NUMBER_BUFFER_LAST_IDX = MAX_NUMBER_LENGTH - 1;
6161

6262
private final byte[] numberBuffer = new byte[MAX_NUMBER_LENGTH];
63-
private int numberBufferIdx = 0;
6463
private ExcerptInputStream inputStream = null;
6564
private ExcerptOutputStream outputStream = null;
6665

@@ -1422,21 +1421,19 @@ else if (b == '-')
14221421

14231422
private void appendLong0(long num) {
14241423
// Extract digits into the end of the numberBuffer
1424+
int numberBufferIdx = 0;
14251425
do {
14261426
numberBuffer[NUMBER_BUFFER_LAST_IDX - numberBufferIdx++] = (byte) (num % 10L + '0');
14271427
num /= 10L;
14281428
} while (num > 0L);
14291429

1430-
// numberBufferIdx was advanced one too many in last run through loop
1431-
final int numberLength = numberBufferIdx--;
1432-
14331430
// Bulk copy the digits into the front of the buffer
14341431
// TODO: Can this be avoided with use of correctly offset bulk appends on Excerpt?
1435-
System.arraycopy(numberBuffer, NUMBER_BUFFER_LAST_IDX - numberBufferIdx,
1436-
numberBuffer, 0, numberLength);
1432+
// Uses (numberBufferIdx - 1) because index was advanced one too many times
1433+
System.arraycopy(numberBuffer, NUMBER_BUFFER_LAST_IDX - (numberBufferIdx - 1),
1434+
numberBuffer, 0, numberBufferIdx);
14371435

1438-
write(numberBuffer, 0, numberLength);
1439-
numberBufferIdx = 0;
1436+
write(numberBuffer, 0, numberBufferIdx);
14401437
}
14411438

14421439
@Override
@@ -1464,18 +1461,23 @@ public ByteStringAppender append(double d, int precision) {
14641461
}
14651462

14661463
private void appendDouble0(long num, int precision) {
1467-
// find the number of digits
1468-
long power10 = Math.max(TENS[precision], power10(num));
1469-
// starting from the end, write each digit
1470-
long decimalPoint = TENS[precision - 1];
1471-
while (power10 > 0) {
1472-
if (decimalPoint == power10)
1473-
writeByte('.');
1474-
// write the lowest digit.
1475-
writeByte((byte) (num / power10 % 10 + '0'));
1476-
// remove that digit.
1477-
power10 /= 10;
1478-
}
1464+
// Extract digits into the end of the numberBuffer
1465+
// Once desired precision is reached, write the '.'
1466+
int numberBufferIdx = 0;
1467+
do {
1468+
numberBuffer[NUMBER_BUFFER_LAST_IDX - numberBufferIdx++] = (byte) (num % 10L + '0');
1469+
num /= 10L;
1470+
if (numberBufferIdx == precision)
1471+
numberBuffer[NUMBER_BUFFER_LAST_IDX - numberBufferIdx++] = (byte) '.';
1472+
} while (num > 0L);
1473+
1474+
// Bulk copy the digits into the front of the buffer
1475+
// TODO: Can this be avoided with use of correctly offset bulk appends on Excerpt?
1476+
// Uses (numberBufferIdx - 1) because index was advanced one too many times
1477+
System.arraycopy(numberBuffer, NUMBER_BUFFER_LAST_IDX - (numberBufferIdx - 1),
1478+
numberBuffer, 0, numberBufferIdx);
1479+
1480+
write(numberBuffer, 0, numberBufferIdx);
14791481
}
14801482

14811483
private static final long[] TENS = new long[19];

chronicle/src/test/java/com/higherfrequencytrading/chronicle/impl/NewVsOldNumberAppendTest.java

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ public class NewVsOldNumberAppendTest {
3232
static final String TMP = System.getProperty("java.io.tmpdir");
3333

3434
private static final int NUM_ENTRIES_PER_RECORD = 20;
35-
private static final int NUM_RECORDS = 400 * 1000;
35+
private static final int NUM_RECORDS = 200 * 1000;
3636
private static final int NUM_WARMUP_RECORDS = 40 * 1000;
3737
private static final int TOTAL_RECORDS = NUM_RECORDS + NUM_WARMUP_RECORDS;
3838
private static final long[][] RANDOM_LONGS = new long[TOTAL_RECORDS][NUM_ENTRIES_PER_RECORD];
3939
private static final double[][] RANDOM_DOUBLES = new double[TOTAL_RECORDS][NUM_ENTRIES_PER_RECORD];
40+
private static final int MAX_PRECISION = 8;
4041

4142
private static final Random random = new Random();
4243

@@ -49,21 +50,15 @@ public void fillRandoms() {
4950
for (int i = 0; i < TOTAL_RECORDS; i++) {
5051
for (int j = 0; j < NUM_ENTRIES_PER_RECORD; j++) {
5152
RANDOM_LONGS[i][j] = random.nextLong();
52-
RANDOM_DOUBLES[i][j] = random.nextDouble();
53+
RANDOM_DOUBLES[i][j] = Math.max(123456.789,
54+
random.nextDouble() % (10 * 1000 * 1000));
5355
}
5456
}
5557
}
5658

57-
@Test
58-
public void testNumberAppends() throws IOException {
59-
System.gc();
60-
timeAppends(Generation.NEW, ExcerptType.BYTE_BUFFER);
61-
System.gc();
62-
timeAppends(Generation.NEW, ExcerptType.UNSAFE);
63-
System.gc();
64-
timeAppends(Generation.OLD, ExcerptType.BYTE_BUFFER);
65-
System.gc();
66-
timeAppends(Generation.OLD, ExcerptType.UNSAFE);
59+
private enum NumberType {
60+
LONG,
61+
DOUBLE
6762
}
6863

6964
private enum Generation {
@@ -94,7 +89,23 @@ private String getStringRep() {
9489
}
9590
}
9691

97-
private void timeAppends(Generation gen, ExcerptType excerptType) throws IOException {
92+
@Test
93+
public void testNumberAppends() throws IOException {
94+
for (NumberType type : NumberType.values()) {
95+
System.gc();
96+
timeAppends(Generation.NEW, ExcerptType.BYTE_BUFFER, type);
97+
System.gc();
98+
timeAppends(Generation.NEW, ExcerptType.UNSAFE, type);
99+
System.gc();
100+
timeAppends(Generation.OLD, ExcerptType.BYTE_BUFFER, type);
101+
System.gc();
102+
timeAppends(Generation.OLD, ExcerptType.UNSAFE, type);
103+
}
104+
}
105+
106+
private void timeAppends(Generation gen,
107+
ExcerptType excerptType,
108+
NumberType numType) throws IOException {
98109
String basePath = TMP + File.separator;
99110

100111
String newPath = basePath + gen.getStringRep() + excerptType.getStringRep() + "Ic";
@@ -121,38 +132,20 @@ private void timeAppends(Generation gen, ExcerptType excerptType) throws IOExcep
121132

122133
excerpt.startExcerpt(2 * 10 * NUM_ENTRIES_PER_RECORD);
123134
for (int j = 0; j < NUM_ENTRIES_PER_RECORD; j++) {
124-
excerpt.append(RANDOM_LONGS[i][j]);
125-
// excerpt.append(RANDOM_DOUBLES[i][j]);
135+
if (numType == NumberType.LONG)
136+
excerpt.append(RANDOM_LONGS[i][j]);
137+
else if (numType == NumberType.DOUBLE)
138+
excerpt.append(RANDOM_DOUBLES[i][j], (j % MAX_PRECISION + 2));
139+
else
140+
throw new AssertionError();
126141
}
127142
excerpt.finish();
128143
}
129144
newIc.close();
130145

131146
long time = System.nanoTime() - start;
132-
System.out.println(gen + " " + excerptType + " time taken " +
147+
System.out.println(numType + " " + gen + " " + excerptType + " time taken " +
133148
(time / 1000000) + " ms");
134-
135-
/*
136-
// Read out values to ensure they were correct and prevent possible DCE
137-
IndexedChronicle ic = new IndexedChronicle(newPath);
138-
ic.useUnsafe(excerptType == ExcerptType.UNSAFE);
139-
Excerpt readExcerpt = ic.createExcerpt();
140-
for (int i = 0; i < TOTAL_RECORDS; i++) {
141-
boolean found = readExcerpt.nextIndex();
142-
if (!found)
143-
assertTrue(found);
144-
for (int j = 0; j < NUM_ENTRIES_PER_RECORD; j++) {
145-
long l = readExcerpt.readLong();
146-
double d = readExcerpt.readDouble();
147-
if (l != RANDOM_LONGS[i][j])
148-
assertEquals(l, RANDOM_LONGS[i][j]);
149-
if (d != RANDOM_DOUBLES[i][j])
150-
assertEquals(d, RANDOM_DOUBLES[i][j]);
151-
}
152-
readExcerpt.finish();
153-
}
154-
ic.close();
155-
*/
156149
}
157150

158151
private static void deleteOnExit(String basePath) {

0 commit comments

Comments
 (0)