设置 DFS 副本时的一项常见任务是确定复制文件夹中最大 32 个文件的大小 - 根据当前最佳实践,这些文件的总和应为暂存区域的最小大小。
Technet 博客中给出了查找和计算此 top-32 文件大小的方法:https://blogs.technet.microsoft.com/askds/2011/07/13/how-to-determine-the-minimum-staging-area-dfsr-needs-for-a-replicated-folder/
它依赖于使用 Get-ChildItem
查找路径中的所有文件及其大小,按大小排序,丢弃除 32 个最大的文件之外的所有文件,然后计算总和。
当路径中的文件数量有限时,这没什么问题,但对包含数十万甚至数百万个文件的文件夹建立索引时,会存在严重的缺点。该进程在执行时将所有内容转储到内存中 - 在我的示例中,它消耗了超过 2GB 的虚拟内存 - 并且需要很长时间,即使单个文件非常小也是如此。内存将保持分配状态,直到 PS 实例关闭。
PS C:\> measure-command { (get-childitem F:\Folder\with\966693\items -recurse |
sort-object length -descending | select-object -first 32 |
measure-object -property length -sum).sum }
Days : 0
Hours : 0
Minutes : 6
Seconds : 6
Milliseconds : 641
Ticks : 3666410633
TotalDays : 0.00424353082523148
TotalHours : 0.101844739805556
TotalMinutes : 6.11068438833333
TotalSeconds : 366.6410633
TotalMilliseconds : 366641.0633
最佳答案
如果您可以大大加快 Get-ChildItem
的速度,我会感到惊讶,除非您可以避免为每个文件构建 [IO.FileInfo]
对象(.Net DirectorySearcher也许?)。
但是您也许可以通过不保留所有结果(仅保留当前的 N 个最大结果(本例中为 100))来减少内存需求,但可以进行调整以测试内存/性能,例如
$BufferSize = 100
$FileSizes = New-Object System.Collections.ArrayList
Get-ChildItem 'd:\downloads' -Force -Recurse -File | ForEach {
$null = $FileSizes.Add($_.Length)
if ($FileSizes.Count -gt $BufferSize)
{
$FileSizes.Sort()
$FileSizes.RemoveRange(0, ($BufferSize-32))
}
}
($FileSizes[0..31] | measure-object -Sum).Sum/1GB
向 gci 添加了 -Force
参数,以防某些最大的文件被隐藏。
关于powershell - 计算 DFS 文件夹暂存大小的前 32 个文件大小的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40457784/