Transmission: [amélioration] Soyez plus intelligent lors du déplacement de fichiers

Créé le 14 juil. 2019  ·  8Commentaires  ·  Source: transmission/transmission

Pour Windows, tr_sys_path_rename pourrait utiliser le drapeau MOVEFILE_COPY_ALLOWED plutôt que sa propre boucle "read&copy" intégrée à partir de util.c:tr_moveFile

Ensuite, la version Linux pourrait utiliser le copy_file_range plus moderne au lieu de boucler sur chacun.

peut-être quelque chose comme ça :

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

Et peut-être un :

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

Commentaire le plus utile

+1 pour rendre les déplacements de données asynchrones. Déplacer de gros torrents entre les systèmes de fichiers verrouille l'ensemble de l'application .

Tous les 8 commentaires

Ensuite, la version Linux pourrait utiliser le copy_file_range plus moderne au lieu de boucler sur chacun.

Cela ne peut pas se faire en un seul appel (ou en boucle simple) :

       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)

Idéalement, nous devrions nous assurer que les verrous sont corrects et utiliser sendfile() dans un thread séparé.

C'est à peu près le même que le code "déplacer le fichier" actuel lorsque
rename échoue. Cela ne garde pas non plus les sections clairsemées, donc je n'ai pas
considérez qu'il s'agit d'un problème lors de son remplacement.

Le dimanche 14 juillet 2019 à 22h41, andreygursky [email protected] a écrit :
>

Ensuite, la version Linux pourrait utiliser le copy_file_range plus moderne au lieu de boucler sur chacun.

Cela ne peut pas se faire en un seul appel (ou en boucle simple) :

   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)

Idéalement, nous devrions nous assurer que les verrous sont corrects et utiliser sendfile() dans un thread séparé.

-
Vous recevez ceci parce que vous avez créé le fil.
Répondez directement à cet e-mail, affichez-le sur GitHub ou coupez le fil de discussion.

Cela ne garde pas non plus les sections clairsemées, donc je n'ai pas
considérez qu'il s'agit d'un problème lors de son remplacement.

Et il manque une préallocation pour les fichiers normaux.

Ouais. Ça aussi. Le mauvais comportement actuel de "déplacer le fichier" est suffisant pour provoquer des charges absurdes dans certaines configurations. Si possible, il semble que la solution de secours dans la glibc copy_file_range soit également une meilleure implémentation.

J'ai joué avec ça. Il est difficile d'y parvenir d'une manière multiplateforme : il ne semble pas y avoir d'interface POSIX pour une copie dans le noyau. Mais je pense qu'il vaut la peine d'avoir un boîtier spécial pour chaque système d'exploitation, car à mesure que les systèmes de fichiers deviennent plus efficaces au niveau des copies, nous souhaitons accéder automatiquement à ces fonctionnalités.

J'ai une implémentation de base opérationnelle sur MacOSX et FreeBSD, mais j'ai besoin de configurer quelques systèmes supplémentaires pour la tester.

Je pense que ce travail est orthogonal au déplacement asynchrone du fichier. L'un ne doit pas gêner l'autre. Pour les projets de volontariat, la dérive de la portée est l'ennemi de la productivité.

Les changements sont ici : https://github.com/transmission/transmission/compare/master...RobCrowston :kernelcopy-wip

En bref, je crée une nouvelle abstraction appelée tr_sys_path_copy(). (J'ai opté pour une copie au lieu d'un déplacement, car lorsque nous en faisons une opération asynchrone, il peut être nécessaire de conserver le fichier d'origine pendant une période indéterminée une fois la copie terminée pour fermer les descripteurs de fichiers dans d'autres threads.)

Jusqu'à présent, j'ai compilé et exécuté le nouveau test (transmission-test-copy) sur MacOS 10.15.1, Windows Server 2016, Linux 5.0 (Ubuntu 19.05), Linux 5.3 (Arch 2019-12-03), FreeBSD 12.1 (utilise le repli de l'espace utilisateur) et FreeBSD 13. Dans chaque cas, j'ai vérifié avec un débogueur que nous effectuons les appels système appropriés. Malheureusement, je n'ai pas pu obtenir le code pour construire sur OpenBSD 6.5, NetBSD 8.1 ou Solaris 10 en raison de problèmes de libevent non liés, mais je ne suis pas sûr que ce soient des plates-formes prises en charge pour la transmission de lib. En tout état de cause, ce changement ne devrait pas affecter ces plateformes.

Reste à faire :

  • Testez sur un noyau Windows plus ancien. Besoin de configurer un environnement de développement de machine virtuelle pour cela.
  • Testez la copie entre volumes (puisque c'est ce qui nous intéresse). Je ne sais pas comment faire cela en tant que test automatisé cependant.
  • Testez le fichier tr_sys_path_copy() pour un fichier raisonnablement volumineux (> 100 Go). Cela ne peut probablement pas être fait comme un test automatisé.
  • Testez in situ au lieu de simplement tester tr_sys_path_copy() de manière isolée.
  • Remplacez l'un de mes serveurs bit torrent par ce code pendant un moment, voyez comment il se comporte dans le monde réel.

Commentaires bienvenus.

+1 pour rendre les déplacements de données asynchrones. Déplacer de gros torrents entre les systèmes de fichiers verrouille l'ensemble de l'application .

Cette page vous a été utile?
0 / 5 - 0 notes