devblackops / Terminal-Icons

A PowerShell module to show file and folder icons in the terminal
MIT License
2.48k stars 109 forks source link

Slow import #13

Closed rashil2000 closed 3 years ago

rashil2000 commented 4 years ago

Import-Module Terminal-Icons command takes a usually 2-3 seconds, and therefore slows down the PowerShell load times when put in the '$PROFILE'. I'm on pretty beefy machine so hardware is not an issue.

Expected Behavior

It shouldn't take that long.

Current Behavior

The output of Measure-Command { Import-Module Terminal-Icons } is 'TotalMilliseconds : 2118.1497' for example.

Possible Solution

I think the culprit is the 'Terminal-Icons/Data/glyphs.ps1' file. It's too long and most of the nerd font icons aren't even used. To decrease load time we should source only those icons that are being used in the 'Terminal-Icons/Data/iconThemes/devblackops.psd1' file.

Context

PowerShell ends up taking too long to start, which hampers its usage.

Your Environment

rashil2000 commented 4 years ago

After a bit of struggle I find out that only 84 of the 3810 glyphs imported were actually being used in devblackops.psd1 file.

Here's the shortened glyphs.ps1 file.


@{
    'nf-fa-folder'                                   = ''
    'nf-mdi-folder_image'                            = ''
    'nf-custom-folder_config'                        = ''
    'nf-custom-folder_git'                           = ''
    'nf-custom-folder_github'                        = ''
    'nf-fa-file'                                     = ''
    'nf-oct-person'                                  = ''
    'nf-seti-json'                                   = ''
    'nf-fa-gitlab'                                   = ''
    'nf-mdi-xml'                                     = '謹'
    'nf-fa-gear'                                     = ''
    'nf-dev-npm'                                     = ''
    'nf-fae-checklist_o'                             = ''
    'nf-dev-bower'                                   = ''
    'nf-dev-travis'                                  = ''
    'nf-fa-file_o'                                   = ''
    'nf-seti-favicon'                                = ''
    'nf-dev-gulp'                                    = ''
    'nf-dev-firebase'                                = ''
    'nf-mdi-library_books'                           = ''
    'nf-mdi-certificate'                             = ''
    'nf-dev-jenkins'                                 = ''
    'nf-dev-docker'                                  = ''
    'nf-mdi-vuejs'                                   = '﵂'
    'nf-dev-bitbucket'                               = ''
    'nf-dev-nodejs_small'                            = ''
    'nf-dev-git'                                     = ''
    'nf-mdi-azure'                                   = 'ﴃ'
    'nf-mdi-check_circle'                            = '﫟'
    'nf-dev-erlang'                                  = ''
    'nf-oct-ruby'                                    = ''
    'nf-dev-javascript'                              = ''
    'nf-mdi-xaml'                                    = 'ﭲ'
    'nf-mdi-file_excel'                              = ''
    'nf-seti-typescript'                             = ''
    'nf-dev-php'                                     = ''
    'nf-dev-sublime'                                 = ''
    'nf-mdi-visualstudio'                            = '﬏'
    'nf-dev-markdown'                                = ''
    'nf-mdi-language_csharp'                         = ''
    'nf-oct-file_zip'                                = ''
    'nf-dev-less'                                    = ''
    'nf-dev-terminal_badge'                          = ''
    'nf-fa-file_video_o'                             = ''
    'nf-fa-certificate'                              = ''
    'nf-seti-html'                                   = ''
    'nf-dev-rust'                                    = ''
    'nf-mdi-language_c'                              = 'ﭰ'
    'nf-dev-sass'                                    = ''
    'nf-oct-terminal'                                = ''
    'nf-fa-lock'                                     = ''
    'nf-dev-visualstudio'                            = ''
    'nf-dev-code_badge'                              = ''
    'nf-mdi-file_pdf'                                = ''
    'nf-mdi-file_word'                               = ''
    'nf-fa-key'                                      = ''
    'nf-mdi-svg'                                     = 'ﰟ'
    'nf-dev-css3'                                    = ''
    'nf-dev-perl'                                    = ''
    'nf-custom-msdos'                                = ''
    'nf-dev-dart'                                    = ''
    'nf-dev-clojure'                                 = ''
    'nf-dev-database'                                = ''
    'nf-mdi-application'                             = 'ﬓ'
    'nf-fa-archive'                                  = ''
    'nf-dev-go'                                      = ''
    'nf-dev-haskell'                                 = ''
    'nf-mdi-file_powerpoint'                         = ''
    'nf-mdi-file_document'                           = ''
    'nf-dev-react'                                   = ''
    'nf-custom-elixir'                               = ''
    'nf-fa-calendar'                                 = ''
    'nf-seti-lua'                                    = ''
    'nf-dev-groovy'                                  = ''
    'nf-dev-fsharp'                                  = ''
    'nf-dev-apple'                                   = ''
    'nf-fa-file_audio_o'                             = ''
    'nf-mdi-help_box'                                = 'ﲉ'
    'nf-mdi-language_cpp'                            = 'ﭱ'
    'nf-fa-file_image_o'                             = ''
    'nf-custom-elm'                                  = ''
    'nf-mdi-format_align_left'                       = ''
    'nf-fa-font'                                     = ''
    'nf-mdi-view_list'                               = '况'
}

