Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimizations #153

Open
9 of 16 tasks
Carterpersall opened this issue Sep 13, 2022 · 0 comments
Open
9 of 16 tasks

Optimizations #153

Carterpersall opened this issue Sep 13, 2022 · 0 comments

Comments

@Carterpersall
Copy link
Contributor

Carterpersall commented Sep 13, 2022

This will be where I keep track of the improvements to Winfetch I make in various pull requests

How I achieve my speed improvements:

  • Assume anything CIM and WMI will be slow and avoid it like the devil
  • Piping is slow, so avoid using it when possible (do $e.Name instead of $e | Select-Object Name)
  • Use https://github.com/nohwnd/Profiler and import generated JSON files into https://www.speedscope.app/ or view results directly in PowerShell
    • Shows which functions take the longest, but not what operations within the function take the longest. That takes looking into the function yourself and heavily leveraging Measure-Command
  • I downclock my laptop hard (1.06 GHz) to get more battery life out of it. But what ends up happening with PowerShell is that slow operations take a very long time to execute, making speed differences much more noticeable
  • Use preexisting values wherever possible
  • Google things a lot. Even if you think you know how to do something fast, there may be a faster or easier solution out there
  • Always investigate using a .NET library instead of a PowerShell command or CIM/WMI call, but don't assume that it will be faster
  • $null = operation > [void]operation > operation | Out-Null
  • Always check if $var | ForEach-Object or $variable.foreach() is faster
  • Check if using [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey() is faster than Get-ItemProperty.

Notes to self:

  • Keep an eye on the speed improvement of creating a CIM Instance
    • Currently negligible or faster in both slow and fast systems using both all functions and my personal config

TODO:

  • Improve the beginning of the script
    • Add more arguments
    • Perform checks for variables only used in some functions
      • Implementing for the initial CIM declaration leads to speed regression
        • Checks for config values need to be almost negligible to be worth it
    • Create more variables for commands used in multiple functions
    • More and faster environment checking
  • Improve the functions
    • info_ps_pkgs
    • info_pkgs
    • info_gpu
    • info_cpu_usage
    • info_locale
    • info_weather
    • info_local_ip
    • info_memory
      • Attempted to reverse engineer Get-CimInstance
        • Initially tried (([System.Management.ManagementObjectSearcher]::new(([System.Management.ObjectQuery]::new("SELECT TotalVisibleMemorySize,FreePhysicalMemory FROM Win32_OperatingSystem")))).Get())
          • ~10ms slower (30ms → 40ms)
        • Then tried $cimSession.GetInstance("root/cimv2","Win32_OperatingSystem").CimInstanceProperties
          • ~18ms slower (30ms → 48.6)
          • Slower because it isn't grabbing specific properties, instead it is grabbing all of them
          • I later found $cimSession.EnumerateInstances("root/cimv2","Win32_OperatingSystem") which does the same thing but at about half the speed
        • After diving into how Get-CimInstance worked, I made $cimSession.QueryInstances("root/cimv2","WQL","SELECT TotalVisibleMemorySize,FreePhysicalMemory FROM Win32_OperatingSystem")
          • ~10ms slower (30 → 40ms)
          • The weird thing with this one is that this should be almost exactly what Get-CimInstance uses, except that it uses CimSession.QueryInstancesAsync() instead
        • Using my new knowledge of how Get-CimInstance worked, I then attempted to optimize the execution of the command
          • First tried defining the flags -QueryDialect WQL -Namespace root/cimv2 in an attempt to prevent the function from needing to retrieve it
            • Ended up decreasing speed extremely slightly
          • Then tried replacing the flags -ClassName Win32_OperatingSystem -Property TotalVisibleMemorySize,FreePhysicalMemory with -Query "SELECT TotalVisibleMemorySize,FreePhysicalMemory FROM Win32_OperatingSystem" to prevent the code from generating the query
            • Caused a very slight speed increase (<1ms)
          • Then I got curious and checked what the speed is when I removed -CimSession $cimSession
            • Ended up saving ~1ms somehow
            • Might not show this speed gain in the script though, as the reuse of the CimSession might be what it's missing here
  • Implement multithreading
  • Look into incorrect resolution being reported

Speed Improvement (Excluding Multithreading):
Before:

After (Subtracting Speed Gains):

  • 11444 ms
    • 63% Faster w. everything enabled
@Carterpersall Carterpersall mentioned this issue Sep 13, 2022
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant