Skip to content

Instantly share code, notes, and snippets.

@rednikotin
Last active April 23, 2017 16:44
Show Gist options
  • Save rednikotin/8372e6ba27f8491228e764b82234c8c1 to your computer and use it in GitHub Desktop.
Save rednikotin/8372e6ba27f8491228e764b82234c8c1 to your computer and use it in GitHub Desktop.
package testnio;
import sun.misc.Unsafe;
import sun.nio.ch.FileChannelImpl;
import java.io.File;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Random;
/**
* Usage: <filename> <mul> <parallel of wrtie> <parallel of read> <test repeats>
* Creates file with length = mul * 4Gb populating with dummy data and read it.
* Be aware to create files having size more than free ram available.
*/
public class MMapBigFile {
private static final Unsafe unsafe;
private static final Method mmap;
private static final int BYTE_ARRAY_OFFSET;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = (Unsafe) f.get(null);
mmap = FileChannelImpl.class.getDeclaredMethod("map0", int.class, long.class, long.class);
mmap.setAccessible(true);
BYTE_ARRAY_OFFSET = unsafe.arrayBaseOffset(byte[].class);
} catch (Exception e) {
throw new RuntimeException("Could not instantiate Unsafe", e);
}
}
private static void write(long addr, byte[] arr, int par, long totalSize) throws Exception {
int arrSize = arr.length;
Thread[] threads = new Thread[par];
for (int t = 0; t < par; t++) {
int thisT = t;
threads[thisT] = new Thread(() -> {
long pos = (long)arrSize * thisT;
while (pos < totalSize) {
long length = Math.min(totalSize - pos, arrSize);
unsafe.copyMemory(arr, BYTE_ARRAY_OFFSET, null, addr + pos, length);
pos += length * par;
}
});
threads[thisT].start();
}
for (int t = 0; t < par; t++) threads[t].join();
}
private static long read(long addr, byte[] arr, int par, long totalSize) throws Exception {
int arrSize = arr.length;
long[] sums = new long[par];
Thread[] threads = new Thread[par];
for (int t = 0; t < par; t++) {
int thisT = t;
threads[thisT] = new Thread(() -> {
long sum = 0L;
long pos = (long)arrSize * thisT;
while (pos < totalSize) {
long length = Math.min(totalSize - pos, arrSize);
for (int i = 0; i < length; i++) sum += ((int)unsafe.getByte(addr + pos + i)) & 0xff;
pos += length * par;
}
sums[thisT] = sum;
});
threads[thisT].start();
}
long sum = 0L;
for (int t = 0; t < par; t++) {
threads[t].join();
sum += sums[t];
}
return sum;
}
private static byte[][] createArrays(int arrSize, int cnt) {
byte[][] arrs = new byte[cnt][arrSize];
Random rnd = new Random();
for (int i = 0; i < cnt; i++) {
rnd.setSeed(i);
rnd.nextBytes(arrs[i]);
}
return arrs;
}
public static void main(String[] args) throws Exception {
String name = args[0];
int mul = Integer.parseInt(args[1]);
int parW = Integer.parseInt(args[2]);
int parR = Integer.parseInt(args[3]);
int rep = Integer.parseInt(args[4]);
// prepare 128Mb arrays to fill in data in file
byte[][] arrs = createArrays(1<<27, rep);
long totalSize = (1L << 32) * mul;
long t0, t1;
// prepare and mmap file
RandomAccessFile raf = new RandomAccessFile(new File(name), "rw");
raf.setLength(totalSize);
long addr = (long) mmap.invoke(raf.getChannel(), 1, 0L, totalSize);
System.out.println("File size = " + totalSize/(1<<30) + "Gb");
// run tests
for (int i = 0; i < rep; i++) {
t0 = System.nanoTime();
write(addr, arrs[i], parW, totalSize);
t1 = System.nanoTime();
System.out.println("write time = " + (t1 - t0) / 1e9);
t0 = System.nanoTime();
long sum = read(addr, arrs[i], parR, totalSize);
t1 = System.nanoTime();
System.out.println("read time = " + (t1 - t0) / 1e9);
System.out.println("sum = " + sum);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment