PowerShell,使用 Start-Job 和 Start-Process 测试异步任务的性能/效率

2024-05-26

我很想测试 PowerShell 中异步任务的性能/有用性Start-ThreadJob, Start-Job and Start-Process。我有一个包含大约 100 个 zip 文件的文件夹,因此进行了以下测试:

New-Item "000" -ItemType Directory -Force   # Move the old zip files in here
foreach ($i in $zipfiles) {
    $name = $i -split ".zip"
    Start-Job -scriptblock {
        7z.exe x -o"$name" .\$name
        Move-Item $i 000\ -Force
        7z.exe a $i .\$name\*.*
    }
}

这样做的问题是它会启动所有 100 个 zip 的作业,这可能太多了,所以我想设置一个值$numjobs,比如说 5,我可以改变它,这样只有$numjobs将同时启动,然后脚本将检查在下一个 5 个作业块开始之前结束的所有 5 个作业。然后我想根据以下值观察 CPU 和内存$numjobs

我如何告诉循环只运行 5 次,然后等待作业完成后再继续?

我发现等待作业完成很容易

$jobs = $commands | Foreach-Object { Start-ThreadJob $_ }
$jobs | Receive-Job -Wait -AutoRemoveJobchange

但我该如何等待Start-Process任务要结束吗?

虽然我想用Parallel-ForEach,我工作的企业将在未来 3-4 年内与 PowerShell 5.1 紧密相连,我预计没有机会安装 PowerShell 7.x(尽管我很好奇自己可以使用Parallel-ForEach在我的家庭系统上比较所有方法)。


ForEach-Object -Parallel https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7.2 and Start-ThreadJob https://docs.microsoft.com/en-us/powershell/module/threadjob/start-threadjob?view=powershell-7.2具有内置功能来限制可以同时运行的线程数量,这同样适用于Runspace https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspace?view=powershellsdk-7.0.0和他们的运行空间池 https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspacepool?view=powershellsdk-7.0.0这是两个 cmdlet 在幕后使用的内容。

Start-Job https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/start-job?view=powershell-7.2不提供此类功能,因为每个作业都在单独的进程中运行,而不是之前提到的在同一进程中的不同线程中运行的 cmdlet。我个人也不认为它是并行替代方案,它非常慢,并且在大多数情况下线性循环会比它更快。序列化和反序列化 https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_remote_output?view=powershell-7.2#deserialized-objects在某些情况下也可能是一个问题。

如何限制正在运行的线程数?

这两个 cmdlet 都提供-ThrottleLimit为此的参数。

  • https://learn.microsoft.com/en-us/powershell/module/threadjob/start-threadjob?view=powershell-7.2#-throttlelimit https://learn.microsoft.com/en-us/powershell/module/threadjob/start-threadjob?view=powershell-7.2#-throttlelimit
  • https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7.2#-throttlelimit https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/foreach-object?view=powershell-7.2#-throttlelimit

代码看起来怎么样?

$dir = (New-Item "000" -ItemType Directory -Force).FullName

# ForEach-Object -Parallel
$zipfiles | ForEach-Object -Parallel {
    $name = [IO.Path]::GetFileNameWithoutExtension($_)
    7z.exe x -o $name .\$name
    Move-Item $_ $using:dir -Force
    7z.exe a $_ .\$name\*.*
} -ThrottleLimit 5

# Start-ThreadJob
$jobs = foreach ($i in $zipfiles) {
    Start-ThreadJob {
        $name = [IO.Path]::GetFileNameWithoutExtension($using:i)
        7z.exe x -o $name .\$name
        Move-Item $using:i $using:dir -Force
        7z.exe a $using:i .\$name\*.*
    } -ThrottleLimit 5
}
$jobs | Receive-Job -Wait -AutoRemoveJob

只有 PowerShell 5.1 可用并且无法安装新模块时如何实现相同的效果?

The 运行空间池 https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspacepool?view=powershellsdk-7.0.0提供相同的功能,无论是.SetMaxRunspaces(Int32) Method https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspacepool.setmaxrunspaces?view=powershellsdk-7.0.0#system-management-automation-runspaces-runspacepool-setmaxrunspaces(system-int32)或通过瞄准其中之一RunspaceFactory.CreateRunspacePool超载 https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspacefactory.createrunspacepool?view=powershellsdk-7.0.0#overloads提供一个maxRunspaces极限作为参数。

