Вопрос Почему Powershell так медленно?


Я попытался сделать простую вещь с PowerShell, найти файлы, которые занимают больше места на диске. я использовал ls + sort и ... это заняло навсегда для меня.

Иногда я использую дальний менеджер и по сравнению с PowerShell выглядит намного быстрее и стабильнее.

Хорошо, он основан на .NET, но .NET не так медленен. Я ожидаю увидеть что-то легкое и быстрое! Это консоль!

Другое дело, я хотел бы иметь что-то вроде IEnumerable в PowerShell, чтобы сразу увидеть результаты. Можно ли достичь? Это может немного помочь в ожидании результатов, иногда я думаю, что это просто болтается.

РЕДАКТИРОВАТЬ

Я делаю что-то вроде этого

ls -Recurse -ErrorAction SilentlyContinue | sort -Property Size | select -First 10

И я думаю, это может занять ДНИ.

РЕДАКТИРОВАТЬ

Просто для сравнения.

Код C # занял у меня около 2 мин. Конечно, он не идеален и не обрабатывает все файлы, но обрабатывается как минимум> 95%.

void Main()
{
    GetFilesSize(@"C:\").OrderByDescending(x => x).Take(10).ToList();
}

public IEnumerable<long> GetFilesSize(string directory)
{
    var accessDenied = false;
    var dirList = new string[0]; 
    try
    {
        dirList = Directory.GetDirectories(directory);
    }
    catch{
        accessDenied = true;
    }

    if(accessDenied) yield break;

    foreach (var dir in dirList)
    {
        foreach (var size in GetFilesSize(dir))
        {
            yield return size;
        }
    }

    foreach (var fileName in Directory.GetFiles(directory))
    {
        if(fileName.Length>=260) continue;
        yield return new FileInfo(fileName).Length;
    }
}

4
2018-05-13 01:47


происхождения


«Другое дело ...» «Нет, пожалуйста, нет! Не задавайте второй вопрос, который будет генерировать дополнительные / разные / несвязанные ответы в том же вопросе. Просто создайте новый вопрос SuperUser. - TOOGAM
было бы очень полезно увидеть ваш код, который «настолько медленный», потому что, возможно, это не PowerShell, это медленный, скорее ваш код! - SimonS
Добро пожаловать в Суперпользователь! Пожалуйста, попробуйте задать один вопрос одновременно (в противном случае ваш вопрос будет закрыт как слишком широкий). - DavidPostill♦
@Ramhound Если вы внимательно читаете мои комментарии, вы можете видеть, что я жалуюсь на производительность PowerShell, а не .net. .NET упоминается как база powershell, которая работает быстрее. Не уверен относительно общего количества файлов, я пытаюсь отсканировать весь диск. Поэтому я думаю, что там тысячи файлов. - Neir0
@Ramhound Я вычислил: 556458 - Neir0


ответы:


PowerShell - это программа, написанная на .Net, но она использует интерфейсы для многих разных интерпретаторов и времени выполнения, когда она фактически запущена. Это оболочка, так же, как и BASH, даже если она написана на C, которая ничего не говорит о исполняемых файлах и скриптах. Исполняемыми файлами могут быть: .Net-код, команды VDM / CMD, команды * nix shell, VB / C / WSScript, WMI-вызовы, неуправляемые интерфейсы API, файлы jar или что-то еще. Эти варианты влияют на производительность кода, выполняющегося внутри оболочки, а не на том, на каком языке написана оболочка.

Теперь, похоже, что у вас возникают трудности с реализацией конкретной команды. Поэтому лучший вопрос: почему ls медленно сортировать при вызове из PowerShell. Когда мы копаем глубже, мы обнаруживаем, что ls является псевдоним для 'Get-ChildItem', который возвращает массив объектов, содержащий объекты System.IO.DirectoryInfo.

PS C:\Windows\system32> $x=Get-ChildItem ./
PS C:\Windows\system32> $x.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array 

PS C:\Windows\system32> $x[1].GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DirectoryInfo                            System.IO.FileSystemInfo   

PS C:\Windows\system32>

Вы можете получить ls результата, а затем Sort-Object  вызов и он будет вести себя в основном так, как это делает IEnumerable.

Обратите внимание, что IEnumerable ничего не делает для производительности. Вы можете смутить его с помощью IQueryable, который определяет, но не выполняет запрос до самой последней секунды, по-видимому, после того, как он был украшен фильтрацией и сортировкой, способом .NET через LinQ в Object. В этом случае, поскольку Get-ChildItem не предлагает оптимизированный механизм запросов или индексированный источник данных, вы не можете реально сравнивать современные операции с базами данных с каталогами.

Итак, в конечном счете, попробуйте что-то вроде: ls ./ -recurse | Sort-Object Name -descending Для меня, ориентируясь на System32, для обработки и сортировки файлов 54430 требуется около 20 секунд.

Наконец, обратите внимание, что вы делаете большой удар производительности, когда пытаетесь перечислить каталог, к которому у вас лично нет доступа, поэтому убедитесь, что вы не возвращаетесь в места, куда вам не разрешено, или вы будете страдать от 2 + второе ожидание для каждого.

Надеюсь, это поможет.


10
2018-05-13 22:26



IEnumerable не дает прироста производительности, но позволяет сразу увидеть результаты. Также в случае powershell это может повысить производительность, например, если «ls» возвращает IEnumerable, он не загружает все дерево файлов в память, что может быть большим накладным. - Neir0
Я попробовал ls +, как вы упомянули в своем посте, я хочу проверить все файлы на диске, но, конечно же, это невозможно сделать, или я думаю, это может занять несколько дней (действительно, потому что я оставил его на ночь и в утром никаких результатов нет). Но, например, если я собираюсь использовать специальные утилиты для проверки пространства на диске, они работают очень быстро. Это моя точка зрения. Все, перемещение, копирование, поиск работает медленно в powershell, и это раздражает. - Neir0
попробуйте перенаправить вывод в файл. диск стандартного объема не должен забираться всю ночь, чтобы перечислить. вы уже на пределе по ОЗУ или диском нездоровым? - Frank Thomas
Не уверен, возможно, что-то не так с приводом, мне нужно сделать дополнительные тесты. У меня есть еще один инструмент (TreeSize), который работает довольно быстро, так что это не так очевидно. - Neir0


PowerShell построен, чтобы быть удобным, а не быстрым. Это компромисс - он работает за кулисами, поэтому пользователю приходится делать меньше. Выполнение большего количества работы замедляет работу.

Посмотрите, что ваш код PowerShell является одной строкой, чтобы сделать больше, чем ваш код C # делает в 15 строках.

Он делает больше - даже если вы этого не используете.

ls на Linux возвращает строки, строки простые и быстрые. Ваш .Net-код даже не сохраняет имя файла, он просто сохраняет размер, а числа меньше, так что даже быстрее,

ls в PowerShell возвращает объекты [FileInfo] и [DirectoryInfo] - каждый из них должен быть создан, и каждый из них должен запросить файл, чтобы заполнить другие поля, такие как CreationTime и LastWriteTime, а также расширение и длина, а также поля времени Объекты [DateTime].

Это намного медленнее для каждого файла. Это стоит того, чтобы включить другие параметры, даже если вы их не используете, - ваш код PowerShell может измениться, чтобы размер первых 10 файлов, сделанных в январе, был простым изменением, другими командлетами или инструментами и все равно быть одной строкой, код C # должен быть сильно переписан, запросить время создания, нести как время создания, так и размер в сортировку и т. д.

Причина, по которой вы не видите результаты сразу, - это то, что вы | sort, Это делает невозможным. Что делать, если вы сразу начали выводить результаты, но последний найденный файл нужно сортировать в начале? Тогда выход будет неправильным - IEnumerable ничего не может с этим поделать, | sort должен собирать каждый вход, прежде чем он сможет вывести что угодно. Ваш вид быстрее, потому что он сортирует мелочи

Ваш .Net-код может быстрее выполнять сортировку, потому что он сортирует перечислимое значение [long], ему не нужно выполнять поиск свойств.

В целом, ваш код делает намного меньше, и меньше занимает меньше времени. Но потребовалось больше времени, чтобы писать и менее гибко и более узко сфокусировано. Компромисс.


2
2017-09-23 21:40