【发布时间】:2013-07-08 02:40:34
【问题描述】:
当我想编写将文本写入文件的 Java 代码时,它通常看起来像这样:
File logFile = new File("/home/someUser/app.log");
FileWriter writer;
try {
writer = new FileWriter(logFile, true);
writer.write("Some text.");
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
我现在正在编写一个Logger,它将被内部报告工具广泛使用。由于此问题上下文之外的原因,我不能使用传统的日志记录框架之一(SLF4J、Log4j、Logback、JUL、JCL 等)。所以我必须做一些本土的东西。
这个日志系统很简单,不可配置,但必须能够处理大容量(可能每秒数百个日志操作,或更多)。
所以我问:如何优化我上面的普通文件 I/O 模板,以处理高吞吐量日志记录?我可以在这里利用“Java File I/O 的隐藏宝石”中的哪个孩子?几乎任何事情都会发生,除了,就像我说的,使用其他日志框架。基本的Logger API 需要类似于:
public class Logger {
private File logFile;
public Logger(File logFile) {
super();
setFile(logFile);
}
public void log(String message) {
???
}
}
提前致谢!
更新:如果我的Logger 使用ByteOutputStream 而不是FileWriter,那么如何正确同步我的log(String) : void 方法?
public class Logger {
private File logFile;
// Constructor, getters/setters, etc.
public void synchronized log(String message) {
FileOutputStream foutStream = new FileOutputStream(logFile);
ByteOutputStream boutStream = new BytesOutputStream(foutStream);
boutStream.write(message.getBytes(Charset.forName("utf-8")));
// etc.
}
}
【问题讨论】:
-
也许尝试使用 BufferedOutputStream 而不是 FileWriter。您可能希望将写入同步到 BufferedOutputStream。也许将缓冲区大小设置为 8MB 左右,以将磁盘搜索对吞吐量的影响降至最低。
-
感谢@tmyklebu (+1) - 我对您的声明非常感兴趣“也许将缓冲区大小设置为 8MB 左右,以将磁盘搜索对吞吐量的影响降至最低。" 你能详细说明一下吗?我想说到目前为止这个问题已经得到的所有输入,你在这里的评论是最有帮助的。如果您要做出正式的回答,我可能会给您绿色检查;-)。再次感谢!
-
观察这里的数字:磁盘寻道大约需要 8 毫秒。您的南桥可能可以将大约 1GB/s 的速度推送到您的磁盘阵列。您的磁盘阵列可能比这慢,它可能有更好的事情要做;特别是,如果您谈论的是单个磁盘,您将获得大约 100MB/s。 8ms * 1GB/s 告诉您进行磁盘查找所花费的时间可能已经花费在写入 8MB 的内容上,或者用于单个磁盘的 800k。如果您在 LAN 上使用闪存或阵列,那么这种眼光就完全消失了,因为延迟和吞吐量数字是不同的。
-
再次感谢@tmyklebu(我希望我能给你更多的支持!) - 请看看我的代码更新 - 我应该如何同步日志方法(使用
ByteOutputStream),或者有没有更好的办法?此外,ByteOutputStream似乎已经是线程安全的(每种方法) - 所以我什至需要尝试在其上添加自己的同步吗?为什么/为什么不?再次感谢! -
最大的胜利是从无缓冲到有缓冲的 I/O。提前进行 char -> byte 转换比较小。我不熟悉你的 ByteOutputStream。
标签: java performance optimization logging file-io