@conJOULA

Скрипт powershell использует слишком много памяти. Что я делаю не так?

Windows 10. PowerShell 7.4.4. Имеется следующий простой скрипт, для примера проблемы, которую я пытаюсь понять:
$threadslimit = 8
$collection = @{}
$synccollection = [System.Collections.Hashtable]::Synchronized($collection)

1..1000 | ForEach-Object {
    $data = @('some', 'valuable', 'text', 'data')
    $synccollection.Add($_, $data)
}

#выводим созданную коллекцию до изменений, просто чтобы можно было сравнить
$synccollection

# Массив ключей для обхода коллекции
$keys = @($synccollection.Keys)

$jobs = @()

foreach ($key in $keys) {
    $jobs += Start-ThreadJob -ScriptBlock {
        param(
            $synccollection,
            $key
        )

        # Здесь на самом деле какая-то функция, которая возвращает строку
        $format = 'Changed data'

        # Изменяем одно из полей, напоминаю, по ключам лежат массивы
        $synccollection[$key][3] = $format

        # Тут вывод чтобы просто отслеживать выполнение скрипта
        Write-Output "Data was changed"

    } -ThrottleLimit $threadslimit -ArgumentList $synccollection, $key
}

foreach ($job in $jobs) {
    $results = Receive-Job -Job $job -Wait
    Write-Host "Job $($job.Name) - $results"
    Remove-Job -Job $job
}

# Вывод самой коллекции в консоль, чтобы убедиться, что значения поменялись
$synccollection


Скрипт вроде работает как надо, но после первого же запуска, память которую занимает процесс pwsh увеличивается в разы:
66b258f5d801e115268281.jpeg
Вот столько процесс занимал до запуска скрипта:
66b2591a8ca89764198451.jpeg

Часть памяти удается освободить при помощи [System.GC]::Collect(), но даже с ним, процесс все ещё остается сильно раздутым:
66b25956d74c0401378249.jpeg
Get-Jobs пустой, если закрыть pwsh, память сразу же освобождается. Размер самой коллекции явно не такой большой, чтобы занимать 1+ГБ оперативки. Что я делаю не так, нагуглить/начатгптиить ответ не получилось.
  • Вопрос задан
  • 359 просмотров
Решения вопроса 1
@conJOULA Автор вопроса
Удалось добиться желаемого поведения использовав другой подход (другую фичу), которая называется ForEach-Object -Parallel. Если кто-то случайно забредёт сюда в поисках ответа, можете попробовать следующее:

$threadslimit = 8
$collection = @{}
$synccollection = [System.Collections.Hashtable]::Synchronized($collection)

1..1000 | ForEach-Object {
    $data = @('some', 'valuable', 'text', 'data')
    $synccollection.Add($_, $data)
}

#выводим созданную коллекцию до изменений, просто чтобы можно было сравнить
$synccollection

$keys = @($synccollection.Keys)

$keys | ForEach-Object -Parallel {
    $synccollectionscope = $using:synccollection

    # Здесь на самом деле какая-то функция, которая возвращает строку
    $format = 'Changed data'

    # Изменяем одно из полей, напоминаю, по ключам лежат массивы
    $synccollectionscope[$_][3] = $format

    # Тут вывод чтобы просто отслеживать выполнение скрипта
    Write-Output "Data was changed"

} -ThrottleLimit $threadslimit

# Вывод самой коллекции в консоль, чтобы убедиться, что значения поменялись
$synccollection


Делает то же самое, использует практически нулевое количество памяти, работает быстрее.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
14 сент. 2024, в 19:08
20000 руб./за проект
14 сент. 2024, в 18:13
7000 руб./за проект
14 сент. 2024, в 18:03
30000 руб./за проект