Cópia de arquivo multithread


8

Existe um utilitário que é usado para carregar arquivos (e executar outras operações no arquivo) em um local compartilhado da rede.
O tamanho do arquivo tende a variar de alguns mb a 500 mb.
Surgiu uma sugestão de que talvez devêssemos oferecer suporte à multi-threading ao fazer upload dos arquivos para o local compartilhado - não é necessário fazê-lo em blocos de bytes - cada thread deve escolher um arquivo e tentar fazer o upload.

Não tenho certeza se o multithreading pode acelerar operações de E / S como esta. Meu palpite é válido?

Se, de fato, somos obrigados a criar essa funcionalidade, eu estava pensando qual seria uma boa abordagem de design para o mecanismo de cópia de arquivos?
Faria sentido usar uma ferramenta como robocopy (eu li que as versões mais recentes suportam multithreading)?

Edit: Desculpas pelo atraso e falta de algumas informações vitais.
Esse utilitário é criado usando C # (.Net 2.0) e qualquer atualização futura também deve estar usando .Net (a versão da estrutura não é uma restrição). O utilitário é instalado nas máquinas dos usuários (cerca de 20 no WinXP). O compartilhamento de destino está no servidor Win2k3.

Edit 2: decidiram executar alguns testes com um aplicativo simples implementando o upload do arquivo através do TPL. Após esta análise, decidiremos se vamos ou não em frente. Obrigado a todos pela ajuda estendida.


1
Qual linguagem de programação? Em C, uma abordagem mais idiomática pode ser a utilização de E / S assíncrona, usando um selectloop em vez de threads. Embora isso exija que você "vire seu código de dentro para fora" (o código para copiar um arquivo não é mais uma sequência direta de comandos), você não precisará se preocupar com a sincronização de threads.
Joey Adams

Provavelmente, a solução razoável mais fácil é deixar o OS lidar com tudo isso: SHFileOperation(FO_COPY). Isso oferece a você todas as otimizações que as pessoas da Microsoft consideraram razoáveis.
MSalters

Tosse robocopy tosse ... você poderia automatizar isso com algo como robomojo
James Snell

Respostas:


19

Isso depende de qual é o fator limitante, não é? Se o gargalo for o programa utilitário, certifique-se de que executar mais de uma cópia ou usar mais threads agilizará as coisas. Se a rede for o fator limitante, a adição de várias instâncias do utilitário não ajudará, pois você ainda ficará parado se movendo no máximo X bytes por segundo. Na verdade, pode doer porque você tem a sobrecarga adicional de uma segunda cópia do aplicativo. Mesmo com disco-IO. Você só pode copiar o mais rápido que a máquina puder ler e gravar no disco. Se isso já foi o máximo, adicionar cópias não vai ajudar.

O que você precisa fazer é testar para ver qual é o gargalo e partir daí.


11

Como o multithreading não ajudará:

Múltiplos encadeamentos que leem simultaneamente do disco do cliente ou enviam coisas pela rede simultaneamente não ajudam em nada, pois provavelmente existe apenas um caminho de comunicação entre o cliente e o servidor, é provável que o cliente esteja lendo arquivos de um único disco rígido -drive, e os arquivos provavelmente estão sendo gravados em um único disco rígido no servidor. (Mesmo que o servidor tenha RAID, isso fará alguma diferença, mas não muito.) Pelo contrário, como já foi apontado, o desempenho provavelmente diminuirá, pois haverá uma busca constante entre os arquivos que estão sendo lidos em paralelo no cliente e busca constante entre os arquivos que estão sendo gravados em paralelo no servidor. Além disso, os arquivos podem acabar sendo armazenados muito fragmentados no servidor.

Como o multithreading ajudará:

