Transmission: 【改善】ファイル移動時のスマート化

作成日 2019年07月14日  ·  8コメント  ·  ソース: transmission/transmission

Windowsの場合、 tr_sys_path_renameフラグを使用することができますMOVEFILE_COPY_ALLOWEDそれは自分の組み込みのだから、 "読み取り&コピー"ループではなく、 util.c:tr_moveFile

次に、Linuxバージョンは、それぞれをループする代わりに、より新しいcopy_file_range使用できます。

おそらくこのようなもの:

size_t tr_sys_file_copy(tr_sys_file_t infile, tr_sys_file_t outfile, size_t len, tr_error** error )
{
        TR_ASSERT(outfile != NULL);
        TR_ASSERT(infile != NULL);
        bool ret = false;
        unsigned int flags = 0;
        size_t res;

        res = copy_file_range(infile, NULL, outfile, NULL, &len, flags);
        if (res) {
                return res;
        }      
        else {
                set_system_error(error, errno);  
                return res;
        }
}

そして多分:

tr_sys_file_copy_fallback(tr_sys_file_t infile, tr_sys_file_t outfile, size_t len,  tr_error** error ) {
    TR_ASSERT(outfile != NULL);
    TR_ASSERT(infile != NULL);

    uint64_t bytesLeft = len;
    size_t const buflen = 1024 * 128; /* 128 KiB buffer */
    tr_sys_path_info info;
    while (bytesLeft > 0)
    {
        uint64_t const bytesThisPass = MIN(bytesLeft, buflen);
        uint64_t numRead;
        uint64_t bytesWritten;

        if (!tr_sys_file_read(infile, buf, bytesThisPass, &numRead, error))
        {
            break;
        }

        if (!tr_sys_file_write(outfile, buf, numRead, &bytesWritten, error))
        {
            break;
        }

        TR_ASSERT(numRead == bytesWritten);
        TR_ASSERT(bytesWritten <= bytesLeft);
        bytesLeft -= bytesWritten;
    }
    return bytesLeft;
}
core enhancement pr welcome

最も参考になるコメント

データを非同期に移動させるための+1。 ファイルシステム間で大きなトレントを移動すると、アプリケーション全体がロックされます

全てのコメント8件

次に、Linuxバージョンは、それぞれをループする代わりに、より新しいcopy_file_rangeを使用できます。

これは、1回の呼び出しだけで(または単純なループで)実行することはできません。

       If  file_in  is  a  sparse  file, then copy_file_range() may expand any
       holes existing in the requested range.  Users may benefit from  calling
       copy_file_range()  in  a  loop,  and  using  the lseek(2) SEEK_DATA and
       SEEK_HOLE operations to find the locations of data segments.

(man copy_file_range)

理想的には、適切にロックし、別のスレッドでsendfile()を使用する必要があります。

これは、現在の「ファイルの移動」コードとほとんど同じです。
rename失敗します。 それもまばらなセクションを保持しないので、私はしませんでした
それを交換するときに問題を考慮してください。

22:41の日、2019年7月14日にはandreygursky [email protected]書きました:
>>

次に、Linuxバージョンは、それぞれをループする代わりに、より新しいcopy_file_rangeを使用できます。

これは、1回の呼び出しだけで(または単純なループで)実行することはできません。

   If  file_in  is  a  sparse  file, then copy_file_range() may expand any
   holes existing in the requested range.  Users may benefit from  calling
   copy_file_range()  in  a  loop,  and  using  the lseek(2) SEEK_DATA and
   SEEK_HOLE operations to find the locations of data segments.

(man copy_file_range)

理想的には、適切にロックし、別のスレッドでsendfile()を使用する必要があります。


スレッドを作成したため、これを受け取っています。
このメールに直接返信するか、GitHubで表示するか、スレッドをミュートしてください。

それもまばらなセクションを保持しないので、私はしませんでした
それを交換するときに問題を考慮してください。

また、通常のファイルの事前割り当てがありません。

うん。 それも。 「ファイルの移動」の現在の悪い動作は、いくつかのセットアップでばかげた負荷を引き起こすのに十分です。 可能であれば、glibccopy_file_rangeのフォールバックソリューションもより良い実装であるように思われます。

私はこれで遊んだことがあります。 クロスプラットフォームの方法で正しく理解するのは難しいです。カーネル内コピー用のPOSIXインターフェースがないようです。 しかし、ファイルシステムがコピーでより効率的になるにつれて、それらの機能に自動的にアクセスしたいので、オペレーティングシステムごとに特別なケーシングをする価値があると思います。

私はMacOSXとFreeBSDで基本的な実装を実行していますが、それをテストするためにさらにいくつかのシステムをセットアップする必要があります。

この作業は、ファイルを非同期に移動させることと直交していると思います。 一方が他方の邪魔をしてはいけません。 ボランティアプロジェクトの場合、スコープクリープは生産性の敵です。

変更点は次のとおりです: https ://github.com/transmission/transmission/compare/master ... RobCrowston:kernelcopy-wip

簡単に言うと、tr_sys_path_copy()という新しい抽象化を作成します。 (これを非同期操作にすると、他のスレッドのファイルハンドルを閉じるために、コピーが完了した後、元のファイルを一定期間保持する必要がある場合があるため、移動ではなくコピーを使用しました。)

今日まで、私はMacOS 10.15.1、Windows Server 2016、Linux 5.0(Ubuntu 19.05)、Linux 5.3(Arch 2019-12-03)、FreeBSD 12.1で新しいテスト(transmission-test-copy)をコンパイルして実行しました。 (ユーザースペースフォールバックを使用)、およびFreeBSD 13.いずれの場合も、適切なシステム呼び出しを行っていることをデバッガーで確認しました。 残念ながら、関係のないlibeventの問題が原因で、OpenBSD 6.5、NetBSD 8.1、またはSolaris 10でコードをビルドすることができませんでしたが、これらがlibtransmissionでサポートされているプラ​​ットフォームであるかどうかはわかりません。 いずれにせよ、この変更はそれらのプラットフォームに影響を与えるべきではありません。

まだやるべきこと:

  • 古いWindowsカーネルでテストします。 そのために仮想マシン開発環境を構成する必要があります。
  • クロスボリュームコピーをテストします(それが私たちが気にしていることだからです)。 ただし、自動テストとしてそれを行う方法はわかりません。
  • ファイルtr_sys_path_copy()をテストして、適度に大きなファイル(> 100 GB)を探します。 おそらく、自動テストとして実行することはできません。
  • tr_sys_path_copy()を単独でテストするのではなく、その場でテストします。
  • しばらくの間、私のビットトレントサーバーの1つをこのコードに置き換えて、実際の世界でどのように動作するかを確認してください。

フィードバックを歓迎します。

データを非同期に移動させるための+1。 ファイルシステム間で大きなトレントを移動すると、アプリケーション全体がロックされます

このページは役に立ちましたか?
0 / 5 - 0 評価