2
import java.io.IOException;
3
import java.io.RandomAccessFile;
4
import java.nio.ByteBuffer;
5
import java.nio.MappedByteBuffer;
6
import java.nio.channels.FileChannel;
7
import java.nio.channels.FileChannel.MapMode;
8
import java.util.Random;
11
* Try to learn how much advantage there is in a gathering byte buffer
16
public class ScatterTest {
18
static ByteBuffer bigBuffer;
19
static MappedByteBuffer mmapBuffer;
20
static long mmapBufferSize = 4 * 1024 * 1024;
21
static long mmapBufferAddress = 0;
23
static int bigBufferFlushCount = 0;
24
static long bigBufferFlushSize = 0;
32
public static void main(final String[] args) throws Exception {
33
final File file = new File(args[0]);
34
final Which which = Which.valueOf(args[1]);
35
final int count = Integer.parseInt(args[2]);
36
final int flush = args.length > 3 ? Integer.parseInt(args[3]) : 0;
37
final Random random = new Random(1234);
40
throw new RuntimeException("File " + file + " exists");
43
final ByteBuffer header = ByteBuffer.allocate(16);
44
System.arraycopy("aaaabbbbccccdddd".getBytes(), 0, header.array(), 0,
47
final ByteBuffer buffer = ByteBuffer.allocate(8192);
48
final byte[] bytes = buffer.array();
49
for (int i = 0; i < bytes.length; i++) {
50
bytes[i] = (byte) (' ' + (i % 64));
53
final FileChannel channel = new RandomAccessFile(file, "rw")
56
if (which == Which.t3) {
57
bigBuffer = ByteBuffer.allocateDirect(4 * 1024 * 1024);
58
} else if (which == Which.t4) {
59
mmapBuffer = channel.map(MapMode.READ_WRITE, 0, mmapBufferSize);
65
thread = new Thread(new Runnable() {
70
flush(channel, 0, "Flusher");
71
force(false, channel);
72
} catch (Throwable e) {
78
thread.setDaemon(true);
82
start = System.nanoTime();
83
for (int i = 1; i <= count; i++) {
84
if (i % 100000 == 0) {
85
System.out.println(String.format("%s %,10d: per=%,10dns",
86
which, i, (System.nanoTime() - start) / i));
88
final int offset = random.nextInt(1000) + 32;
89
final int size = random.nextInt(8192 - offset - 32);
92
t1(channel, header, buffer, offset, size);
95
t2(channel, header, buffer, offset, size);
98
t3(channel, header, buffer, offset, size);
101
t4(channel, header, buffer, offset, size);
105
flush(channel, 0, "Done");
106
force(true, channel);
108
final long end = System.nanoTime();
109
System.out.println();
110
System.out.println(String.format("Total time=%,13dns", end - start));
111
if (bigBufferFlushCount > 0) {
112
System.out.println(String.format(
113
"Flush count=%,8d, bytes per flush=%,8d",
114
bigBufferFlushCount, bigBufferFlushSize
115
/ bigBufferFlushCount));
120
if (mmapBuffer != null) {
121
channel.truncate(mmapBuffer.limit() + mmapBufferAddress);
125
private synchronized static void flush(final FileChannel channel,
126
final int threshold, final String message) throws IOException,
127
InterruptedException {
128
if (bigBuffer != null) {
129
if (bigBuffer.position() > threshold) {
131
bigBufferFlushCount++;
132
final long elapsed = System.nanoTime() - start;
133
// System.out.println(String.format("%,16d %s bytes=%,d",
134
// elapsed, message, bigBuffer.remaining()));
135
bigBufferFlushSize += bigBuffer.remaining();
136
channel.write(bigBuffer);
143
private static void force(final boolean metaData, final FileChannel channel)
145
final long start = System.nanoTime();
146
if (mmapBuffer != null) {
149
channel.force(metaData);
151
final long elapsed = System.nanoTime() - start;
152
System.out.printf("Force took %,dns\n", elapsed);
155
private static void t1(final FileChannel channel, final ByteBuffer header,
156
final ByteBuffer buffer, final int offset, final int size)
160
channel.write(header);
162
buffer.limit(offset);
163
channel.write(buffer);
165
buffer.position(offset + size);
166
channel.write(buffer);
169
private static void t2(final FileChannel channel, final ByteBuffer header,
170
final ByteBuffer buffer, final int offset, final int size)
174
final ByteBuffer buffer2 = buffer.duplicate();
176
buffer.limit(offset);
178
buffer2.position(offset + size);
179
channel.write(new ByteBuffer[] { header, buffer, buffer2 });
182
private synchronized static void t3(final FileChannel channel,
183
final ByteBuffer header, final ByteBuffer buffer, final int offset,
184
final int size) throws Exception {
185
final int need = header.capacity() + buffer.capacity() - size;
186
flush(channel, bigBuffer.capacity() - need, "Forced: need=" + need);
187
bigBuffer.put(header.array(), 0, header.capacity());
188
bigBuffer.put(buffer.array(), 0, offset);
189
bigBuffer.put(buffer.array(), offset + size, 8192 - (offset + size));
193
private static void t4(final FileChannel channel, final ByteBuffer header,
194
final ByteBuffer buffer, final int offset, final int size)
196
mmapBuffer.put(header.array(), 0, header.capacity());
197
mmapBuffer.put(buffer.array(), 0, offset);
198
mmapBuffer.put(buffer.array(), offset + size, 8192 - (offset + size));
200
if (mmapBuffer.position() > mmapBufferSize - 65536) {
201
mmapBufferAddress += mmapBuffer.limit();
202
mmapBuffer = channel.map(MapMode.READ_WRITE, mmapBufferAddress,