java nio 从内存读信息_Java NIO(内存映射文件) 与 传统IO 读取 性能测试

package io;

import java.io.File;

import java.io.RandomAccessFile;

import java.nio.ByteBuffer;

import java.nio.MappedByteBuffer;

import java.nio.channels.FileChannel;

import java.nio.channels.FileChannel.MapMode;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

/**

* Java NIO(内存映射文件) 与 传统IO 读取 性能测试

*

* 读取 RandomAccessFile 类读写测试及其性能优化(一)

* (链接 http://jackyin5918.iteye.com/blog/2022888 )中

* GenerateIntArray 生成的并保存到文件的数据.

* 测试时读取1千万个整型构成的二进制文件38.1M

*

* 由测试结果分析可知:

*

* readData(f) -- 普通IO方式读取

* readDataNIO(f) -- NIO Channel,Buffer方式读取

* readDataNIO_D(f) -- NIO中Buffer使用 直接方式分配空间(allocateDirect)

* readDataMap_M(f) -- 多线程中使用 内存映射文件

* readDataMap(f) -- 单线程中使用内存映射文件读取

*

* NIO方式使用直接分配Buffer空间方式读取性能最好,甚至超过了内存映射文件

* (可能是文件还不够大,如果文件达到1000M以上应该是内存映射文件性能最好).

*

* 普通NIO方式 耗时 是NIO_D方式的2倍.

*

* 传统IO方式读取文件,耗时 是NIO的 上百倍.

*

* 内存映射文件,在文件较大(大小达到几十M时)可以显著提升性能.

* 多线程中使用内存映射文件 没有 提高性能.

----------------------测试结果---------

count = 1000, size = 10000

正在读取数据,请稍后...

readData(f) 读取数据成功, 耗时:411326

正在读取数据,请稍后...

readDataNIO_D(f) 读取数据成功, 耗时:4161

正在读取数据,请稍后...

readDataNIO(f) 读取数据成功, 耗时:10645

正在读取数据,请稍后...

readDataMap_M(f) 读取数据成功, 耗时:6682

正在读取数据,请稍后...

readDataMap 读取数据成功, 耗时:4841

*/

public class GetTheMiddle

{

private int count = 10; // 数组的个数,

private int size = 1000; // 每个数组的元素个数

private int[][] dataArr;

public GetTheMiddle()

{

dataArr = new int[count][size];

}

public GetTheMiddle(int count, int size)

{

this.count = count;

this.size = size;

this.dataArr = new int[count][size];

}

public int[][] getDataArr()

{

return dataArr;

}

public int[][] readData(File f)

{

try

{

RandomAccessFile rf = new RandomAccessFile(f, "r");

for (int i = 0; i < count; i++)

{

for (int j = 0; j < size; j++)

{

dataArr[i][j] = rf.readInt();

}

}

rf.close();

}

catch (Exception e)

{

e.printStackTrace();

}

return dataArr;

}

public int[][] readDataNIO(File f)

{

try

{

RandomAccessFile rf = new RandomAccessFile(f, "r");

FileChannel fc = rf.getChannel();

ByteBuffer buffer = ByteBuffer.allocate(size * 4);

for (int i = 0; i < count; i++)

{

fc.read(buffer);

buffer.rewind();

for (int j = 0; j < size; j++)

{

dataArr[i][j] = buffer.getInt();

}

buffer.rewind();

}

rf.close();

}

catch (Exception e)

{

e.printStackTrace();

}

return dataArr;

}

public int[][] readDataNIO_D(File f)

{

try

{

RandomAccessFile rf = new RandomAccessFile(f, "r");

FileChannel fc = rf.getChannel();

ByteBuffer buffer = ByteBuffer.allocateDirect(size * 4);

for (int i = 0; i < count; i++)

{

fc.read(buffer);

buffer.rewind();

for (int j = 0; j < size; j++)

{

dataArr[i][j] = buffer.getInt();

}

buffer.rewind();

}

rf.close();

}

catch (Exception e)

{

e.printStackTrace();

}

return dataArr;

}

public int[][] readDataMap(File f)

{

try

{

RandomAccessFile rf = new RandomAccessFile(f, "r");

FileChannel fc = rf.getChannel();

int mapSize = size * 4;

for (int i = 0; i < count; i++)

{

int position = i * size * 4;

MappedByteBuffer mBuffer = fc.map(MapMode.READ_ONLY,position,mapSize);

for (int j = 0; j < size; j++)

{

dataArr[i][j] = mBuffer.getInt();

}

}

rf.close();

}

catch (Exception e)

{

e.printStackTrace();

}

return dataArr;

}

class ReadDataTask implements Runnable

{

private File f;

private int dataIndex;

public ReadDataTask(File f,int dataIndex)

{

this.f = f;

this.dataIndex = dataIndex;

}

@Override

public void run()

{

try

{

RandomAccessFile rf = new RandomAccessFile(f, "r");

FileChannel fc = rf.getChannel();

int mapSize = size * 4;

int position = dataIndex * size * 4;

MappedByteBuffer mBuffer = fc.map(MapMode.READ_ONLY,position,mapSize);

for (int j = 0; j < size; j++)

{

dataArr[dataIndex][j] = mBuffer.getInt();

}

rf.close();

}

catch (Exception e)

{

e.printStackTrace();

}

}

}

public int[][] readDataMap_M(File f)

{

try

{

ExecutorService exec = Executors.newCachedThreadPool();

for(int i=0;i

{

exec.execute(new ReadDataTask(f,i));

}

exec.shutdown();

while(true)

{

if(exec.isTerminated()) break;

}

}

catch (Exception e)

{

e.printStackTrace();

}

return dataArr;

}

public static void main(String[] args)

{

int count = 1000;

int size = 10000;

boolean bPrintData = false; // 是否打印生成的数组,当数据量大是不打印,只在小数据量时打印以便测试

boolean bRefreshData = true; //是否重新生成数据,第一次测试时生成数据后,改成false不必重新生成数据

System.out.printf("count = %d, size = %d \n\n", count, size);

GetTheMiddle gm = new GetTheMiddle(count,size);

GenerateIntArray generator = new GenerateIntArray(count, size);

File f;

try

{

f = new File("D:\\D\\test_data.dat");

if(bRefreshData)

{

generator.refreshDataArr();

generator.writeData2File_B(f);

}

System.out.println("正在读取数据,请稍后...");

long startTmie = System.nanoTime();

gm.readData(f);

long totalTime = (System.nanoTime() - startTmie)/ 100000;

System.out.println("readData(f) 读取数据成功, 耗时:" + totalTime);

System.out.println();

System.out.println("正在读取数据,请稍后...");

startTmie = System.nanoTime();

gm.readDataNIO_D(f);

totalTime = (System.nanoTime() - startTmie)/ 100000;

System.out.println("readDataNIO_D(f) 读取数据成功, 耗时:" + totalTime);

System.out.println();

System.out.println("正在读取数据,请稍后...");

startTmie = System.nanoTime();

gm.readDataNIO(f);

totalTime = (System.nanoTime() - startTmie)/ 100000;

System.out.println("readDataNIO(f) 读取数据成功, 耗时:" + totalTime);

System.out.println();

System.out.println("正在读取数据,请稍后...");

startTmie = System.nanoTime();

gm.readDataMap_M(f);

totalTime = (System.nanoTime() - startTmie)/ 100000;

System.out.println("readDataMap_M(f) 读取数据成功, 耗时:" + totalTime);

System.out.println();

System.out.println("正在读取数据,请稍后...");

startTmie = System.nanoTime();

gm.readDataMap(f);

totalTime = (System.nanoTime() - startTmie)/ 100000;

System.out.println("readDataMap 读取数据成功, 耗时:" + totalTime);

System.out.println();

}

catch (Exception e)

{

e.printStackTrace();

}

if(bPrintData)

{

System.out.println("generator中生成的数据...");

int[][] intArr = generator.getDataArr();

for (int i = 0; i < count; i++)

{

for (int j = 0; j < size; j++)

{

System.out.printf("%1$3d", intArr[i][j]);

}

System.out.println();

}

System.out.println("读取出来的数组...");

intArr = gm.getDataArr();

for (int i = 0; i < count; i++)

{

for (int j = 0; j < size; j++)

{

System.out.printf("%1$-5s", intArr[i][j]);

}

System.out.println();

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值