Por que o Powershell é tão lento?

5

Eu tentei fazer uma coisa simples com o PowerShell, encontrar arquivos que ocupam mais espaço na unidade. Eu usei ls + sort e ... demorou muito para mim.

Às vezes, uso o gerenciador remoto e, comparado com o PowerShell, parece muito mais rápido e estável.

Ok, é baseado no .NET, mas o .NET não é tão lento. Eu espero ver algo leve e rápido! É console!

Outra coisa, gostaria de ter algo como IEnumerable no PowerShell para ver os resultados imediatamente. É possível conseguir? Pode ajudar um pouco enquanto espero resultados, às vezes acho que é só sair.

EDITAR

Estou fazendo algo assim

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

E eu acho que pode levar DAYS.

EDITAR

Apenas para comparar.

O código c # demorou cerca de 2 min. Com certeza não é ideal e não processou todos os arquivos, mas processou pelo menos > 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;
    }
}
    
por Neir0 13.05.2016 / 03:47

2 respostas

11

O PowerShell é um programa escrito em .Net, mas utiliza interfaces para muitos intérpretes e tempos de execução diferentes quando está em execução. É um Shell, assim como o BASH, mesmo que esteja escrito em C, que não diz nada sobre os binários e scripts executados nele. Os executáveis podem ser código .Net, comandos VDM / CMD, comandos shell do * nix, VB / C / WSScript, invocações do WMI, interfaces de API não gerenciadas, arquivos jar ou qualquer outra coisa. Essas opções afetam o desempenho do código em execução no shell, não a linguagem em que o shell está escrito.

Agora, parece que você está tendo dificuldades com a implementação de um comando específico. Portanto, a melhor pergunta é: por que ls é lento para classificar quando chamado de dentro do PowerShell. Quando nos aprofundamos, descobrimos que ls é um alias para 'Get-ChildItem' que retorna uma matriz de objetos contendo objetos 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>

Você pode recuperar o resultado ls e enviá-lo para uma chamada Sort-Object e vai se comportar em grande parte da maneira que um IEnumerable faz.

Observe que IEnumerable não faz nada pelo desempenho. Você pode estar confundindo-o com o IQueryable, que define mas não executa uma consulta até o último segundo, presumivelmente depois de ter sido decorado com operações de filtragem e classificação, da maneira como o .Net faz via LinQ to Objects. Nesse caso, como Get-ChildItem não oferece um mecanismo de consulta otimizado ou fonte de dados indexada, você não pode comparar as operações modernas do banco de dados com as listagens de diretório.

Então, finalmente, tente algo como: %código% Para mim, segmentação System32, isso leva cerca de 20 segundos para processar e classificar 54430 arquivos.

Por fim, observe que você recebe um grande impacto no desempenho ao tentar enumerar um diretório ao qual não tem acesso pessoal, por isso, certifique-se de não recorrer a lugares para os quais não tem permissão de ir. sofrer uma espera de 2 + segundos para cada um.

Espero que ajude.

    
por 14.05.2016 / 00:26
5

O PowerShell foi criado para ser conveniente e não rápido. É uma troca - funciona nos bastidores, então o usuário precisa fazer menos. Fazer mais trabalho torna isso mais lento.

Veja que o seu código PowerShell é uma linha, para fazer mais do que o código C # em 15 linhas.

Ele faz mais - mesmo que você não esteja usando isso.

ls no Linux retorna strings, strings são simples e rápidas. Seu código .Net nem sequer mantém o nome do arquivo, apenas mantém o tamanho, e os números são menores novamente, então isso é ainda mais rápido .

ls no PowerShell, retorna objetos [FileInfo] e [DirectoryInfo] - cada um precisa ser criado e cada um precisa consultar o arquivo para preencher os outros campos, como CreationTime e LastWriteTime e extensão e comprimento, e os campos de hora têm que criar objetos [DateTime].

Isso é muito mais lento para todos os arquivos. Custos para permitir outras opções, mesmo quando você não as estiver usando - o código do PowerShell pode mudar para ter o tamanho dos primeiros 10 arquivos feitos em janeiro com uma alteração simples, sem outros cmdlets ou ferramentas, e ainda ser uma linha, o código C # teria que ser reescrito extensivamente, consultar o tempo de criação, levar o tempo de criação e o tamanho para a classificação e assim por diante.

O motivo pelo qual você não vê resultados imediatamente é porque você | sort . Isso torna isso impossível. E se você começou a produzir resultados imediatamente, mas o último arquivo encontrado precisa classificar para a frente? Em seguida, a saída seria errada - IEnumerable não pode fazer nada sobre isso, | sort tem que reunir todas as entradas antes de poder produzir qualquer coisa. Seu tipo é mais rápido porque está classificando as coisas pequenas

Seu código .Net pode fazer a classificação em si mais rapidamente porque está classificando um enumerável de [long], ele não precisa fazer nenhuma pesquisa de propriedade.

No geral, seu código faz muito menos e fazer menos leva menos tempo. Mas você demorou mais para escrever e é menos flexível e mais focado. Uma troca.

    
por 23.09.2017 / 23:40