No entanto, o multithreading pode ajudar de uma maneira diferente: com apenas dois threads no cliente, a E / S do arquivo pode ser dessincronizada a partir da E / S da rede. Isso significa que o cliente pode transmitir simultaneamente um pedaço de um arquivo enquanto lê o próximo pedaço do seu disco. (O servidor já é capaz de gravar simultaneamente um pedaço de arquivo no disco enquanto recebe o próximo pedaço da rede.) Isso seria muitoacelerar o processo de transferência, porque o cliente tenderia a manter o canal de rede ou o canal de disco (o que for mais lento) saturado, em vez de acessar cada um de cada vez, de forma intermitente. Eu acho que todo utilitário de cópia de arquivo especializado deve ser inteligente o suficiente para fazer isso, mas posso estar errado, por isso, se o "Robocopy" anunciar que eles fazem cópias com vários threads, tudo bem, vá em frente.

EDIT: Corrigi o que escrevi sobre RAID.

EDIT: Corrigi um pouco sobre a exigência de dois threads no servidor.

Eu acho que a coisa mais importante aqui (como está em quase toda parte) é a medição . Você não tem controle sobre o funcionamento desses utilitários; portanto, só saberá se está fazendo da maneira mais rápida possível se medir a taxa de transferência para verificar se ela está próxima à taxa de transferência anunciada do seu disco ou rede (o que for menor) .)


Parece uma ótima idéia, mas não entendo como o utilitário de transferência de arquivos pode realmente fazer isso, a menos que tenha privilégios de execução remota (ou o protocolo de transferência de alguma forma suporte isso inerentemente). Estou tentando escrever um utilitário para fazer transferências regulares de um número gigantesco de arquivos de um NAS, e realmente preciso encontrar maneiras de reduzir o tempo.
Asad Saeeduddin

Sua pergunta é muito perspicaz e aponta para uma imprecisão na minha resposta. O servidor já deve estar dessincronizando a E / S da rede a partir do acesso ao disco, em virtude de como os servidores geralmente funcionam: eles tendem a fazer a E / S assíncrona em vez de gerar um encadeamento separado para cada cliente, que só pode fazer uma coisa de cada vez. Portanto, você não precisa se preocupar com o servidor, apenas com o cliente. Vou reformular minha resposta.
Mike Nakis

@ Asad Além disso, observe que, por "servidor", neste caso, quero dizer qualquer máquina que esteja na extremidade receptora da transferência. Não precisa ser uma máquina com uma função de servidor designada.
Mike Nakis

9

Ao copiar muitos arquivos menores, o multithreading pode ajudar, pois costuma haver lacunas na transferência de dados enquanto o programa está pesquisando nos diretórios o próximo arquivo, abrindo-o e obtendo os dados.

O multithreading também ajudará quando o cliente e o servidor tiverem armazenamento de dados paralelo, como RAID ou SSD: qualquer coisa que tenha um desempenho melhor com números mais altos de profundidade da fila.

Fora isso, muitas vezes atrasa as coisas. Por exemplo, fazer um único disco rígido ler ou gravar dois arquivos ao mesmo tempo forçará a busca repetida do arquivo 1 para o arquivo 2.


2

Trabalho na Data Expedition, Inc., que, como Emmad mencionou, produz software comercial para esse tipo de cenário. A transferência de arquivos multithread pode ter benefícios, mas você precisa entender cuidadosamente quais são os gargalos de desempenho.

Qualquer caminho de rede terá pelo menos dezenas de componentes de hardware e software pelos quais os dados devem passar. O mais lento de todos eles determinará sua velocidade. Mas a maneira como você move os dados mudará o comportamento desses componentes.

Muitos antecedentes sobre isso aqui: http://www.DataExpedition.com/support/notes/tn0009.html

A execução de TCPs paralelos pode ajudar quando as velocidades TCP individuais estão caindo muito abaixo das capacidades da rede, do disco e da CPU.

