Last active
April 23, 2017 16:44
-
-
Save rednikotin/8372e6ba27f8491228e764b82234c8c1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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