我正在使用Windows Azure虛擬機和D2實例(新SSD實例)上的Windows Server 2012數據中心解壓縮1.8 GB zip文件,該文件包含51 GB XML文件解壓縮。不用說,這個過程可以通過快速磁盤加速,這就是我測試D2實例的原因。Azure VM上SSD磁盤性能下降
但是,我得到的磁盤性能並不令人印象深刻,並且不符合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虛擬機上運行它時,我會在前10秒左右獲得良好的性能(100-150 MB/s),然後降至20 MB/s左右並保持在那裏,並定期進一步下降到8-9 MB /秒。它沒有改善。整個解壓縮過程大約需要42分鐘,而我的本地計算機可以在10分鐘左右完成。
這是怎麼回事?爲什麼磁盤性能如此糟糕?是我的應用程序做錯了什麼?
本地和Azure虛擬機上的zip文件都放置在SSD磁盤上,並且該文件被提取到同一個SSD磁盤。 (關於Azure的VM,我使用的是臨時存儲驅動器,因爲這是SSD)
下面是來自Azure的VM提取文件截圖:
注意性能是如何在大開始,但隨後突然下降,並沒有恢復。我的猜測是有一些緩存正在進行,然後當緩存未命中時性能下降。
這裏是我的本地機器中提取文件截圖:
性能變化了一點,但仍高於160 MB /秒。
這是我在兩臺機器上使用的相同的二進制文件,它是爲x64(非AnyCPU)編譯的。 我機器中的SSD磁盤大約有1.5年的歷史,所以它不是什麼新的或特殊的東西。 我不認爲這是一個內存問題,因爲D2實例有大約7 GB的RAM,而我的本地機器有12 GB。但7 GB應該足夠了,不是嗎?
有沒有人對發生了什麼有任何線索?
非常感謝您的幫助。
新增
我試圖監視內存的使用情況,而這樣做的提取,我注意到的是,當應用程序開始,修改內存量爆炸,只是不停地增長。雖然這樣做,我的應用程序報告的性能很好(100+ MB/s)。然後修改後的內存開始縮小(據我所知,這意味着內存正在刷新到磁盤),性能立即下降到20-30 MB/s。有幾次,性能實際上有所提高,我可以看到,當它做到時,修改後的內存使用率增加了。過了一會兒,表現再次下降,我可以看到修改後的內存量減少了。所以看起來數據刷新到磁盤導致我的應用程序性能問題。但爲什麼?我該如何解決這個問題?
新增
好了,所以我想大衛的建議,並運行在一個D14實例的應用程序,而現在我得到了真正優秀的磁盤性能,穩定180-200 + MB /秒。我將繼續測試不同大小的實例,看看我可以走多低,仍然可以獲得良好的磁盤性能。就像我用D2實例一樣,在具有本地SSD磁盤的虛擬機上,我感覺如此糟糕的磁盤性能似乎仍然很奇怪。
這應該被張貼到ServerFault,而不是計算器。 – 2014-09-25 11:51:34
你可能是對的。我在這裏發佈它是因爲我懷疑是我的應用程序是問題,而不是服務器上的任何硬件或設置。 – 2014-09-25 11:55:49
嗯......我想,如果你的代碼在本地工作正常,但在D級虛擬機中運行時卻顯示速度惡化問題,這是虛擬機特性的特定情況。順便說一下:在您調查時,請嘗試使用最大(D14)虛擬機進行測試,以消除鄰居問題。 – 2014-09-25 12:06:22