cmdlets/Get-FolderSizeParallel.psm1

using module .\Get-BestSizeUnit.psm1

Add-Type -TypeDefinition @"
using System;
using System.IO;
using System.Threading.Tasks;
using System.Collections.Concurrent;
 
public static class ParallelFolderSize
{
    public static long GetFolderSizeParallel(string folderPath)
    {
        if (!Directory.Exists(folderPath))
            throw new DirectoryNotFoundException("Directory not found: " + folderPath);
         
        return GetDirectorySizeParallel(new DirectoryInfo(folderPath));
    }
     
    private static long GetDirectorySizeParallel(DirectoryInfo directory)
    {
        long size = 0;
         
        try
        {
            // Get files in current directory
            FileInfo[] files = directory.GetFiles();
             
            // Calculate file sizes in parallel
            Parallel.ForEach(files, file =>
            {
                try
                {
                    System.Threading.Interlocked.Add(ref size, file.Length);
                }
                catch
                {
                    // Skip files we can't access
                }
            });
             
            // Get subdirectories
            DirectoryInfo[] subdirectories = directory.GetDirectories();
             
            // Process subdirectories in parallel
            var subSizes = new long[subdirectories.Length];
            Parallel.For(0, subdirectories.Length, i =>
            {
                try
                {
                    subSizes[i] = GetDirectorySizeParallel(subdirectories[i]);
                }
                catch
                {
                    subSizes[i] = 0;
                }
            });
             
            // Add all subdirectory sizes
            for (int i = 0; i < subSizes.Length; i++)
            {
                size += subSizes[i];
            }
        }
        catch
        {
            // Skip if we can't enumerate the directory
        }
         
        return size;
    }
}
"@


function Get-FolderSizeParallel {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$Path
    )
    
    process {
        try {
            $resolvedPath = Resolve-Path $Path -ErrorAction Stop
            $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
            
            $size = [ParallelFolderSize]::GetFolderSizeParallel($resolvedPath.Path)
            
            $stopwatch.Stop()
            
            [PSCustomObject]@{
                Path              = $resolvedPath.Path
                SizeBytes         = $size
                SizeKB            = [Math]::Round($size / 1KB, 2)
                SizeMB            = [Math]::Round($size / 1MB, 2)
                SizeGB            = [Math]::Round($size / 1GB, 3)
                SizeTB            = [Math]::Round($size / 1TB, 4)
                SizePB            = [Math]::Round($size / 1PB, 5)
                BestUnit          = Get-BestSizeUnit -Bytes $size
                CalculationTimeMs = $stopwatch.ElapsedMilliseconds
            }
        }
        catch {
            Write-Error "Error calculating folder size for '$Path': $($_.Exception.Message)"
        }
    }
}