We can use this. If users want to add more icons to their custom icon themes, they can just append their icons to this file.

devblackops commented 4 years ago

Thanks for the issue @rashil2000. In limited testing on my machine, I see that loading the module and just loading the glyphs in a new PowerShell instance takes the following:

Commands:

pwsh -nop -c '(Measure-Command { Import-Module Terminal-Icons }).TotalMilliseconds'
powershell -nop -c '(Measure-Command { Import-Module Terminal-Icons }).TotalMilliseconds'
pwsh -nop -c '(Measure-Command {$g = . C:\Users\Brandon\Documents\PowerShell\Modules\Terminal-Icons\0.1.1\Data\glyphs.ps1}).TotalMilliseconds'
powershell -nop -c '(Measure-Command {$g = . C:\Users\Brandon\Documents\PowerShell\Modules\Terminal-Icons\0.1.1\Data\glyphs.ps1}).TotalMilliseconds'
Task Pwsh Version Time (ms)
Module import PowerShell 7.0.3 1422.1564
Module import Windows PowerShell 5.1.19041.546 1224.1456
Glyph import PowerShell 7.0.3 50.802
Glyph import Windows PowerShell 5.1.19041.546 38.2479

It doesn't look like loading the glyphs is the primary cause of slow loading. We'll have to dig in a bit more.

rashil2000 commented 4 years ago

@devblackops I was about to say this! Perhaps I judged the glyphs.ps1 too quickly. I tested by putting the modified file I mentioned above, and it hadn't affected the import time at all.

There might be something else that's holding this back then, because 1.5-2 seconds is still a lot of time.

ajhall commented 4 years ago

I've noticed this too, and it seems to be something happening inside the Configuration module. These two lines account for most of the slowdown (especially the Export-Configuration line):

https://github.com/devblackops/Terminal-Icons/blob/7b4ce017831605de8ec561dd70f99079ae8f3b0d/Terminal-Icons/Terminal-Icons.psm1#L87

https://github.com/devblackops/Terminal-Icons/blob/7b4ce017831605de8ec561dd70f99079ae8f3b0d/Terminal-Icons/Terminal-Icons.psm1#L129

It seems to do quite a bit of work every time the module is initially imported to import and re-export the Configuration.psd1 file.

ajhall commented 4 years ago

https://github.com/PoshCode/Configuration/pull/39

I made a pull request to the Configuration module with some decent performance improvements. I don't think it'll fix the entire delay on startup, but it definitely helps.

rashil2000 commented 4 years ago

