使用FileStream.Write函数时遇到性能问题。
我有一个控制台应用程序,用于使用StreamReader对象从文件中读取Base64字符串(~size为400 KB)。我使用Convert.FromBase64String将此字符串转换为字节数组。然后我使用FileStream对象将此字节数组写入文件。这里获得的字节数组长度为334991。
我测量了写入字节数组所花费的时间 - 它大约是 0.116秒。
为了好玩,我使用ASCIIEncoding.GetBytes函数从相同的Base64编码字符串中获取了字节数组(尽管我知道这不会给出正确的DECODED输出 - 我只是想尝试一下)。我使用FileStream对象将此字节数组写入文件。这里获得的字节数组长度为458414。
我测量了使用这种方法编写字节数组所花费的时间 - 它大约 0.008秒。
以下是示例代码:
class Program
{
static void Main(string[] args)
{
Stopwatch stopWatch = new Stopwatch();
TimeSpan executionTime;
StreamReader sr = new StreamReader("foo.txt");
string sampleString = sr.ReadToEnd();
sr.Close();
////1. Convert to bytes using Base64 Decoder (The real output!)
//byte[] binaryData = Convert.FromBase64String(sampleString);
//2. Convert to bytes using AsciiEncoding (Just for Fun!)
byte[] binaryData = new System.Text.ASCIIEncoding().GetBytes(sampleString);
Console.WriteLine("Byte Length: " + binaryData.Length);
stopWatch.Start();
FileStream fs = new FileStream("bar.txt", FileMode.Create, FileAccess.Write);
fs.Write(binaryData, 0, binaryData.Length);
fs.Flush();
fs.Close();
stopWatch.Stop();
executionTime = stopWatch.Elapsed;
Console.WriteLine("FileStream Write - Total Execution Time: " + executionTime.TotalSeconds.ToString());
Console.Read();
}
}
我对包含Base64编码字符串的大约5000个文件进行了测试,并且写入这两种字节数组所花费的时间差异几乎是10倍(使用 real编写字节数组的那个) 解码需要更多时间)。
使用Convert.FromBase64String获得的字节数组的长度小于使用ASCIIEncoding.GetBytes函数获得的字节数组的长度。
我想知道我要做的就是使用FileStream对象写一堆字节。那么为什么在将字节数组写入磁盘时会出现如此剧烈的性能差异(w.r.t. time)?
或者我做错了什么?请指教。
答案 0 :(得分:1)
对于初学者来说,DateTime的分辨率很低(iirc为0.018秒)。所以最好使用秒表课程。
现在这并没有完全解释差异,但你可能会得到更好的数字。
答案 1 :(得分:1)
我给另一个问题提出了一些类似的建议,请查看 来自MS Research的{{3}}工具和参考资料。
他们会帮助您解决任何潜在的I / O问题,或者至少了解它们。
此外,您应该注意CLR these周围的问题。特别是在使用数组时(超过~80kb的任何东西都有次优的托管堆交互,请在同一过程中运行5000次)。
但是,真的,在再次看之后,我认为这些与你的引理没有密切关系。我在分析器中运行此代码,它只是显示转换。 Base64 正在消耗所有周期。
其他一些事情,在测试代码中,您应该总是连续运行2次以上的测试,抖动将有可能影响运行时负载。这可能导致执行时间的这种变化,这是惊人的。现在我认为你应该重新评估你的测试工具,试图考虑抖动和可能的大对象堆效应。 (将其中一个例程放在另一个例程之前......)。
答案 2 :(得分:1)
我认为您的代码中的主要问题是您正在尝试将卷心菜与胡萝卜(法语表达式)进行比较:
Convert.FromBase64String和ASCIIEncoding()。GetBytes根本不会做同样的事情。
只是尝试使用任何文本文件作为程序的输入,并且在使用ASCIIEncoding正常运行时,它将在FromBase64上失败。
现在有关性能影响的解释:
ASCIIEncoding()。GetBytes只是从你的文件中取一个字符并将其转换成一个字节(这是相当直接的:没有什么可做的)。例如,它会将'A'转换为0x41,将'Z'转换为0x5A ......
对于Convert.FromBase64String,这是另一个故事。它实际上是将“base64编码的字符串”转换为字节数组。一个base64字符串是 - 比如说 - “二进制数据的可打印表示。更好的是,它是二进制数据的”文本“表示,允许它例如通过互联网线发送。邮件中的图像是base64编码的,因为邮件协议是基于文本的。因此,将back64转发到字节的过程根本不简单;因此性能受到影响。
Fyi,base64字符串看起来应该是这样的:
SABlAGwAbABvAHcAIABXAG8AcgBsAGQAIQA =
转换为“Hello World!”不是直接的,不是吗?
以下是有关base64格式的一些信息:http://en.wikipedia.org/wiki/Base64
希望这有帮助
答案 3 :(得分:0)