일부 컴퓨터에서 큰 파일을 동기화해야합니다. 파일 크기는 최대 6GB입니다. 동기화는 몇 주마다 수동으로 수행됩니다. 파일 이름은 언제든지 변경할 수 있으므로 고려할 수 없습니다.
내 계획은 대상 PC와 원본 PC에서 체크섬을 만든 다음 아직 대상에없는 체크섬이있는 모든 파일을 대상에 복사하는 것입니다. 내 첫 번째 시도는 다음과 같습니다.
using System.IO;
using System.Security.Cryptography;
private static string GetChecksum(string file)
{
using (FileStream stream = File.OpenRead(file))
{
SHA256Managed sha = new SHA256Managed();
byte[] checksum = sha.ComputeHash(stream);
return BitConverter.ToString(checksum).Replace("-", String.Empty);
}
}
런타임 문제 :
-1,6GB 파일이있는 SHA256-> 20 분
-1,6GB 파일이있는 MD5-> 6.15 분
체크섬을 얻는 더 좋고 빠른 방법이 있습니까?
답변
여기서 문제는 SHA256Managed
한 번에 4096 바이트 를 읽으며 ( 파일 스트림에서 읽은 양을 확인하기 위해 상속 FileStream
하고 재정의 Read(byte[], int, int)
함) 디스크 IO에 비해 너무 작은 버퍼입니다.
속도 일까지 랩 (2 내 SHA256와 기계, MD5 1 분 정도에 2GB의 파일을 해싱 분) FileStream
에 BufferedStream
설정하고 합리적인 크기의 버퍼 크기 (나는 ~ 1 메가 버퍼로 시도) :
// Not sure if BufferedStream should be wrapped in using block
using(var stream = new BufferedStream(File.OpenRead(filePath), 1200000))
{
// The rest remains the same
}
답변
전체 파일을 체크섬하지 말고 100MB 정도마다 체크섬을 생성하십시오. 따라서 각 파일에는 체크섬 모음이 있습니다.
그런 다음 체크섬을 비교할 때 첫 번째 다른 체크섬 후 비교를 중지하고 일찍 나가 전체 파일을 처리하지 않아도됩니다.
동일한 파일의 경우 여전히 풀 타임이 소요됩니다.
답변
Anton Gogolev가 언급했듯이 FileStream은 기본적으로 한 번에 4096 바이트를 읽지 만 FileStream 생성자를 사용하여 다른 값을 지정할 수 있습니다.
new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 16 * 1024 * 1024)
Microsoft의 Brad Abrams는 2004 년에 다음과 같이 썼습니다.
FileStream 주위에 BufferedStream을 래핑하면 이점이 없습니다. 약 4 년 전에 BufferedStream의 버퍼링 로직을 FileStream에 복사하여 기본 성능을 향상 시켰습니다.
답변
md5sum.exe 의 Windows 포트를 호출하십시오 . .NET 구현보다 약 2 배 빠릅니다 (적어도 1.2GB 파일을 사용하는 컴퓨터에서는)
public static string Md5SumByProcess(string file) {
var p = new Process ();
p.StartInfo.FileName = "md5sum.exe";
p.StartInfo.Arguments = file;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
p.WaitForExit();
string output = p.StandardOutput.ReadToEnd();
return output.Split(' ')[0].Substring(1).ToUpper ();
}
답변
좋아요-모두 감사합니다. 마무리하겠습니다.
답변
이 코드를 실행하면서 버퍼 크기로 테스트를 수행했습니다.
using (var stream = new BufferedStream(File.OpenRead(file), bufferSize))
{
SHA256Managed sha = new SHA256Managed();
byte[] checksum = sha.ComputeHash(stream);
return BitConverter.ToString(checksum).Replace("-", String.Empty).ToLower();
}
그리고 29½ GB 크기의 파일로 테스트했는데 결과는
- 10.000 : 369,24 초
- 100.000 : 362,55 초
- 1.000.000 : 361,53 초
- 10.000.000 : 434,15 초
- 100.000.000 : 435,15 초
- 1.000.000.000 : 434,31 초
- 그리고 버퍼링되지 않은 원본 코드를 사용할 때 376,22s.
i5 2500K CPU, 12GB 램 및 OCZ Vertex 4256GB SSD 드라이브를 실행하고 있습니다.
그래서 표준 2TB 하드 드라이브는 어떨까요? 결과는 이렇습니다
- 10.000 : 368,52 초
- 100.000 : 364,15 초
- 1.000.000 : 363,06 초
- 10.000.000 : 678,96 초
- 100.000.000 : 617,89 초
- 1.000.000.000 : 626,86 초
- 버퍼링되지 않은 버퍼
따라서 버퍼 없음 또는 최대 1 밀의 버퍼를 권장합니다.
답변
무언가 잘못하고 있습니다 (아마도 너무 작은 읽기 버퍼). 디스크에 DMA가있을 수있는 부적절한 연령 (2002 년 애슬론 2x1800MP)의 머신에서 아마도 순차 읽기 (6.6M / s는 순차 읽기를 수행 할 때 느려짐)입니다.
“무작위”데이터로 1G 파일을 만듭니다.
# dd if=/dev/sdb of=temp.dat bs=1M count=1024
1073741824 bytes (1.1 GB) copied, 161.698 s, 6.6 MB/s
# time sha1sum -b temp.dat
abb88a0081f5db999d0701de2117d2cb21d192a2 *temp.dat
1m5.299s
# time md5sum -b temp.dat
9995e1c1a704f9c1eb6ca11e7ecb7276 *temp.dat
1m58.832s
이것은 또한 이상합니다 .md5는 sha1보다 지속적으로 느립니다 (여러 번 재생).