@ajhall Looks like the repo you sent a PR to hasn't seen a commit in a couple of years. It's no longer maintained :(

Is it possible to bake in the module here itself instead of having a dependency?

ajhall commented 4 years ago

There are a couple quick fixes you could make locally:

  1. You should have a local copy of Metadata.psm1 at ~\Documents\PowerShell\Modules\Configuration\1.3.1\Metadata.psm1 that you can manually edit to apply the change I suggested in the pull request.
  2. If you're fine with the built-in theme, you can edit ~\Documents\PowerShell\Modules\Terminal-Icons\0.1.1\Terminal-Icons.psm1 to comment out the two lines I mentioned in https://github.com/devblackops/Terminal-Icons/issues/13#issuecomment-711348699. That will make it skip over the slowest parts entirely.

Anything beyond that might require @devblackops to rework the way this module saves and loads its configuration, so I can't speak to that 😄

devblackops commented 4 years ago

I did a quick experiment with storing the current theme that's saved at $env:APPDATA/powershell/Community/Terminal-Icons/Configuration.psd1 as JSON instead of PSD1. There is a noticeable improvement in module load times by using ConvertTo-Json/ConvertFrom-Json vs Import-Configuration/Export-Configuration for getting/saving the selected theme.

By changing the theme format and removing the dependency on the Configuration module I was able to get module load times down to 360ms vs 1200ms

pwsh -nop -c '(measure-command {ipmo terminal-icons -requiredversion 0.1.1}).TotalMilliseconds'
1290.3601
pwsh -nop -c '(measure-command {ipmo terminal-icons -requiredversion 0.2.0}).TotalMilliseconds'  
361.3216

I'll have to play with this some more to make everything works as expected but on the face of it, I think this is a pretty good improvement.

devblackops commented 4 years ago

@rashil2000 @ajhall. Can run both try pulling the latest and running .\build.ps1 -task build and testing out 0.2.0 in the output directory? I've decided to use Import/Export-CliXml instead of storing the current theme in JSON. This is so the module will work with < PowerShell 6.0 since ConvertFom-Json -AsHashtable was introduced in 6.0 and I'd like to keep compatibility with other versions.

rashil2000 commented 4 years ago

I am getting this error The term 'Set-BuildEnvironment' is not recognized as the name of a cmdlet, function, script file, or operable program. Do I need to install any module for building?

devblackops commented 4 years ago

Yes, the build dependencies. Try:

.\build.ps1 -task build -bootstrap

rashil2000 commented 4 years ago

Okay, so I built the module. It's significantly faster now.

PS > (Measure-Command { Import-Module 'C:\Users\RashilGandhi\3D Objects\Terminal-Icons\Output\Terminal-Icons\0.2.0\Terminal-Icons.psd1' }).TotalMilliseconds
1032
ajhall commented 4 years ago

Looks good here too:

❯ (Measure-Command { Import-Module '.\Terminal-Icons.psd1' }).TotalMilliseconds
320.1912
rashil2000 commented 3 years ago

@devblackops Is the new (improved) version not going to be released?

devblackops commented 3 years ago

@rashil2000 v0.2.0 has just been released to PSGallery!

devblackops commented 3 years ago

@rashil2000 v0.2.0 has just been released to [PSGallery!

nstrelow commented 3 years ago

I feel like this is still very slow on startup Anything to be done about it?

Or maybe the update did not work for me and I need to reset something? I am on 0.2.2

devblackops commented 3 years ago

@nstrelow What are the import times you're experiencing?

Also, what is in $env:USERPROFILE/AppData/Roaming/powershell/Community/Terminal-Icons? Do you have theme.xml and nothing else? If there is a psd1 file in there, try removing it or renaming it to a different extension.

nstrelow commented 3 years ago

OMG this is so much better.

Terminal starting went down from 2000ms to 1100ms.

Thanks a lot. Maybe this should be mentioned somewhere, so thst Others also experience the boost :D

Dumb old files laying around.

devblackops commented 3 years ago

Good to hear. Sounds like some logic needs to be updated to not load the psd1 if it exists.