Skip to content

Commit ead66d0

Browse files
committed
Improved delete performance by:
- Checking with inflight writes and only syncing them when needed. - Reduced number of seeks. - Only physically syncing when the corresponding journal property is set.
1 parent b73ccf8 commit ead66d0

File tree

4 files changed

+70
-33
lines changed

4 files changed

+70
-33
lines changed

src/main/java/journal/io/api/DataFileAccessor.java

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ void updateLocation(Location location, byte type, boolean sync) throws ClosedJou
6060
threadLock.lock();
6161
try {
6262
if (opened) {
63-
journal.sync();
63+
if (journal.getInflightWrites().containsKey(location)) {
64+
journal.sync();
65+
}
6466
//
6567
RandomAccessFile raf = getOrCreateRaf(Thread.currentThread(), location.getDataFileId());
6668
if (seekToLocation(raf, location, false)) {
@@ -278,39 +280,52 @@ private boolean seekToLocation(RandomAccessFile raf, Location destination, boole
278280
length = raf.readInt();
279281
type = raf.readByte();
280282
}
281-
// Else seek:
283+
// If pointer is wrong, seek by trying the saved file position:
282284
if (pointer != destination.getPointer()) {
283-
Entry<Location, Long> hint = journal.getHints().lowerEntry(destination);
284-
if (hint != null && hint.getKey().getDataFileId() == destination.getDataFileId()) {
285-
position = hint.getValue();
286-
} else {
287-
position = Journal.FILE_HEADER_SIZE;
288-
}
289-
raf.seek(position);
290-
if (raf.length() - position > Journal.RECORD_HEADER_SIZE) {
285+
position = destination.getThisFilePosition();
286+
if (position != Location.NOT_SET && raf.length() - position > Journal.RECORD_HEADER_SIZE) {
287+
raf.seek(position);
291288
pointer = raf.readInt();
292289
length = raf.readInt();
293290
type = raf.readByte();
294-
while (pointer != destination.getPointer()) {
295-
IOHelper.skipBytes(raf, length - Journal.RECORD_HEADER_SIZE);
296-
position = raf.getFilePointer();
297-
if (raf.length() - position > Journal.RECORD_HEADER_SIZE) {
298-
pointer = raf.readInt();
299-
length = raf.readInt();
300-
type = raf.readByte();
301-
} else {
302-
return false;
291+
}
292+
// Else seek by using hints:
293+
if (pointer != destination.getPointer()) {
294+
Entry<Location, Long> hint = journal.getHints().lowerEntry(destination);
295+
if (hint != null && hint.getKey().getDataFileId() == destination.getDataFileId()) {
296+
position = hint.getValue();
297+
} else {
298+
position = Journal.FILE_HEADER_SIZE;
299+
}
300+
raf.seek(position);
301+
if (raf.length() - position > Journal.RECORD_HEADER_SIZE) {
302+
pointer = raf.readInt();
303+
length = raf.readInt();
304+
type = raf.readByte();
305+
while (pointer != destination.getPointer()) {
306+
IOHelper.skipBytes(raf, length - Journal.RECORD_HEADER_SIZE);
307+
position = raf.getFilePointer();
308+
if (raf.length() - position > Journal.RECORD_HEADER_SIZE) {
309+
pointer = raf.readInt();
310+
length = raf.readInt();
311+
type = raf.readByte();
312+
} else {
313+
return false;
314+
}
303315
}
316+
} else {
317+
return false;
304318
}
305-
} else {
306-
return false;
307319
}
308320
}
309321
if (fillLocation) {
322+
// If we have to fill the location, do so and do not seek back to this position:
310323
destination.setThisFilePosition(position);
311324
destination.setSize(length);
312325
destination.setType(type);
313326
} else {
327+
// Otherwise seek back to this position as caller will probably read
328+
// things by itself:
314329
raf.seek(position);
315330
}
316331
return true;
@@ -351,6 +366,7 @@ private RandomAccessFile getOrCreateRaf(Thread thread, Integer file) throws Comp
351366
RandomAccessFile raf = rafs.get(file);
352367
if (raf == null) {
353368
raf = journal.getDataFile(file).openRandomAccessFile();
369+
IOHelper.skipBytes(raf, journal.FILE_HEADER_SIZE);
354370
rafs.put(file, raf);
355371
}
356372
return raf;

src/main/java/journal/io/api/Journal.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ public Location write(byte[] data, WriteType write, WriteCallback callback) thro
344344
* @throws CompactedDataFileException
345345
*/
346346
public void delete(Location location) throws ClosedJournalException, CompactedDataFileException, IOException {
347-
accessor.updateLocation(location, Location.DELETED_RECORD_TYPE, true);
347+
accessor.updateLocation(location, Location.DELETED_RECORD_TYPE, physicalSync);
348348
}
349349

350350
/**

src/test/java/journal/io/PerformanceTest.java

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,10 @@ public void testSyncPerf() throws Exception {
7575
for (int i = 0; i < iterations; i++) {
7676
journal.write(payload, Journal.WriteType.SYNC);
7777
}
78-
journal.close();
7978
//
80-
System.out.println("Time in millis: " + (System.currentTimeMillis() - start));
79+
System.out.println("testSyncPerf time in millis: " + (System.currentTimeMillis() - start));
80+
//
81+
journal.close();
8182
}
8283

8384
@Test
@@ -89,9 +90,10 @@ public void testAsyncPerf() throws Exception {
8990
for (int i = 0; i < iterations; i++) {
9091
journal.write(payload, Journal.WriteType.ASYNC);
9192
}
92-
journal.close();
9393
//
94-
System.out.println("Time in millis: " + (System.currentTimeMillis() - start));
94+
System.out.println("testAsyncPerf time in millis: " + (System.currentTimeMillis() - start));
95+
//
96+
journal.close();
9597
}
9698

9799
@Test
@@ -107,11 +109,11 @@ public void testSequentialReadPerf() throws Exception {
107109
assertEquals("" + i++, new String(journal.read(current, Journal.ReadType.ASYNC), "UTF-8"));
108110
}
109111
//
110-
journal.close();
112+
System.out.println("testSequentialReadPerf time in millis: " + (System.currentTimeMillis() - start));
111113
//
112-
System.out.println("Time in millis: " + (System.currentTimeMillis() - start));
114+
journal.close();
113115
}
114-
116+
115117
@Test
116118
public void testRandomReadPerf() throws Exception {
117119
int iterations = 1000000;
@@ -128,14 +130,33 @@ public void testRandomReadPerf() throws Exception {
128130
assertEquals("" + n, new String(journal.read(read, Journal.ReadType.ASYNC), "UTF-8"));
129131
}
130132
//
133+
System.out.println("testRandomReadPerf time in millis: " + (System.currentTimeMillis() - start));
134+
//
131135
journal.close();
136+
}
137+
138+
@Test
139+
public void testDeletePerf() throws Exception {
140+
int iterations = 1000000;
141+
byte[] payload = new byte[100];
142+
for (int i = 0; i < iterations; i++) {
143+
journal.write(payload, Journal.WriteType.ASYNC);
144+
}
132145
//
133-
System.out.println("Time in millis: " + (System.currentTimeMillis() - start));
146+
long start = System.currentTimeMillis();
147+
//
148+
for (Location location : journal.redo()) {
149+
journal.delete(location);
150+
}
151+
//
152+
System.out.println("testDeletePerf time in millis: " + (System.currentTimeMillis() - start));
153+
//
154+
journal.close();
134155
}
135156

136157
protected void configure(Journal journal) {
137-
journal.setMaxFileLength(1024 * 1024 * 32);
138-
journal.setMaxWriteBatchSize(1024 * 100);
158+
journal.setMaxFileLength(1024 * 1024 * 10);
159+
journal.setMaxWriteBatchSize(1024);
139160
}
140161

141162
private void deleteFilesInDirectory(File directory) {

src/test/java/journal/io/api/ReadWriteTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
public class ReadWriteTest extends AbstractJournalTest {
2727

2828
@Test(expected = IOException.class)
29-
public void testAsyncSpeculativeReadWorksButSyncReadRaisesException() throws Exception {
29+
public void testAfterDeleteAsyncSpeculativeReadWorksButSyncReadRaisesException() throws Exception {
3030
Location data = journal.write(new String("DATA").getBytes("UTF-8"), Journal.WriteType.SYNC);
3131
journal.delete(data);
3232
assertEquals("DATA", journal.read(data, Journal.ReadType.ASYNC));

0 commit comments

Comments
 (0)