如何提升PowerShell中PSObject动态成员查找的执行速度?
PowerShell 动态对象成员查找性能优化方案
核心性能瓶颈说明
代码中$obj.$columnName的动态属性访问开销大,是因为PowerShell每次执行该语句时都会重新做成员解析,没有针对重复场景做缓存,嵌套循环中调用次数多了就会成为性能瓶颈。
可行的优化方法
方法1:直接遍历对象的属性集合,取消按名称查找步骤
不需要提前收集所有属性名再循环按名取值,遍历每个对象时直接获取其所有属性集合遍历即可,完全省去属性名匹配的开销,兼容任意类型的对象,无需提前知道属性列表,性能提升幅度可达十倍以上:$objs = Get-Process [Int64]$sum = 0 foreach ($obj in $objs) { # 直接取当前对象所有符合要求的属性,无需按名查找 foreach ($prop in $obj.PSObject.Properties) { $v = $prop.Value if ($v -eq $null) { continue } elseif ($v -is [System.IntPtr]) { $sum += $v -as [int64] } elseif ($v -is [System.Int64] -or $v -is [System.Int32]) { $sum += $v } } } "sum = $sum"方法2:缓存同类型对象的属性访问器
如果$objs数组中所有对象都是同一类型,可以提前缓存对应属性的反射访问器,后续直接调用GetValue取值,避免每次重复解析成员,处理同类型大对象数组时性能比方法1更高:$objs = Get-Process # 仅首次获取类型的属性信息,同类型对象复用 $type = $objs[0].GetType() $validProps = [System.Collections.Generic.List[System.Reflection.PropertyInfo]]::new() foreach ($prop in $type.GetProperties([System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::Instance)) { $propType = $prop.PropertyType if ($propType -eq [int] -or $propType -eq [long] -or $propType -eq [IntPtr]) { $validProps.Add($prop) } } [Int64]$sum = 0 foreach ($obj in $objs) { foreach ($prop in $validProps) { $v = $prop.GetValue($obj) if ($null -eq $v) { continue } if ($v -is [IntPtr]) { $sum += $v -as [long] } else { $sum += $v } } } "sum = $sum"额外优化点:原有代码中使用
$columnNames += $name的方式追加数组,每次都会生成新的数组对象,属性数量多的时候也会有额外开销,可改用[System.Collections.Generic.List[string]]存储属性名降低开销。
内容的提问来源于stack exchange,提问作者René Nyffenegger
相关产品推荐
相关产品推荐

