~pbeaman/+junk/sandbox

« back to all changes in this revision

Viewing changes to src/ScatterTest.java

  • Committer: Peter Beaman
  • Date: 2011-08-31 15:56:37 UTC
  • Revision ID: pbeaman@akiban.com-20110831155637-cp1nrrty9ylvy3ww
Put sandbox under bzr

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import java.io.File;
 
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;
 
9
 
 
10
/**
 
11
 * Try to learn how much advantage there is in a gathering byte buffer
 
12
 * 
 
13
 * @author peter
 
14
 * 
 
15
 */
 
16
public class ScatterTest {
 
17
 
 
18
        static ByteBuffer bigBuffer;
 
19
        static MappedByteBuffer mmapBuffer;
 
20
        static long mmapBufferSize = 4 * 1024 * 1024;
 
21
        static long mmapBufferAddress = 0;
 
22
 
 
23
        static int bigBufferFlushCount = 0;
 
24
        static long bigBufferFlushSize = 0;
 
25
 
 
26
        static long start;
 
27
 
 
28
        static enum Which {
 
29
                t1, t2, t3, t4
 
30
        };
 
31
 
 
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);
 
38
 
 
39
                if (file.exists()) {
 
40
                        throw new RuntimeException("File " + file + " exists");
 
41
                }
 
42
 
 
43
                final ByteBuffer header = ByteBuffer.allocate(16);
 
44
                System.arraycopy("aaaabbbbccccdddd".getBytes(), 0, header.array(), 0,
 
45
                                16);
 
46
 
 
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));
 
51
                }
 
52
 
 
53
                final FileChannel channel = new RandomAccessFile(file, "rw")
 
54
                                .getChannel();
 
55
 
 
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);
 
60
                        mmapBuffer.clear();
 
61
                }
 
62
 
 
63
                final Thread thread;
 
64
                if (flush > 0) {
 
65
                        thread = new Thread(new Runnable() {
 
66
                                public void run() {
 
67
                                        while (true) {
 
68
                                                try {
 
69
                                                        Thread.sleep(flush);
 
70
                                                        flush(channel, 0, "Flusher");
 
71
                                                        force(false, channel);
 
72
                                                } catch (Throwable e) {
 
73
                                                        e.printStackTrace();
 
74
                                                }
 
75
                                        }
 
76
                                }
 
77
                        }, "Flusher");
 
78
                        thread.setDaemon(true);
 
79
                        thread.start();
 
80
                }
 
81
 
 
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));
 
87
                        }
 
88
                        final int offset = random.nextInt(1000) + 32;
 
89
                        final int size = random.nextInt(8192 - offset - 32);
 
90
                        switch (which) {
 
91
                        case t1:
 
92
                                t1(channel, header, buffer, offset, size);
 
93
                                break;
 
94
                        case t2:
 
95
                                t2(channel, header, buffer, offset, size);
 
96
                                break;
 
97
                        case t3:
 
98
                                t3(channel, header, buffer, offset, size);
 
99
                                break;
 
100
                        case t4:
 
101
                                t4(channel, header, buffer, offset, size);
 
102
                                break;
 
103
                        }
 
104
                }
 
105
                flush(channel, 0, "Done");
 
106
                force(true, channel);
 
107
 
 
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));
 
116
                }
 
117
 
 
118
                bigBuffer = null;
 
119
 
 
120
                if (mmapBuffer != null) {
 
121
                        channel.truncate(mmapBuffer.limit() + mmapBufferAddress);
 
122
                }
 
123
        }
 
124
 
 
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) {
 
130
                                bigBuffer.flip();
 
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);
 
137
                                bigBuffer.clear();
 
138
                                Thread.sleep(20);
 
139
                        }
 
140
                }
 
141
        }
 
142
 
 
143
        private static void force(final boolean metaData, final FileChannel channel)
 
144
                        throws IOException {
 
145
                final long start = System.nanoTime();
 
146
                if (mmapBuffer != null) {
 
147
                        mmapBuffer.force();
 
148
                } else {
 
149
                        channel.force(metaData);
 
150
                }
 
151
                final long elapsed = System.nanoTime() - start;
 
152
                System.out.printf("Force took %,dns\n", elapsed);
 
153
        }
 
154
 
 
155
        private static void t1(final FileChannel channel, final ByteBuffer header,
 
156
                        final ByteBuffer buffer, final int offset, final int size)
 
157
                        throws Exception {
 
158
                header.position(0);
 
159
                header.limit(16);
 
160
                channel.write(header);
 
161
                buffer.position(0);
 
162
                buffer.limit(offset);
 
163
                channel.write(buffer);
 
164
                buffer.limit(8192);
 
165
                buffer.position(offset + size);
 
166
                channel.write(buffer);
 
167
        }
 
168
 
 
169
        private static void t2(final FileChannel channel, final ByteBuffer header,
 
170
                        final ByteBuffer buffer, final int offset, final int size)
 
171
                        throws Exception {
 
172
                header.position(0);
 
173
                header.limit(16);
 
174
                final ByteBuffer buffer2 = buffer.duplicate();
 
175
                buffer.position(0);
 
176
                buffer.limit(offset);
 
177
                buffer2.limit(8192);
 
178
                buffer2.position(offset + size);
 
179
                channel.write(new ByteBuffer[] { header, buffer, buffer2 });
 
180
        }
 
181
 
 
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));
 
190
                // Thread.yield();
 
191
        }
 
192
 
 
193
        private static void t4(final FileChannel channel, final ByteBuffer header,
 
194
                        final ByteBuffer buffer, final int offset, final int size)
 
195
                        throws Exception {
 
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));
 
199
 
 
200
                if (mmapBuffer.position() > mmapBufferSize - 65536) {
 
201
                        mmapBufferAddress += mmapBuffer.limit();
 
202
                        mmapBuffer = channel.map(MapMode.READ_WRITE, mmapBufferAddress,
 
203
                                        mmapBufferSize);
 
204
                        mmapBuffer.clear();
 
205
                }
 
206
        }
 
207
 
 
208
}