我有一个令人费解的情况,我需要一个专家意见,以解释下面解释的现象的原因。几周前,我进行了一次名为“Java开发人员概述”的会议,作为其中的一部分,我编写了一个快速的C#(3.5框架)类来读取文件并逐行写入另一个文件(在迭代中)。由于我的观众是java开发人员,我在java类中使用相同的代码进行并排比较。但是,当我在同一台机器上运行这些类时,令我惊讶的是,java代码的运行速度始终是C#代码的两倍。我已尝试在C#代码中进行许多优化以缩小差距,但无法成功。必须有一个解释,我正在寻找可以解释原因的人。我附上了两个类的源代码供您参考。
public class ReadWriteTextFile {
static public String getContents(File aFile, String OutPutFileName) {
StringBuilder contents = new StringBuilder();
try {
BufferedReader input = new BufferedReader(new FileReader(aFile));
FileReader x = new FileReader(aFile);
try {
String line = null;
while (( line = input.readLine()) != null){
setContents(OutPutFileName, line + System.getProperty("line.separator"));
}
}
finally {
input.close();
}
}
catch (IOException ex){
ex.printStackTrace();
}
return contents.toString();
}
static public void setContents(String FileName, String aContents)
throws FileNotFoundException, IOException {
try {
FileWriter fstream = new FileWriter(FileName, true);
BufferedWriter out = new BufferedWriter(fstream);
out.write(aContents);
out.close();
} catch (Exception xe) {
xe.printStackTrace();
}
}
public static void main (String[] aArguments) throws IOException {
System.out.println(getDateTime() + ": Started");
File testFile = new File("C:\\temp\\blah.txt");
String testFile2 = "C:\\temp\\blahblah.txt";
for(int i=0; i<100; i++){
getContents(testFile, testFile2);
}
System.out.println(getDateTime() + ": Ended");
}
private synchronized static String getDateTime() {
DateFormat dateFormat = new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss");
Date date = new Date();
return dateFormat.format(date);
}
}
class ReadWriteTextFile
{
static void Main(string[] args)
{
System.Diagnostics.Trace.WriteLine(getDateTime() + ": Started");
String testFile = "C:\\temp\\blah.txt";
String testFile2 = "C:\\temp\\blahblah.txt";
for(int i=0; i<100; i++){
getContents(testFile, testFile2);
}
System.Diagnostics.Trace.WriteLine(getDateTime() + ": Ended");
}
static public void getContents(String sourceFile, String targetFile) {
try {
using (StreamReader r = File.OpenText(sourceFile))
{
String line;
while ((line = r.ReadLine()) != null)
{
setContents(targetFile, line);
}
r.Close();
}
}
catch (IOException ex){
Console.WriteLine(ex.StackTrace);
}
}
static public void setContents(String targetFile, String aContents)
{
try {
//FileStream fsO = new FileStream(targetFile, FileMode.Append);
//StreamWriter w = new StreamWriter(fsO);
FileStream fs = new FileStream(targetFile, FileMode.Append,
FileAccess.Write, FileShare.None);
using (StreamWriter w = new StreamWriter(fs))
{
w.WriteLine(aContents + "\n");
}
} catch (Exception xe) {
Console.WriteLine(xe.StackTrace);
}
}
private static String getDateTime() {
DateTime dt = DateTime.Now;
return dt.ToString("yyyy/MM/dd HH:mm:ss");
}
}
答案 0 :(得分:8)
首先,在Java中,您使用的是平台的默认编码。这可能是一个固定的“每字符单字节”编码,这显然比使用UTF-8简单,而.NET默认使用它。
此外,您在.NET中编写两个换行符,而在Java中只编写一个。
要检查的一件事是你是CPU限制还是IO绑定。我期待这是IO限制,但我现在肯定感到惊讶。
最后,您应该在重新启动后运行每个测试,以尽可能从等式中删除磁盘缓存。
答案 1 :(得分:3)
我在这里看不到任何代码问题。一些可能性:您可能在调试模式下运行C#代码?文件缓存存在问题。 C#数据文件在严重碎片化的磁盘区域上运行。对于这样一个简单的C#程序,我不希望半速。
编辑:我在10439字节的blah.txt上尝试了两个版本。生成的文件长度为1 043 900字节。
C#(CTRL + F5)时间为18秒
C#(F5)时间为22秒
Java时间是17秒。
两个应用程序都占用了大约40%的CPU时间,其中一半是内核时间。
<强> EDIT2:强> CPU绑定是由于代码不断打开,关闭和写入小块数据。这会导致许多托管本机和用户内核模式转换。
我的系统规格:Core 2 Duo 2.4GHz,2 GB 800MHz RAM,WinXP SP3
答案 2 :(得分:2)
基准测试的缓慢部分看起来好像是单个文件重复打开,装饰,小写并再次关闭的位置。不是一个有用的基准。显而易见的差异是缓冲区有多大(单次写入,实际上并不需要任何),以及生成的文件是否同步到光盘。