Skip to content

Optimizations #153

@Carterpersall

Description

@Carterpersall

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions