JAVA常用IO方式包括流,通道和MappedByteBuffer。
试验通过复制一个大文件(eclipse-jee-juno-SR2-win32.rar 237M),并选择不同的缓冲区大小,记录复制的时间。
影响IO的因素有很多,同样的方式复制时间可能差异很大。所以需要排除一些最大和最小的数据,保证样本的正确性。
-
import java.io.BufferedInputStream;
-
import java.io.BufferedOutputStream;
-
import java.io.File;
-
import java.io.FileInputStream;
-
import java.io.FileOutputStream;
-
import java.io.IOException;
-
import java.io.RandomAccessFile;
-
import java.lang.reflect.InvocationHandler;
-
import java.lang.reflect.Method;
-
import java.lang.reflect.Proxy;
-
import java.nio.ByteBuffer;
-
import java.nio.MappedByteBuffer;
-
import java.nio.channels.FileChannel;
-
import java.nio.channels.FileChannel.MapMode;
-
import java.util.Date;
-
-
public class TestIO {
-
// 缓存大小
-
private static enum BufferSize {
-
_1M, _10M, _50M;
-
-
public static int getBufferSize(BufferSize bufferSize) {
-
if ("_1M".equals(bufferSize.toString())) {
-
return 1024 * 1024;
-
} else if ("_10M".equals(bufferSize.toString())) {
-
return 10 * 1024 * 1024;
-
} else if ("_50M".equals(bufferSize.toString())) {
-
return 50 * 1024 * 1024;
-
}
-
return -1;
-
}
-
}
-
-
// 源文件
-
private static File source = new File("C:/Users/lihuilin/Desktop/eclipse-jee-juno-SR2-win32.rar");
-
-
// 复制文件接口
-
private static interface Copy {
-
void action() throws Exception;
-
-
BufferSize getBufferSize();
-
}
-
-
// 获取目标文件
-
private static File getTarget(Copy copy, BufferSize bufferSize) {
-
String target = "C:/tmp/" + copy.getClass().getSimpleName() + bufferSize.toString() + "_" + new Date().getTime() + ".rar";
-
return new File(target);
-
}
-
-
// 传统IO流复制方式
-
private static class Stream implements Copy {
-
BufferSize bufferSize;
-
-
public Stream(BufferSize bufferSize) {
-
this.bufferSize = bufferSize;
-
}
-
-
@Override
-
public void action() throws IOException {
-
BufferedInputStream in = new BufferedInputStream(new FileInputStream(source), BufferSize.getBufferSize(bufferSize));
-
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(getTarget(this, bufferSize)));
-
byte[] buffer = new byte[BufferSize.getBufferSize(bufferSize)];
-
int length;
-
while ((length = in.read(buffer)) != -1) {
-
out.write(buffer, 0, length);
-
}
-
out.flush();
-
in.close();
-
out.close();
-
}
-
-
@Override
-
public BufferSize getBufferSize() {
-
return bufferSize;
-
}
-
}
-
-
// NIO通道方式
-
private static class Channel implements Copy {
-
-
private BufferSize bufferSize;
-
-
public Channel(BufferSize bufferSize) {
-
this.bufferSize = bufferSize;
-
}
-
-
@Override
-
public void action() throws Exception {
-
FileChannel in = new FileInputStream(source).getChannel();
-
FileChannel out = new FileOutputStream(getTarget(this, bufferSize)).getChannel();
-
ByteBuffer buffer = ByteBuffer.allocate(BufferSize.getBufferSize(bufferSize));
-
while (in.read(buffer) != -1) {
-
buffer.flip();
-
out.write(buffer);
-
buffer.compact();
-
}
-
in.close();
-
out.close();
-
}
-
-
@Override
-
public BufferSize getBufferSize() {
-
return bufferSize;
-
}
-
}
-
-
// MappedByteBuffer方式
-
private static class Mapped implements Copy {
-
private BufferSize bufferSize;
-
-
public Mapped(BufferSize bufferSize) {
-
this.bufferSize = bufferSize;
-
}
-
-
@Override
-
public void action() throws Exception {
-
FileChannel in = new RandomAccessFile(source, "r").getChannel();
-
FileChannel out = new RandomAccessFile(getTarget(this, bufferSize), "rw").getChannel();
-
long pos = 0;
-
long step = BufferSize.getBufferSize(bufferSize);
-
MappedByteBuffer inBuffer, outBuffer = null;
-
while (pos < in.size() && (in.size() - pos) > step) {
-
inBuffer = in.map(MapMode.READ_ONLY, pos, BufferSize.getBufferSize(bufferSize));
-
outBuffer = out.map(MapMode.READ_WRITE, pos, BufferSize.getBufferSize(bufferSize));
-
outBuffer.put(inBuffer);
-
pos = pos + step;
-
inBuffer.clear();
-
outBuffer.clear();
-
}
-
-
inBuffer = in.map(MapMode.READ_ONLY, pos, in.size() - pos);
-
outBuffer = out.map(MapMode.READ_WRITE, pos, in.size() - pos);
-
-
outBuffer.put(inBuffer);
-
inBuffer.clear();
-
outBuffer.clear();
-
in.close();
-
out.close();
-
}
-
-
@Override
-
public BufferSize getBufferSize() {
-
return bufferSize;
-
}
-
-
}
-
-
// 动态代理,用于记录复制时间并写入日志
-
private static class Watch implements InvocationHandler {
-
private Copy copy;
-
-
public Watch(Copy copy) {
-
this.copy = copy;
-
}
-
-
public Copy getInstance() {
-
return (Copy) Proxy.newProxyInstance(copy.getClass().getClassLoader(), copy.getClass().getInterfaces(), this);
-
}
-
-
@Override
-
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-
Object result;
-
long start = System.currentTimeMillis();
-
result = method.invoke(copy, args);
-
long end = System.currentTimeMillis();
-
-
String log = copy.getClass().getSimpleName() + ":" + copy.getBufferSize().toString() + ":" + (end - start) + "\n";
-
System.out.print(log);
-
FileOutputStream out = new FileOutputStream("C:/tmp/Log.txt", true);
-
out.write(log.getBytes());
-
out.flush();
-
out.close();
-
return result;
-
}
-
}
-
-
public static void main(String[] args) throws Exception {
-
for (int i = 0; i < 15; i++) {
-
new Watch(new Mapped(BufferSize._50M)).getInstance().action();
-
new Watch(new Mapped(BufferSize._10M)).getInstance().action();
-
new Watch(new Mapped(BufferSize._1M)).getInstance().action();
-
-
new Watch(new Channel(BufferSize._50M)).getInstance().action();
-
new Watch(new Channel(BufferSize._10M)).getInstance().action();
-
new Watch(new Channel(BufferSize._1M)).getInstance().action();
-
-
new Watch(new Stream(BufferSize._50M)).getInstance().action();
-
new Watch(new Stream(BufferSize._10M)).getInstance().action();
-
new Watch(new Stream(BufferSize._1M)).getInstance().action();
-
}
-
}
-
}
将样本数据Log.txt挂载为Oracle的外部表,以便分析
-
create table log
-
(
-
copytype varchar2(10),
-
buffersize varchar2(10),
-
copytime varchar2(10)
-
)
-
organization external
-
(
-
type oracle_loader
-
default directory tmp
-
access parameters
-
(
-
records delimited by "\n"
-
FIELDS TERMINATED BY ":" LDRTRIM
-
REJECT ROWS WITH ALL NULL FIELDS
-
(
-
copytype CHAR(20) TERMINATED BY ":",
-
buffersize CHAR(20) TERMINATED BY ":",
-
copytime CHAR(20) TERMINATED BY ":"
-
)
-
)
-
location ('Log.txt')
-
);
查询样本数据,发现同样的方式,差异非常大。
SQL> select * from log where copytype='Channel' and buffersize='_1M';
COPYTYPE BUFFERSIZE COPYTIME
---------- ---------- ----------
Channel _1M 6896
Channel _1M 9859
Channel _1M 5711
Channel _1M 6514
Channel _1M 5400
Channel _1M 5494
Channel _1M 7052
Channel _1M 5807
Channel _1M 10904
Channel _1M 13839
Channel _1M 17035
Channel _1M 6255
Channel _1M 5085
已选择13行。
整理样本数据,将每种方式前五个数据和最后五个数据清除,并建立视图。
-
create or replace view v1 as
-
select copytype,buffersize,copytime from
-
(
-
select copytype,buffersize,copytime,
-
row_number() over(partition by copytype,buffersize order by to_number(copytime)) c1,
-
row_number() over(partition by copytype,buffersize order by to_number(copytime) desc) c2
-
from log
-
) log where c1 not in (1,2,3,4,5) and c2 not in(1,2,3,4,5);
此时数据已经相差不大。
SQL> select * from v1;
COPYTYPE BUFFERSIZE COPYTIME
---------- ---------- ----------
Channel _10M 807
Channel _10M 844
Channel _10M 870
Channel _1M 6255
Channel _1M 6514
Channel _1M 6896
Channel _50M 12748
Channel _50M 12865
Channel _50M 12901
Mapped _10M 11170
Mapped _10M 16355
Mapped _10M 17158
Mapped _1M 1774
Mapped _1M 1963
Mapped _1M 4213
Mapped _50M 472
Mapped _50M 601
Stream _10M 1047
Stream _10M 1182
Stream _10M 1436
Stream _1M 7283
Stream _1M 7347
Stream _50M 28280
Stream _50M 30288
Stream _50M 31012
已选择25行。
使用行转列,查看平均时间。
-
select copytype,
-
round(avg(decode(buffersize,'_1M',copytime)),2) one,
-
round(avg(decode(buffersize,'_10M',copytime)),2) ten,
-
round(avg(decode(buffersize,'_50M',copytime)),2) fifty
-
from v1 group by copytype;
COPYTYPE ONE TEN FIFTY
---------- ---------- ---------- ----------
Channel 6555 840.33 12838
Mapped 2650 14894.33 536.5
Stream 7315 1221.67 29860
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29254281/viewspace-776173/
,如需转载,请注明出处,否则将追究法律责任。