代码看起来怎么样?

$dir   = (New-Item "000" -ItemType Directory -Force).FullName
$limit = 5
$iss   = [initialsessionstate]::CreateDefault2()
$pool  = [runspacefactory]::CreateRunspacePool(1, $limit, $iss, $Host)
$pool.ThreadOptions = [Management.Automation.Runspaces.PSThreadOptions]::ReuseThread
$pool.Open()

$tasks  = foreach ($i in $zipfiles) {
    $ps = [powershell]::Create().AddScript({
        param($path, $dir)

        $name = [IO.Path]::GetFileNameWithoutExtension($path)
        7z.exe x -o $name .\$name
        Move-Item $path $dir -Force
        7z.exe a $path .\$name\*.*
    }).AddParameters(@{ path = $i; dir = $dir })
    $ps.RunspacePool = $pool

    @{ Instance = $ps; AsyncResult = $ps.BeginInvoke() }
}

foreach($task in $tasks) {
    $task['Instance'].EndInvoke($task['AsyncResult'])
    $task['Instance'].Dispose()
}
$pool.Dispose()

请注意,对于所有示例,尚不清楚 7zip 代码是否正确,此答案尝试演示如何在 PowerShell 中完成异步,而不是如何压缩文件/文件夹。


下面是一个辅助函数,可以简化并行调用的过程,尝试模拟ForEach-Object -Parallel并且与 PowerShell 5.1 兼容不应该被视为一个强大的解决方案:

NOTE 本次问答 https://stackoverflow.com/questions/74257556/is-there-an-easier-way-to-run-commands-in-parallel-while-keeping-it-efficient-in为以下功能提供了更好、更强大的替代方案。

using namespace System.Management.Automation
using namespace System.Management.Automation.Runspaces
using namespace System.Collections.Generic

function Invoke-Parallel {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory, ValueFromPipeline, DontShow)]
        [object] $InputObject,

        [Parameter(Mandatory, Position = 0)]
        [scriptblock] $ScriptBlock,

        [Parameter()]
        [int] $ThrottleLimit = 5,

        [Parameter()]
        [hashtable] $ArgumentList
    )

    begin {
        $iss = [initialsessionstate]::CreateDefault2()
        if($PSBoundParameters.ContainsKey('ArgumentList')) {
            foreach($argument in $ArgumentList.GetEnumerator()) {
                $iss.Variables.Add([SessionStateVariableEntry]::new($argument.Key, $argument.Value, ''))
            }
        }
        $pool  = [runspacefactory]::CreateRunspacePool(1, $ThrottleLimit, $iss, $Host)
        $tasks = [List[hashtable]]::new()
        $pool.ThreadOptions = [PSThreadOptions]::ReuseThread
        $pool.Open()
    }
    process {
        try {
            $ps = [powershell]::Create().AddScript({
                $args[0].InvokeWithContext($null, [psvariable]::new("_", $args[1]))
            }).AddArgument($ScriptBlock.Ast.GetScriptBlock()).AddArgument($InputObject)

            $ps.RunspacePool = $pool
            $invocationInput = [PSDataCollection[object]]::new(1)
            $invocationInput.Add($InputObject)

            $tasks.Add(@{
                Instance    = $ps
                AsyncResult = $ps.BeginInvoke($invocationInput)
            })
        }
        catch {
            $PSCmdlet.WriteError($_)
        }
    }
    end {
        try {
            foreach($task in $tasks) {
                $task['Instance'].EndInvoke($task['AsyncResult'])
                if($task['Instance'].HadErrors) {
                    $task['Instance'].Streams.Error
                }
                $task['Instance'].Dispose()
            }
        }
        catch {
            $PSCmdlet.WriteError($_)
        }
        finally {
            if($pool) { $pool.Dispose() }
        }
    }
}

其工作原理的示例:

