我在D2实例(新的SSD实例)上使用带有Windows Server 2012 Datacenter的Windows Azure虚拟机来解压缩包含解压缩的51 GB XML文件的1.8 GB zip文件。毋庸置疑,这个过程可以用快速磁盘加速,这就是我测试D2实例的原因。
然而,我获得的磁盘性能并不令人印象深刻,并且不符合SSD磁盘的性能预期,因为我的写入速度只有20-30 MB / s左右平均而言。
我用来解压缩文件的程序是为此目的而开发的自定义.NET控制台应用程序。源代码如下:
static void Main(string[] args)
{
if (args.Count() < 1)
{
Console.WriteLine("Missing file parameter.");
return;
}
string zipFilePath = args.First();
if (!File.Exists(zipFilePath))
{
Console.WriteLine("File does not exist.");
return;
}
string targetPath = Path.GetDirectoryName(zipFilePath);
var start = DateTime.Now;
Console.WriteLine("Starting extraction (" + start.ToLongTimeString() + ")");
var zipFile = new ZipFile(zipFilePath);
zipFile.UseZip64 = UseZip64.On;
foreach (ZipEntry zipEntry in zipFile)
{
byte[] buffer = new byte[4096]; // 4K is optimum
Stream zipStream = zipFile.GetInputStream(zipEntry);
String entryFileName = zipEntry.Name;
Console.WriteLine("Extracting " + entryFileName + " ...");
String fullZipToPath = Path.Combine(targetPath, entryFileName);
string directoryName = Path.GetDirectoryName(fullZipToPath);
if (directoryName.Length > 0)
{
Directory.CreateDirectory(directoryName);
}
// Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
// of the file, but does not waste memory.
// The "using" will close the stream even if an exception occurs.
long dataWritten = 0;
long dataWrittenSinceLastOutput = 0;
const long dataOutputThreshold = 100 * 1024 * 1024; // 100 mb
var timer = System.Diagnostics.Stopwatch.StartNew();
using (FileStream streamWriter = File.Create(fullZipToPath))
{
bool moreDataAvailable = true;
while (moreDataAvailable)
{
int count = zipStream.Read(buffer, 0, buffer.Length);
if (count > 0)
{
streamWriter.Write(buffer, 0, count);
dataWritten += count;
dataWrittenSinceLastOutput += count;
if (dataWrittenSinceLastOutput > dataOutputThreshold)
{
timer.Stop();
double megabytesPerSecond = (dataWrittenSinceLastOutput / timer.Elapsed.TotalSeconds) / 1024 / 1024;
Console.WriteLine(dataWritten.ToString("#,0") + " bytes written (" + megabytesPerSecond.ToString("#,0.##") + " MB/s)");
dataWrittenSinceLastOutput = 0;
timer.Restart();
}
}
else
{
streamWriter.Flush();
moreDataAvailable = false;
}
}
Console.WriteLine(dataWritten.ToString("#,0") + " bytes written");
}
}
zipFile.IsStreamOwner = true; // Makes close also shut the underlying stream
zipFile.Close(); // Ensure we release resources
Console.WriteLine("Done. (Time taken: " + (DateTime.Now - start).ToString() +")");
Console.ReadKey();
}
在我自己的带有SSD磁盘的计算机上本地运行此应用程序时,我在整个解压缩过程中不断获得180-200 MB / s的性能。但是当我在Azure VM上运行它时,我在前10秒左右获得了良好的性能(100-150 MB / s),然后它下降到大约20 MB / s并保持在那里,并定期进一步下降到8-9 MB /秒。它没有改善。整个解压缩过程在Azure VM上大约需要42分钟,而我的本地计算机可以在大约10分钟内完成。
这里发生了什么?为什么磁盘性能如此糟糕?是我的应用程序做错了吗?
在本地和Azure VM上,zip文件都放在SSD磁盘上,文件被解压缩到同一个SSD磁盘上。 (在Azure VM上,我使用临时存储驱动器,因为那是SSD)
以下是Azure VM提取文件的屏幕截图:
注意一开始表现如何,但突然下降并且无法恢复。我的猜测是有一些缓存正在进行,然后当缓存未命中时性能下降。
以下是本地计算机提取文件的屏幕截图:
性能略有不同但仍高于160 MB / s。
它是我在两台机器上使用的二进制文件,它是为x64(非AnyCPU)编译的。 我机器上的SSD磁盘大约有1.5年的历史,所以它不是什么新东西或特殊的东西。 我也不认为这是一个内存问题,因为D2实例有大约7 GB的RAM,而我的本地机器有12 GB。但7 GB就足够了,不应该吗?
有没有人知道发生了什么?
非常感谢您的帮助。
加
我尝试在进行提取时监视内存使用情况,我注意到的是,当应用程序启动时,修改内存的数量爆炸并且不断增长。虽然它这样做,我的应用程序报告的性能很好(100 + MB / s)。然后修改后的内存开始缩小(据我所知,这意味着内存被刷新到磁盘),性能立即下降到20-30 MB / s。有几次,性能实际上有所改善,我可以看到,当它发生时,修改后的内存使用量增加了。片刻之后,性能再次下降,我可以看到修改后的内存量减少了。因此,似乎将数据刷新到磁盘会导致我的应用程序性能问题。但为什么?我该如何解决这个问题?
加
好的,所以我尝试了David的建议并在D14实例上运行应用程序,现在我的磁盘性能非常好,稳定在180-200 + MB / s。我将继续测试不同大小的实例,看看我能走多远,仍能获得良好的磁盘性能。我在使用本地SSD磁盘的虚拟机上遇到如此糟糕的磁盘性能仍然只是看起来很奇怪。正如我使用D2实例一样。
答案 0 :(得分:0)
文件位于何处? C:或D: D系列VM只有临时驱动器D是SSD。所有其他磁盘都是普通驱动器。
如果您需要将附加磁盘作为其他驱动器,那么您需要使用G系列VM预览的高级存储帐户。
谢谢, 苏博德