2013-07-18 35 views
0

我有一個應用程序從Unix FTP服務器下載文件。它工作正常,只是有這樣的性能問題:大小爲< = 1K的文件平均需要2084​​到2400毫秒才能下載,而像Filezilla這樣的應用程序在不到1秒(每個文件)下載相同的文件。c#ftpwebrequest性能

也許這次對於一些普通用戶來說可以,但是對於我的應用程序來說是不可接受的,因爲我需要下載幾千個文件。

我儘可能地優化了代碼: - 讀取內容的緩存和緩衝區在類的構造函數中創建一次。 - 我創建1次網絡憑證,並在每次下載文件時重新使用。我知道這是工作,因爲第一個文件需要7s下載,並且所有後續下載都在2s範圍內。 - 我將緩衝區的大小從2K改爲32K。我不知道這是否會有所幫助,因爲我下載的文件小於1K,所以理論上緩衝區將從網絡中填充所有信息。

也許與網絡無關,但是對於Im寫入和/或窗口處理寫入文件的方式?

有人可以給我一些關於如何減少類似filezilla的時間? 我需要減少時間,否則我的ftp將每天24小時運行3天,以完成其任務:( 非常感謝提前。 代碼在這裏:它不完整,它只顯示下載部分。

//Create this on the constructor of my class 
downloadCache = new MemoryStream(2097152); 
downloadBuffer = new byte[32768]; 

public bool downloadFile(string pRemote, string pLocal, out long donwloadTime) 
{ 
FtpWebResponse response = null; 
Stream responseStream = null; 

try 
{ 
    Stopwatch fileDownloadTime = new Stopwatch(); 
    donwloadTime = 0; 
    fileDownloadTime.Start(); 

    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(pRemote); 
    request.Method = WebRequestMethods.Ftp.DownloadFile; 
    request.UseBinary = false; 
    request.AuthenticationLevel = AuthenticationLevel.None; 
    request.EnableSsl = false; 
    request.Proxy = null; 
    //I created the credentials 1 time and re-use for every file I need to download 
    request.Credentials = this.manager.ftpCredentials; 

    response = (FtpWebResponse)request.GetResponse(); 
    responseStream = response.GetResponseStream(); 

    downloadCache.Seek(0, SeekOrigin.Begin); 
    int bytesSize = 0; 
    int cachedSize = 0; 

    //create always empty file. Need this because WriteCacheToFile just append the file 
    using (FileStream fileStream = new FileStream(pLocal, FileMode.Create)) { }; 

    // Download the file until the download is completed. 
    while (true) 
    { 
     bytesSize = responseStream.Read(downloadBuffer, 0, downloadBuffer.Length); 
     if (bytesSize == 0 || 2097152 < cachedSize + bytesSize) 
     { 
      WriteCacheToFile(pLocal, cachedSize); 
      if (bytesSize == 0) 
      { 
       break; 
      } 
      downloadCache.Seek(0, SeekOrigin.Begin); 
      cachedSize = 0; 
     } 
     downloadCache.Write(downloadBuffer, 0, bytesSize); 
     cachedSize += bytesSize; 
    } 

    fileDownloadTime.Stop(); 
    donwloadTime = fileDownloadTime.ElapsedMilliseconds; 

    //file downloaded OK 
    return true; 
} 
catch (Exception ex) 
{ 
    return false; 
} 
finally 
{ 
    if (response != null) 
    { 
     response.Close(); 
    } 

    if (responseStream != null) 
    { 
     responseStream.Close(); 
    } 
} 
} 

private void WriteCacheToFile(string downloadPath, int cachedSize) 
{ 
using (FileStream fileStream = new FileStream(downloadPath, FileMode.Append)) 
{ 
    byte[] cacheContent = new byte[cachedSize]; 
    downloadCache.Seek(0, SeekOrigin.Begin); 
    downloadCache.Read(cacheContent, 0, cachedSize); 
    fileStream.Write(cacheContent, 0, cachedSize); 
} 
} 
+0

我忘了說:。即時通訊使用多個線程同時下載多個文件。 – user2232787

回答

1

的聲音,我的問題是有關在TCP客戶機使用Nagels algorithm

您可以嘗試打開格爾的算法關閉,也可以設置SendChunked

+0

謝謝sean717。我閱讀了關於Nagels算法的信息。我還閱讀了關於如何關閉它的msdn文檔,並說它將Socket.NoDelay屬性設置爲true或false。但是,這是在Socket級別,而我的應用程序使用更高的類:FtpWebRequest。我如何從我的代碼訪問NoDelay屬性? – user2232787

+0

嘿,請看看[這個問題](http://stackoverflow.com/questions/2400949/what-might-cause-the-big-overhead-of-making-a-httpwebrequest-call)。基本上FtpWebRequest派生自System.Net.WebRequest,您可以從中關閉Nagel。 – sean717

+0

我添加了以下幾行:ServicePoint spTemp = request.ServicePoint; spTemp.UseNagleAlgorithm = false;我需要測試它是否有效,因爲[鏈接](http://msdn.microsoft.com/zh-cn/library/system.net.servicepointmanager.usenaglealgorithm.aspx)表示「該屬性的值並不影響現有的ServicePoint對象,只有在更改後創建的新服務點受到影響「 – user2232787