2013-07-18 33 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