【问题标题】:Is there a way to stream data out faster from a large command?有没有办法从大命令中更快地流出数据?
【发布时间】:2018-08-15 02:35:25
【问题描述】:

假设我正在使用 get-childitem c:\*.* -recurse 并且我正在使用它。在管道处理它之前,我必须等待整个 get-childitem 命令完成。有一些例外,例如select -first 2,它会神奇地停止上一个命令。无论如何,有没有办法提高输出,所以它立即写入而不是吸收大量的内存?我的一个想法是......(我知道这行不通,但它让这个想法得到了理解)

[System.IO.File]::ReadLines("$(dir c:\*.* -recurse)")

我知道这是 Windows 的事情,因为 Linux 会在数据一出现时就对其进行处理。但我知道,这是两个不同的世界。

我最担心的是内存使用...

这是一个很好的例子

(1..10000000) | where {$_ -like "*543*"}

这需要我的机器大约 100 秒

在哪里

(1..10000000).where({$_ -like "*543*"})

只用了 25 秒。

【问题讨论】:

    标签: performance powershell pipeline memory-efficient


    【解决方案1】:

    在管道处理它之前,我必须等待整个 get-childitem 命令完成。

    否:PowerShell 管道的真正意义在于在对象可用时逐个处理,从而充当内存节流阀以保持内存无论输入集合的大小如何,都使用常量

    • 警告:不要在通过管道发送其输出的命令周围使用(...),因为这确实会首先在内存中完整收集该命令的输出。 p>

    • Cmdlet,作为 PowerShell 的本机命令,天生就支持这种一对一的流式传输。

      • 但是,某些 cmdlet,例如 Sort-ObjectGroup-Object必须首先收集内存中的所有输入[1],作为一个概念必要性(例如,在比较所有项之前,您无法生成排序输出)。谢谢Bacon Bits

      • 1234563李>
    • 类似地,外部程序的标准输出输出通过逐行传递,因为这些行变得可用。 p>

    • 您可以通过将 表达式 括在 & { ... } 中将其转换为流式命令,但这仅在表达式尚未构建时才有用内存中对象的完整集合;例如,
      & { 1.. 10000000 } | ... 不会为您带来任何好处,但
      & { for ($i=0; $i -lt 10000000; ++$i) { $i } } | ... 会。

    • 最终,如果源 cmdlet/程序/表达式本身不以流式方式发出输出对象(一个接一个,因为它们正在生成),那么您就不走运了。

    然而,确实缺少的是停止管道处理按需的能力——目前只有Select-Object -First可以做到——见我的this answer
    有一个长期存在的feature request on GitHub 要求提供一种机制来按需停止管道。


    顺便说一句:使用 PSv4+ .Where() method 确实比使用 Where-Object cmdlet(其内置别名为 where)更快,但 .Where() 总是要求它操作的集合已加载提前完整记入内存。

    但是,.Where() 方法确实可以通过将'First' 作为第二个参数传递来停止处理剩余项目,该参数在第一次匹配后停止; 'First'[System.Management.Automation.WhereOperatorSelectionMode] 的一个实例;比较
    (1..1e6).Where({$_ -eq 10})
    (1..1e6).Where({$_ -eq 10}, 'First')的性能


    [1] 例如,PowerShell 确实使用 临时文件 来缓解 Unix sort 实用程序的内存压力;我的猜测是,这样做在 PowerShell 中并不是一个真正的选择:PowerShell 处理活动对象(而不是静态字符串)的能力将带来重大的序列化/反序列化挑战,这是要使用的临时文件。

    【讨论】:

    • 您对 powershell 的掌握非常令人印象深刻。你有什么书推荐吗?我会相信你的意见而不是评论。我想知道基本的内部工作原理(例如括号如何强制将全部负载加载到 ram 中)等......并且还对 .net 框架/对象/命令有非常广泛的了解。我知道前面的山。但是我为大文件编写了许多脚本。如果我可以通过更好的代码节省 30% 的时间,我每年可以节省几个月的时间
    • @RobertCotterman: 有语言规范,虽然它自 v3 以来一直没有更新:microsoft.com/en-us/download/details.aspx?id=36389 我知道的唯一一本书(并且只阅读过摘录)是manning.com/books/windows-powershell-in-action-third-edition 除此之外,试用和错误是您的朋友(不幸的是,官方文档不是,尽管由于 PowerShell 和文档都已开源,情况正在改善),如果您喜欢冒险,请研究源代码:github.com/PowerShell/PowerShell跨度>
    • 对于那些想知道的人,我的问题并没有真正的正确答案,它更像是一种探索 powershell 工作原理的方法,Mklement0 一如既往地提出了一些惊人的观点。
    猜你喜欢
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 1970-01-01
    • 2022-10-21
    相关资源
    最近更新 更多