org.apache.activemq.store.kahadb.disk.util.DiskBenchmark Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of activemq-osgi Show documentation
Show all versions of activemq-osgi Show documentation
Puts together an ActiveMQ OSGi bundle
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.store.kahadb.disk.util;
import org.apache.activemq.util.RecoverableRandomAccessFile;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
/**
* This class is used to get a benchmark the raw disk performance.
*/
public class DiskBenchmark {
private static final boolean SKIP_METADATA_UPDATE =
Boolean.getBoolean("org.apache.activemq.file.skipMetadataUpdate");
boolean verbose;
// reads and writes work with 4k of data at a time.
int bs = 1024 * 4;
// Work with 100 meg file.
long size = 1024 * 1024 * 500;
long sampleInterval = 10 * 1000;
public static void main(String[] args) {
DiskBenchmark benchmark = new DiskBenchmark();
args = CommandLineSupport.setOptions(benchmark, args);
ArrayList files = new ArrayList();
if (args.length == 0) {
files.add("disk-benchmark.dat");
} else {
files.addAll(Arrays.asList(args));
}
for (String f : files) {
try {
File file = new File(f);
if (file.exists()) {
System.out.println("File " + file + " already exists, will not benchmark.");
} else {
System.out.println("Benchmarking: " + file.getCanonicalPath());
Report report = benchmark.benchmark(file);
file.delete();
System.out.println(report.toString());
}
} catch (Throwable e) {
if (benchmark.verbose) {
System.out.println("ERROR:");
e.printStackTrace(System.out);
} else {
System.out.println("ERROR: " + e);
}
}
}
}
public static class Report {
public int size;
public int writes;
public long writeDuration;
public int syncWrites;
public long syncWriteDuration;
public int reads;
public long readDuration;
@Override
public String toString() {
return "Writes: \n" + " " + writes + " writes of size " + size + " written in " + (writeDuration / 1000.0) + " seconds.\n" + " " + getWriteRate()
+ " writes/second.\n" + " " + getWriteSizeRate() + " megs/second.\n" + "\n" + "Sync Writes: \n" + " " + syncWrites + " writes of size "
+ size + " written in " + (syncWriteDuration / 1000.0) + " seconds.\n" + " " + getSyncWriteRate() + " writes/second.\n" + " "
+ getSyncWriteSizeRate() + " megs/second.\n" + "\n" + "Reads: \n" + " " + reads + " reads of size " + size + " read in "
+ (readDuration / 1000.0) + " seconds.\n" + " " + getReadRate() + " writes/second.\n" + " " + getReadSizeRate() + " megs/second.\n" + "\n"
+ "";
}
private float getWriteSizeRate() {
float rc = writes;
rc *= size;
rc /= (1024 * 1024); // put it in megs
rc /= (writeDuration / 1000.0); // get rate.
return rc;
}
private float getWriteRate() {
float rc = writes;
rc /= (writeDuration / 1000.0); // get rate.
return rc;
}
private float getSyncWriteSizeRate() {
float rc = syncWrites;
rc *= size;
rc /= (1024 * 1024); // put it in megs
rc /= (syncWriteDuration / 1000.0); // get rate.
return rc;
}
private float getSyncWriteRate() {
float rc = syncWrites;
rc /= (syncWriteDuration / 1000.0); // get rate.
return rc;
}
private float getReadSizeRate() {
float rc = reads;
rc *= size;
rc /= (1024 * 1024); // put it in megs
rc /= (readDuration / 1000.0); // get rate.
return rc;
}
private float getReadRate() {
float rc = reads;
rc /= (readDuration / 1000.0); // get rate.
return rc;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getWrites() {
return writes;
}
public void setWrites(int writes) {
this.writes = writes;
}
public long getWriteDuration() {
return writeDuration;
}
public void setWriteDuration(long writeDuration) {
this.writeDuration = writeDuration;
}
public int getSyncWrites() {
return syncWrites;
}
public void setSyncWrites(int syncWrites) {
this.syncWrites = syncWrites;
}
public long getSyncWriteDuration() {
return syncWriteDuration;
}
public void setSyncWriteDuration(long syncWriteDuration) {
this.syncWriteDuration = syncWriteDuration;
}
public int getReads() {
return reads;
}
public void setReads(int reads) {
this.reads = reads;
}
public long getReadDuration() {
return readDuration;
}
public void setReadDuration(long readDuration) {
this.readDuration = readDuration;
}
}
public Report benchmark(File file) throws Exception {
Report rc = new Report();
// Initialize the block we will be writing to disk.
byte[] data = new byte[bs];
for (int i = 0; i < data.length; i++) {
data[i] = (byte) ('a' + (i % 26));
}
rc.size = data.length;
RecoverableRandomAccessFile raf = new RecoverableRandomAccessFile(file, "rw");
preallocateDataFile(raf, file.getParentFile());
// Figure out how many writes we can do in the sample interval.
long start = System.currentTimeMillis();
long now = System.currentTimeMillis();
int ioCount = 0;
while (true) {
if ((now - start) > sampleInterval) {
break;
}
raf.seek(0);
for (long i = 0; i + data.length < size; i += data.length) {
raf.write(data);
ioCount++;
now = System.currentTimeMillis();
if ((now - start) > sampleInterval) {
break;
}
}
// Sync to disk so that the we actually write the data to disk..
// otherwise OS buffering might not really do the write.
raf.getChannel().force(!SKIP_METADATA_UPDATE);
}
raf.getChannel().force(!SKIP_METADATA_UPDATE);
raf.close();
now = System.currentTimeMillis();
rc.size = data.length;
rc.writes = ioCount;
rc.writeDuration = (now - start);
raf = new RecoverableRandomAccessFile(file, "rw");
start = System.currentTimeMillis();
now = System.currentTimeMillis();
ioCount = 0;
while (true) {
if ((now - start) > sampleInterval) {
break;
}
for (long i = 0; i + data.length < size; i += data.length) {
raf.seek(i);
raf.write(data);
raf.getChannel().force(!SKIP_METADATA_UPDATE);
ioCount++;
now = System.currentTimeMillis();
if ((now - start) > sampleInterval) {
break;
}
}
}
raf.close();
now = System.currentTimeMillis();
rc.syncWrites = ioCount;
rc.syncWriteDuration = (now - start);
raf = new RecoverableRandomAccessFile(file, "rw");
start = System.currentTimeMillis();
now = System.currentTimeMillis();
ioCount = 0;
while (true) {
if ((now - start) > sampleInterval) {
break;
}
raf.seek(0);
for (long i = 0; i + data.length < size; i += data.length) {
raf.seek(i);
raf.readFully(data);
ioCount++;
now = System.currentTimeMillis();
if ((now - start) > sampleInterval) {
break;
}
}
}
raf.close();
rc.reads = ioCount;
rc.readDuration = (now - start);
return rc;
}
private void preallocateDataFile(RecoverableRandomAccessFile raf, File location) throws Exception {
File tmpFile;
if (location != null && location.isDirectory()) {
tmpFile = new File(location, "template.dat");
}else {
tmpFile = new File("template.dat");
}
if (tmpFile.exists()) {
tmpFile.delete();
}
RandomAccessFile templateFile = new RandomAccessFile(tmpFile, "rw");
templateFile.setLength(size);
templateFile.getChannel().force(true);
templateFile.getChannel().transferTo(0, size, raf.getChannel());
templateFile.close();
tmpFile.delete();
}
public boolean isVerbose() {
return verbose;
}
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
public int getBs() {
return bs;
}
public void setBs(int bs) {
this.bs = bs;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public long getSampleInterval() {
return sampleInterval;
}
public void setSampleInterval(long sampleInterval) {
this.sampleInterval = sampleInterval;
}
}