0

Unix FTP サーバーからファイルをダウンロードするアプリケーションがあります。正常に動作しますが、このパフォーマンスの問題があります。サイズが 1K 以下のファイルのダウンロードには平均 2084 ~ 2400 ミリ秒かかりますが、Filezilla などのアプリケーションは同じファイルを 1 秒未満でダウンロードします (各ファイルごと)。

今回は一部の平均的なユーザーには問題ないかもしれませんが、何千ものファイルをダウンロードする必要があるため、私のアプリケーションには受け入れられません。

できる限りコードを最適化します。 - コンテンツを読み取るためのキャッシュとバッファーは、クラスのコンストラクターで 1 回作成されます。- ネットワーク資格情報を 1 回作成し、ファイルをダウンロードするたびに再利用します。最初のファイルのダウンロードには 7 秒ほどかかり、その後のすべてのダウンロードは 2 秒の範囲にあるため、これが機能していることはわかっています。- バッファーのサイズを 2K から 32K に変更します。ダウンロードするファイルは 1K 未満であるため、これが役立つかどうかはわかりません。理論的には、バッファはネットワークからの 1 ラウンドですべての情報で満たされます。

おそらくネットワークとは関係ありませんが、私が書いている方法やWindowsがファイルの書き込みを処理する方法に関係していますか??

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);
}
} 
4

1 に答える 1

1

あなたの問題は、TCP クライアントで使用されるNagels アルゴリズムに関連しているように思えます。

Nagel のアルゴリズムをオフにして、SendChunkedfalse に設定することもできます。

于 2013-07-18T22:30:22.110 に答える