2016-11-07 49 views
1

設置DFS副本時的常見任務是確定複製文件夾中32個最大文件的大小 - 其總和應爲根據目前的最佳做法,分級區域的最小尺寸。計算DFS文件夾分級大小的前32個文件大小的更好方法

發現和計算這頂-32文件大小的方法是TechNet博客中給出: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 

回答

0

有了輕微的調整 - 實例化一個System.Collections.ArrayList來存儲文件長度的名單 - 在同一目錄下執行查詢的時間幾乎減半。當您向其中添加新項目時,您是not constantly creating/destroying a standard fixed-sized array

此示例的Powershell進程的內存使用量仍低於900MB。如果我想重新使用PS控制檯,我還希望有一個變量設置爲$ null。

measure command { $total = New-Object System.Collections.ArrayList; 
gci F:\Folder\with\966693\items -file -r | 
ForEach { $total.Add($_.length)>$null } ; 
(($total | sort -descending | select -first 32 |measure-object -sum).sum/1GB) } 
Days    : 0 
Hours    : 0 
Minutes   : 3 
Seconds   : 34 
Milliseconds  : 215 
Ticks    : 2142159038 
TotalDays   : 0.00247935073842593 
TotalHours  : 0.0595044177222222 
TotalMinutes  : 3.57026506333333 
TotalSeconds  : 214.2159038 
TotalMilliseconds : 214215.9038 

整潔多層線路版:

$total = New-Object System.Collections.ArrayList 
gci F:\Folder\with\966693\items -file -r | ForEach { $total.Add($_.length)>$null } 
($total | sort -descending | select -first 32 | measure-object -sum).sum/1GB 
1

我會感到驚訝,如果你能多加快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 

增加了-Force參數給gci,以防一些最大的文件被隱藏。

+0

謝謝,看起來效率更高,通過減少不再需要的結果。至於我的結果,他們在測試文件夾樹中的100K +文件方面非常一致。我想解決這個問題,因爲我每次在120萬個項目文件集上嘗試原始進程時,基本上都會在服務器上發生內存泄漏。這些特定的文件集的一個特點是,它們中的大部分都由<5K大小的文件組成。 – Trix