Transmission: [melhoria] Seja mais inteligente ao mover arquivos

Criado em 14 jul. 2019  ·  8Comentários  ·  Fonte: transmission/transmission

Para Windows, tr_sys_path_rename poderia usar a sinalização MOVEFILE_COPY_ALLOWED vez de seu próprio loop "ler e copiar" embutido de util.c:tr_moveFile

Então, a versão do Linux poderia usar o mais moderno copy_file_range vez de fazer um loop sobre cada um.

talvez algo assim:

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

E talvez um:

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

Comentários muito úteis

1 para tornar as movimentações de dados assíncronas. Mover torrents grandes entre sistemas de arquivos bloqueia todo o aplicativo .

Todos 8 comentários

Então, a versão do Linux poderia usar o copy_file_range mais moderno em vez de fazer um loop sobre cada um.

Isso não pode ser feito apenas com uma chamada (ou em loop simples):

       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)

Idealmente, devemos garantir os bloqueios adequados e usar sendfile () em uma thread separada.

É praticamente o mesmo que o código atual de "mover arquivo" quando
rename falha. Isso também não mantém seções esparsas, então eu não
considere isso um problema ao substituí-lo.

No domingo, 14 de julho de 2019 às 22h41, andreygursky [email protected] escreveu:
>

Então, a versão do Linux poderia usar o copy_file_range mais moderno em vez de fazer um loop sobre cada um.

Isso não pode ser feito apenas com uma chamada (ou em loop simples):

   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)

Idealmente, devemos garantir os bloqueios adequados e usar sendfile () em uma thread separada.

-
Você está recebendo isto porque é o autor do tópico.
Responda a este e-mail diretamente, visualize-o no GitHub ou ignore a conversa.

Isso também não mantém seções esparsas, então eu não
considere isso um problema ao substituí-lo.

E está faltando pré-alocação para arquivos normais.

Sim. Isso também. O atual mau comportamento de "mover arquivo" é suficiente para causar cargas absurdas em algumas configurações. Se possível, parece que a solução de fallback em glibc copy_file_range é uma implementação melhor também.

Eu joguei com isso. É difícil acertar em uma plataforma cruzada: não parece haver nenhuma interface POSIX para uma cópia dentro do kernel. Mas acho que vale a pena usar um invólucro especial para cada sistema operacional porque, à medida que os sistemas de arquivos se tornam mais eficientes nas cópias, queremos acessar esses recursos automaticamente.

Tenho uma implementação básica instalada e em execução no MacOSX e no FreeBSD, mas preciso configurar mais alguns sistemas para testá-la.

Acho que este trabalho é ortogonal para fazer o movimento do arquivo de forma assíncrona. Um não deve atrapalhar o outro. Para projetos voluntários, o aumento do escopo é inimigo da produtividade.

As mudanças estão aqui: https://github.com/transmission/transmission/compare/master...RobCrowston : kernelcopy-wip

Em resumo, crio uma nova abstração chamada tr_sys_path_copy (). (Fiz uma cópia em vez de uma mudança porque, quando tornamos esta operação assíncrona, pode ser necessário manter o arquivo original por um período indeterminado de tempo após a cópia ser concluída para fechar os identificadores de arquivo em outros threads.)

Até agora, compilei e executei o novo teste (transmissão-teste-cópia) no MacOS 10.15.1, Windows Server 2016, Linux 5.0 (Ubuntu 19.05), Linux 5.3 (Arch 03-12-2019), FreeBSD 12.1 (usa fallback de espaço de usuário) e FreeBSD 13. Em cada caso, verifiquei com um depurador se estamos fazendo as chamadas de sistema apropriadas. Infelizmente, não consegui obter o código para compilar no OpenBSD 6.5, NetBSD 8.1 ou Solaris 10 por causa de alguns problemas não relacionados do libevent, mas não tenho mais certeza de que essas plataformas sejam mais suportadas para libtransmission. Em qualquer caso, esta mudança não deve afetar essas plataformas.

Ainda por fazer:

  • Teste em um kernel do Windows mais antigo. É necessário configurar um ambiente de desenvolvimento de máquina virtual para isso.
  • Teste a cópia entre volumes (já que é isso que nos preocupa). Não tenho certeza de como fazer isso como um teste automatizado.
  • Teste o arquivo tr_sys_path_copy () para um arquivo razoavelmente grande (> 100 GB). Provavelmente não pode ser feito como um teste automatizado.
  • Teste in situ ao invés de apenas testar tr_sys_path_copy () isoladamente.
  • Substitua um dos meus servidores de bit torrent por este código por um tempo, veja como ele se comporta no mundo real.

Feedback bem-vindo.

1 para tornar as movimentações de dados assíncronas. Mover torrents grandes entre sistemas de arquivos bloqueia todo o aplicativo .

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

z1tr0t3c picture z1tr0t3c  ·  4Comentários

mattia-b89 picture mattia-b89  ·  7Comentários

crozone picture crozone  ·  6Comentários

alimony picture alimony  ·  6Comentários

Zeebrah picture Zeebrah  ·  6Comentários