Mas se você estiver olhando para velocidades de rede superiores a dezenas de megabits por segundo, as transferências paralelas de dados reduzirão exponencialmente a E / S do disco, devido a uma sobrecarga no disco rígido. Pode cair rapidamente ao ponto em que o acesso ao disco se torna muito mais lento que a capacidade da rede. A escolha do tamanho certo do bloco de leitura / gravação pode ajudar, mas isso dependerá do hardware específico. Lembre-se também de que o Windows XP / 2003 tem memória de pool paginada muito limitada, o que pode torná-lo instável se a velocidade ultrapassar os 200 megabits por segundo.

Por outro lado, se a rede é mais lenta do que algumas dezenas de megabits por segundo, a execução de muitos TCPs paralelos pode aumentar a latência até o ponto em que sessões individuais começam a desacelerar ou até mesmo diminuir suas conexões. Novamente, é uma questão de experimentação descobrir qual nível de paralelismo funcionará para qualquer caminho e condições.

Portanto, a cópia de arquivos multithread pode ajudar se você tiver um caminho de dados conhecido e demorar algum tempo para ajustar o número de sessões paralelas e a E / S do disco. Mas exige que você volte a sintonizar sempre que as condições mudarem e pode ser perturbador se você exagerar. É por isso que optamos por evitar transferências paralelas em nosso próprio software, assim como evitamos o TCP.


1

Além do que foi dito, considere: - Deve haver uma tarefa no cliente para criar os chunks e outra no servidor para reuni-los novamente como um arquivo. Isso requer algum trabalho.

  • Uma coisa boa sobre pequenos pedaços é que você pode reenviar partes de um arquivo se o processo falhar, em vez de enviar o arquivo grande todo.

  • Considere solicitar um 'canal maior' entre seu cliente e o servidor.

  • Considere compactar o arquivo grande antes de enviá-lo (não tenho certeza se isso ajudaria no caso de arquivos multimídia, pois eles às vezes já estão compactados).

  • Considere usar um utilitário comercial de transferência de arquivos, como:

DataExp


0

Se você estiver falando de um arquivo grande, o multithreading não ajudará. Você será vinculado à E / S, portanto, o uso de um único encadeamento não atrasará o carregamento.

No entanto, você deve se preocupar com a contenção de recursos (supondo que você esteja gravando o servidor também). Se você estiver manipulando o upload no encadeamento que também aceita e processa novas solicitações, outras solicitações estarão aguardando. Contanto que você retorne à fila do seletor depois de ler um pedaço do soquete e gravá-lo no disco, você deve ficar bem.


0

Fazer o que você sugere de maneira ingênua prejudica sua taxa de transferência, o ponto de estrangulamento é a E / S do disco e não está preparando os arquivos.

Vou sugerir o uso de um thread que receba arquivos para trabalhar e os enfileire para a cópia e, em seguida, mantenha uma cópia seqüencial em qualquer parte da fila; o encadeamento do fornecedor é responsável por fazer com que os arquivos sejam lidos na fila. Dessa forma, você não está debulhando o sistema de arquivos nas unidades compartilhadas e não está criando arquivos um de cada vez com lacunas para preparar o próximo, está preparando e enviando simultaneamente.

O bônus é que há apenas um ponto de sincronização na fila para se preocupar.


0

Em vez de implementar o upload paralelo, considere os protocolos e ferramentas existentes. Por exemplo, o protocolo ftp e a ferramenta lftp (o lftp pode transferir vários arquivos em paralelo).

Portanto, é provavelmente muito mais fácil e mais robusto usar scripts lftp ou controlar o lftp do seu aplicativo em vez de implementar tudo do zero.


0

Tudo depende de onde está o fator limitante.

O multithreading pode ajudar se houver atrasos de ida e volta ou outras lacunas na transmissão, e os threads ajudarem a preencher as lacunas.

O multithreading pode prejudicar se isso causar o movimento do disco para frente e para trás, tentando manter todos os threads fornecidos com os dados.

etc.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.