001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.kahadb.util;
018
019 import java.io.File;
020 import java.io.FileNotFoundException;
021 import java.io.IOException;
022 import java.io.RandomAccessFile;
023 import java.util.ArrayList;
024 import java.util.Arrays;
025
026 /**
027 * This class is used to get a benchmark the raw disk performance.
028 */
029 public class DiskBenchmark {
030
031 boolean verbose;
032 // reads and writes work with 4k of data at a time.
033 int bs=1024*4;
034 // Work with 100 meg file.
035 long size=1024*1024*500;
036 long sampleInterval = 10*1000;
037
038 public static void main(String[] args) {
039
040 DiskBenchmark benchmark = new DiskBenchmark();
041 args = CommandLineSupport.setOptions(benchmark, args);
042 ArrayList<String> files = new ArrayList<String>();
043 if (args.length == 0) {
044 files.add("disk-benchmark.dat");
045 } else {
046 files.addAll(Arrays.asList(args));
047 }
048
049 for (String f : files) {
050 try {
051 File file = new File(f);
052 if (file.exists()) {
053 System.out.println("File " + file + " allready exists, will not benchmark.");
054 } else {
055 System.out.println("Benchmarking: " + file.getCanonicalPath());
056 Report report = benchmark.benchmark(file);
057 file.delete();
058 System.out.println(report.toString());
059 }
060 } catch (Throwable e) {
061 if (benchmark.verbose) {
062 System.out.println("ERROR:");
063 e.printStackTrace(System.out);
064 } else {
065 System.out.println("ERROR: " + e);
066 }
067 }
068 }
069
070 }
071
072 public static class Report {
073
074 public int size;
075
076 public int writes;
077 public long writeDuration;
078
079 public int syncWrites;
080 public long syncWriteDuration;
081
082 public int reads;
083 public long readDuration;
084
085 @Override
086 public String toString() {
087 return
088 "Writes: \n" +
089 " "+writes+" writes of size "+size+" written in "+(writeDuration/1000.0)+" seconds.\n"+
090 " "+getWriteRate()+" writes/second.\n"+
091 " "+getWriteSizeRate()+" megs/second.\n"+
092 "\n"+
093 "Sync Writes: \n" +
094 " "+syncWrites+" writes of size "+size+" written in "+(syncWriteDuration/1000.0)+" seconds.\n"+
095 " "+getSyncWriteRate()+" writes/second.\n"+
096 " "+getSyncWriteSizeRate()+" megs/second.\n"+
097 "\n"+
098 "Reads: \n" +
099 " "+reads+" reads of size "+size+" read in "+(readDuration/1000.0)+" seconds.\n"+
100 " "+getReadRate()+" writes/second.\n"+
101 " "+getReadSizeRate()+" megs/second.\n"+
102 "\n"+
103 "";
104 }
105
106 private float getWriteSizeRate() {
107 float rc = writes;
108 rc *= size;
109 rc /= (1024*1024); // put it in megs
110 rc /= (writeDuration/1000.0); // get rate.
111 return rc;
112 }
113
114 private float getWriteRate() {
115 float rc = writes;
116 rc /= (writeDuration/1000.0); // get rate.
117 return rc;
118 }
119
120 private float getSyncWriteSizeRate() {
121 float rc = syncWrites;
122 rc *= size;
123 rc /= (1024*1024); // put it in megs
124 rc /= (syncWriteDuration/1000.0); // get rate.
125 return rc;
126 }
127
128 private float getSyncWriteRate() {
129 float rc = syncWrites;
130 rc /= (syncWriteDuration/1000.0); // get rate.
131 return rc;
132 }
133 private float getReadSizeRate() {
134 float rc = reads;
135 rc *= size;
136 rc /= (1024*1024); // put it in megs
137 rc /= (readDuration/1000.0); // get rate.
138 return rc;
139 }
140
141 private float getReadRate() {
142 float rc = reads;
143 rc /= (readDuration/1000.0); // get rate.
144 return rc;
145 }
146
147 public int getSize() {
148 return size;
149 }
150
151 public void setSize(int size) {
152 this.size = size;
153 }
154
155 public int getWrites() {
156 return writes;
157 }
158
159 public void setWrites(int writes) {
160 this.writes = writes;
161 }
162
163 public long getWriteDuration() {
164 return writeDuration;
165 }
166
167 public void setWriteDuration(long writeDuration) {
168 this.writeDuration = writeDuration;
169 }
170
171 public int getSyncWrites() {
172 return syncWrites;
173 }
174
175 public void setSyncWrites(int syncWrites) {
176 this.syncWrites = syncWrites;
177 }
178
179 public long getSyncWriteDuration() {
180 return syncWriteDuration;
181 }
182
183 public void setSyncWriteDuration(long syncWriteDuration) {
184 this.syncWriteDuration = syncWriteDuration;
185 }
186
187 public int getReads() {
188 return reads;
189 }
190
191 public void setReads(int reads) {
192 this.reads = reads;
193 }
194
195 public long getReadDuration() {
196 return readDuration;
197 }
198
199 public void setReadDuration(long readDuration) {
200 this.readDuration = readDuration;
201 }
202 }
203
204
205 public Report benchmark(File file) throws IOException {
206 Report rc = new Report();
207
208 // Initialize the block we will be writing to disk.
209 byte []data = new byte[bs];
210 for (int i = 0; i < data.length; i++) {
211 data[i] = (byte)('a'+(i%26));
212 }
213
214 rc.size = data.length;
215 RandomAccessFile raf = new RandomAccessFile(file, "rw");
216 raf.setLength(size);
217
218 // Figure out how many writes we can do in the sample interval.
219 long start = System.currentTimeMillis();
220 long now = System.currentTimeMillis();
221 int ioCount=0;
222 while( true ) {
223 if( (now-start)>sampleInterval ) {
224 break;
225 }
226 raf.seek(0);
227 for( long i=0; i+data.length < size; i+=data.length) {
228 raf.write(data);
229 ioCount++;
230 now = System.currentTimeMillis();
231 if( (now-start)>sampleInterval ) {
232 break;
233 }
234 }
235 // Sync to disk so that the we actually write the data to disk.. otherwise
236 // OS buffering might not really do the write.
237 raf.getFD().sync();
238 }
239 raf.getFD().sync();
240 raf.close();
241 now = System.currentTimeMillis();
242
243 rc.size = data.length;
244 rc.writes = ioCount;
245 rc.writeDuration = (now-start);
246
247 raf = new RandomAccessFile(file, "rw");
248 start = System.currentTimeMillis();
249 now = System.currentTimeMillis();
250 ioCount=0;
251 while( true ) {
252 if( (now-start)>sampleInterval ) {
253 break;
254 }
255 for( long i=0; i+data.length < size; i+=data.length) {
256 raf.seek(i);
257 raf.write(data);
258 raf.getFD().sync();
259 ioCount++;
260 now = System.currentTimeMillis();
261 if( (now-start)>sampleInterval ) {
262 break;
263 }
264 }
265 }
266 raf.close();
267 now = System.currentTimeMillis();
268 rc.syncWrites = ioCount;
269 rc.syncWriteDuration = (now-start);
270
271 raf = new RandomAccessFile(file, "rw");
272 start = System.currentTimeMillis();
273 now = System.currentTimeMillis();
274 ioCount=0;
275 while( true ) {
276 if( (now-start)>sampleInterval ) {
277 break;
278 }
279 raf.seek(0);
280 for( long i=0; i+data.length < size; i+=data.length) {
281 raf.seek(i);
282 raf.readFully(data);
283 ioCount++;
284 now = System.currentTimeMillis();
285 if( (now-start)>sampleInterval ) {
286 break;
287 }
288 }
289 }
290 raf.close();
291
292 rc.reads = ioCount;
293 rc.readDuration = (now-start);
294 return rc;
295 }
296
297
298 public boolean isVerbose() {
299 return verbose;
300 }
301
302
303 public void setVerbose(boolean verbose) {
304 this.verbose = verbose;
305 }
306
307
308 public int getBs() {
309 return bs;
310 }
311
312
313 public void setBs(int bs) {
314 this.bs = bs;
315 }
316
317
318 public long getSize() {
319 return size;
320 }
321
322
323 public void setSize(long size) {
324 this.size = size;
325 }
326
327
328 public long getSampleInterval() {
329 return sampleInterval;
330 }
331
332
333 public void setSampleInterval(long sampleInterval) {
334 this.sampleInterval = sampleInterval;
335 }
336
337 }