When transferring thousands of small files (typically 1-100KB each) across Windows UNC shares, you face significant overhead from:
- File system metadata operations (create/open/close timestamps)
- NTFS permission checks
- SMB protocol negotiation per file
Using PowerShell, we can measure the performance gap:
# Test transferring 10,000 small files (5KB each)
Measure-Command { Copy-Item .\small_files\* \\target\share -Recurse }
# Test transferring single 50MB archive
Measure-Command { Copy-Item .\archive.7z \\target\share }
Typical results show archive transfers completing 3-8x faster due to:
- Single SMB session establishment
- Eliminated file system overhead
- Better network buffer utilization
For maximum throughput with 7-Zip:
7z a -t7z -mx1 -mmt=on archive.7z source_folder
Where:
-mx1
uses fastest compression (prioritizing speed over ratio)-mmt=on
enables multithreading- Consider
-m0=Copy
for no compression if CPU is bottleneck
When archives aren't feasible:
# Robocopy with multi-threading
robocopy source dest /MT:16 /NP /R:1 /W:1
# Tar for streaming (Windows 10+)
tar -cf - . | tar -xf - -C \\target\share
NTFS performance degrades with:
- Directory entries exceeding 100,000 files
- Fragmented Master File Table (MFT)
- Antivirus real-time scanning
For massive transfers (>1M files), consider splitting archives into batches of 50,000 files.
When transferring thousands of small files (typically 1-10KB each) across Windows UNC shares, we face inherent inefficiencies in the SMB protocol. Each file transfer requires:
- New connection establishment
- Metadata operations (permissions checking, timestamps)
- Disk seek operations on both ends
Benchmark tests show that transferring 10,000 x 5KB files takes 3-5x longer than transferring a single 50MB archive containing the same data. Here's why:
// Theoretical transfer times (100Mbps network)
Small files:
10,000 files * (20ms overhead + 0.4ms transfer) ≈ 204 seconds
Zipped archive:
1 file * (20ms overhead + 400ms transfer) ≈ 420ms
For programmatic solutions, consider these approaches:
Option 1: Simple PowerShell Zipping
# Compress files
Compress-Archive -Path "\\source\share\*" -DestinationPath "\\target\share\archive.zip" -CompressionLevel Fastest
# Decompress (if needed)
Expand-Archive -Path "\\target\share\archive.zip" -DestinationPath "\\target\share\extracted"
Option 2: Robocopy for Direct Transfer
robocopy \\source\share \\target\share /MIR /ZB /R:1 /W:1 /MT:16 /LOG:transfer.log
# /MT enables multithreading (16 threads in this case)
For mission-critical transfers:
- SMB Direct: Enable RDMA if supported by NICs
- Disable SMB1: Ensure SMB 3.1.1 is active
- File System Cache: Increase the cache for small files
Consider direct transfer when:
- Files require immediate random access
- Processing pipeline expects individual files
- Total transfer size is below 10,000 files