# Hashtable Key becomes the Variable Name inside the Runspace!
$outsideVariables = @{ Message = 'Hello from {0}' }
0..10 | Invoke-Parallel {
    "[Item $_] - " + $message -f [runspace]::DefaultRunspace.InstanceId
    Start-Sleep 5
} -ArgumentList $outsideVariables -ThrottleLimit 3
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PowerShell,使用 Start-Job 和 Start-Process 测试异步任务的性能/效率 的相关文章

  • 如何从 Powershell 访问 COM 对象上的索引属性

    我正在使用 Powershell 通过 COM 与 Windows 7 任务计划程序服务进行通信任务调度2 0接口 http msdn microsoft com en us library aa383600 VS 85 aspx 例如 I
  • 在没有 TransactionScopeAsyncFlowOption.Enabled 的情况下启用异步 TransactionScope

    以下是使用事务范围的异步缓存和数据库更新 我无法使用TransactionScopeAsyncFlowOption Enabled在 v 4 5 1 中引入 因为我使用的 Apache Ignite Net 缓存不支持它 我尝试通过捕获当前
  • 如何在 Windows 7 上安装 ScheduledTasks 模块

    是否可以安装该模块 http technet microsoft com en us library jj649816 aspx与 Windows 8 和 Windows Server 2012 不同的操作系统上的 PS v3 0 附带吗
  • 使用 Rx 简化异步 Silverlight Web 服务请求

    我已经使用 Rx 为我的 WCF Web 服务编写了一个简化的 Silverlight 客户端库 但是我注意到有时我会丢失已完成的事件 public IObservable
  • Windows 窗体:显示自适应省略号的单元格换行模式

    我正在使用 Windows 窗体 Datagridview 来显示一些 长 文本 代码是PowerShell 但问题与Cell Wrapping模式有关 TestGridView New Object System Windows Form
  • 在 .NET 4.0 中将任务与 Parallel.Foreach 一起使用

    我开始尝试向 Windows 窗体添加一个进度条 以更新 Parallel Foreach 循环中运行的代码的进度 为此 UI 线程必须可用于更新进度条 我使用 Task 来运行 Parallel Foreach 循环 以允许 UI 线程更
  • 我想在 Red Hat Linux 服务器中执行 .ps1 powershell 脚本

    我有一个在窗口中执行的 ps1 powershell 脚本 但我的整个数据都在 Linux 服务器中 有什么可能的方法可以让我在红帽服务器中执行 powershell 脚本 powershell脚本是 Clear Host path D D
  • 如何使用 OpenMP 并行化数组移位?

    如何使用 OpenMP 并行化数组移位 我已经尝试了一些方法 但没有得到以下示例的任何准确结果 该示例旋转 Carteira 对象数组的元素 用于排列算法 void rotaciona int i Carteira aux this gt
  • 使用 Powershell 远程安装 .msi

    我已经让他使用这个论坛上存在的代码来跟踪代码 cls computername Get Content C Users C201578 db Documents server txt sourcefile iceopsnas LNT Sof
  • 所有 C++ 编译器都支持 async/await 关键字吗?

    我想用async awaitC UE4 框架 中的语法 但由于跨平台代码 我不确定这是否可能 或者可能 如果是 我该如何使用它 而且还有await and await resumable yield and yield value另外 在
  • 如何在 PowerShell 中键入 TAB 字符?

    Task 默认情况下 在 Windows 命令提示符中按 TAB 键将输出文件名 而在 PowerShell 中则不会执行任何操作 我希望能够在交互模式下键入 TAB 字符 而不是通过脚本 Research 我在这个网站上和通过谷歌搜索发现
  • 获取对 SOAP 的 XML 响应中的节点值

    我在 PowerShell 中发出 SOAP 请求 如下所示 uri https secure echosign com services EchoSignDocumentService20 WSDL sun Invoke WebReque
  • 并行应用程序的可变与不可变[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在我正在编写的应用程序中 我需要编写大量基本类型 这些类型很可能是不可变的 但我想知道并行应用程序中可变类型与不可变类型的比较如何 您可以对可变
  • SLURM 节点、任务、核心和 CPU

    有人能够澄清这些东西到底是什么吗 据我所知 节点是集群内的计算点 本质上是一台计算机 任务是可以在单个节点或多个节点上执行的进程 核心基本上是指您希望在单个节点上分配多少 CPU 来执行分配给该 CPU 的任务 它是否正确 我混淆了什么吗
  • 在 Java 中并行处理两个任务

    我想在一个方法中调用8个方法 这8个方法中的2个方法是一个洞任务 其余6个方法是另一个洞任务 我想同时并行处理这两个任务 据我所知 我可以用线程来做到这一点 但说实话 要么我看不到与我的目标相似的示例 要么即使我看到了我也无法理解该示例 您
  • Powershell 脚本无法从 SCCM 正常运行 [已关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我正在尝试
  • 如何更改 Visual Studio Code“Powershell 集成控制台”?

    有谁知道如何安装 更新 PS 7 以供 VS Code Powershell 集成控制台使用 我可以在常规 powershell 终端上获取 PS 7 但 Powershell 集成控制台仍然是 PSVersion 5 1 我似乎不知道如何
  • 在 Windows 上不使用 OpenSSL 从 pfx 文件或证书存储中提取私钥

    正如标题所示 我想在不使用 OpenSSL 或任何其他第三方工具的情况下导出我的私钥 如果我需要一个 cer文件或 pfx我可以通过 MMC 或 PowerShell 轻松导出这些文件pkiclient但我找不到获取私钥的方法 https
  • notcontains 不适用于从 AD 组中提取的用户对象

    当使用 notcontains 检查数组中的对象时 它在应该为 false 时却显示为 True 这是我的代码 SPSecUsers Get ADGroupMember Test AllLondon Get ADGroupMember Te
  • Powershell:输出文件

    我正在尝试将所有控制台输出记录到文件中 移动项目 D scripts fileA D scripts fileB verbose Force 输出文件 D scripts move log 追加 如果该文件不存在 则正在创建该文件 但详细信

随机推荐

  • Objective-C 中可以创建私有财产吗?

    Objective C 中可以创建私有财产吗 我确实知道一种私有财产功能可以通过另一种方式实现 但我对特定问题感兴趣 谢谢 是的 可以 但是代码看起来有点奇怪 如果你打电话它只会给你一些警告 你必须自己检查警告 在您的实现文件 m 中 in
  • JFileChooser 上的系统外观布局,但具有 Nimbus 外观主题

    JFileChooser 上的窗口外观和感觉布局比其他类似 nimbus 的外观和感觉要好得多 所以我正在寻找一种方法来拥有系统外观和感觉的布局 但在顶部有 nimbus 或其他主题 这可能吗 如果可以的话怎么办呢 这是可能的 虽然我不知道
  • 我可以将 Braintree.js 与 .NET Web 应用程序一起使用吗?

    我这几天一直在研究 Braintree Payments 我喜欢它的架构 概念等 在浏览完文档和 NET 演练后 我注意到 NET 的所有示例都在 MVC3 中 我正在尝试使用常规 Web 表单将 Braintree 集成到我当前的 NET
  • 仅当单击复选框时才更改 ListViewItem 的选中状态

    默认情况下 双击 ListViewItem 会切换其选中状态 我只想通过单击项目的复选框或在突出显示项目时按空格键来更改选中状态 这容易做到吗 该解决方案涉及 3 个事件和 1 个 bool 类型的状态变量 private bool inh
  • 在Python中,如果我返回“with”块内,文件仍然会关闭吗?

    考虑以下 with open path mode as f return line for line in f if condition 文件是否会正确关闭 或者是否使用return以某种方式绕过上下文管理器 https docs pyth
  • 转换不同世纪的日期

    我有暂存表 其中包含格式为 mm dd yy 的字符串形式的日期 我有 Oracle 11g 程序在加载到主表之前将字符串转换为日期格式 我在用着to date 03 20 34 mm dd rr 转换为日期格式 输出错误为 03 20 2
  • 如何从 .Net 打印对话框中删除打印机?

    我正在开发一个 Winforms 应用程序 它允许用户打印一些不同的 Reporting Services 报告 不幸的是 如果用户尝试使用 Adob e PDF 打印机打印为 PDF 则会崩溃 我们无法解决此问题 因此作为解决方案 我们希
  • C++ 中带有 lambda 的简单自定义迭代器

    假设我有一个容器 其中包含int 一个作用于包含以下内容的容器的函数Point 并且我有一个函数可以给出一些int给我相应的Point它代表 想象一下我已经在一些大的场景中索引了场景中的所有点std vector
  • 如何让一个 Flask 应用程序监听两个不同的端口?

    是否可以有一个单一的 Flask 应用程序 其路由位于两个不同的端口上 我的 Flask 应用程序需要侦听 Webhooks 并且由于某些安全原因 它无法在默认端口上接收外部 POST 请求 可以做这样的事情吗 app route hook
  • Device.BeginInvokeOnMainThread 的用途是什么?

    我希望有人向我解释什么是 Device BeginInvokeOnMainThread 以及它的用途是什么 还有一些使用案例的示例 只是添加一个例子 假设你有一个异步方法DoAnyWorkAsync如果你这样称呼它 仅作为示例 DoAnyW
  • 如何在 mySQL 中定义自定义 ORDER BY 顺序

    在 MySQL 中如何定义自定义排序顺序 为了尝试解释我想要的内容 请考虑这张表 ID Language Text 0 ENU a 0 JPN b 0 DAN c 1 ENU d 1 JPN e 1 DAN f 2 etc 在这里 我想返回
  • 如何将日期格式设置为 1900 年代?

    我正在预处理数据 一列代表日期 例如 6 1 51 我正在尝试将字符串转换为日期对象 到目前为止我所拥有的是 date row 2 strip format m d y datetime object datetime strptime d
  • 使用 Android 数据绑定时,如何通过 xml 为自定义 setter 传递多个参数

    假设我有一个自定义 setter 方法 其中需要两个参数 BindingAdapter imageUrl placeholder public static void loadImage ImageView imageView String
  • 将对象传递给 uibinder 中定义的小部件的构造函数

    我试图将我的应用程序的 EventBus 通过其构造函数传递给 UiBinder 中声明的小部件 我使用 UiConstructor 注释来标记接受 EventBus 的构造函数 但我不知道如何从 ui xml 代码中实际引用该对象 也就是
  • QuantLib:构建关键利率风险

    我能够为国债市场建立一条贴现曲线 然而 我希望用它来找出单个债券 最终是债券投资组合 的关键利率风险 我正在寻找的关键利率风险是 如果我拥有 30 年期债券 并且我们改变用于贴现债券的 1 年期利率 同时保持其他利率不变 那么债券的价格会变
  • 原生C有通用符号吗?

    在GCC10中 gcc默认为fno common 这意味着 所有暂定定义的符号都不通用 我认为gcc符合C规范 但本地C程序中似乎没有通用符号 通用符号仅适用于扩展语法吗 原生C有通用符号吗 阅读C11标准n1570 https web c
  • 防止用户在 javascript 中离开我的页面

    在我的表单中 我有一个不显眼的情态 如果用户单击我的 离开图像 我会打开模式并询问他是否想离开 如果用户同意 JavaScript Jquery 是否可以 停止 重新加载或页面更改以显示我的模式并继续操作 重新加载 下一页 上一页等 I t
  • Stripe 创建使用记录错误 - 时间戳必须早于订阅的当前周期结束时间 - Date.now()?

    我正在尝试为按计量计划的客户创建条带使用记录 当我在请求中使用时间戳 Date now 时 我收到的错误是 无法使用此时间戳创建使用记录 因为时间戳必须早于订阅的当前周期结束时间 这似乎是不言自明的 但考虑到订阅的当前周期结束时间还剩 14
  • 用于检查属性是否适用的 React 函数是什么? [复制]

    这个问题在这里已经有答案了 基于此问答 React 包装器 React 无法识别 DOM 元素上的 staticContext 属性 https stackoverflow com questions 49358560 react wrap
  • PowerShell,使用 Start-Job 和 Start-Process 测试异步任务的性能/效率

    我很想测试 PowerShell 中异步任务的性能 有用性Start ThreadJob Start Job and Start Process 我有一个包含大约 100 个 zip 文件的文件夹 因此进行了以下测试 New Item 00