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

Winfetch 2.1.0 taking ages to get disk info #93

Closed
AwesomeCronk opened this issue Jul 5, 2021 · 27 comments · Fixed by #94
Closed

Winfetch 2.1.0 taking ages to get disk info #93

AwesomeCronk opened this issue Jul 5, 2021 · 27 comments · Fixed by #94
Labels
enhancement Enhance an existing feature help wanted Extra attention is needed

Comments

@AwesomeCronk
Copy link
Contributor

Following the release of winfetch 2.0.0 or something close to that, I have noticed that winfetch hangs somewhere between printing RAM info and pritnign disk info. I usually Ctrl+C it after about 5 seconds, but I left it running once and PS reported roughly 50 seconds to get through it.

I am using PowerShell 7, winfetch 2.1.0, Windows 10, disk is 1 TB WD Blue SSD.

@rashil2000
Copy link
Member

Can you try commenting out all the segments, except the disk info in the config file?

Also, does it happen every time in a session, or just once in a session?

@AwesomeCronk
Copy link
Contributor Author

AwesomeCronk commented Jul 6, 2021

Happens every time in a session.

As for the config, if I comment out every line there except "disk", then run winfetch (whether in a new session or not), it prints out the error message function 'info_diskblank colorbar' not found. If I uncomment the "colorbar" option along with "disk", then run winfetch, it prints the Windows logo, then hangs without any output. If I comment out "disk" and leave only "colorbar" uncommented, it prints out the same error message function 'info_diskblank colorbar' not found. If I comment out only "disk" and leave everything else as-is, winfetch works fine.

Please note that anything that is commented out by default was left commented out the whole time.

@AwesomeCronk
Copy link
Contributor Author

Just tried commenting out only "colorbar" and it still hangs.

@rashil2000
Copy link
Member

Please paste your config file here, I'd like to test it on my system.

@AwesomeCronk
Copy link
Contributor Author

I will tomorrow when I can get back to my computer.

If it helps I did use Scoop to install winfetch (not a global installation).

@AwesomeCronk
Copy link
Contributor Author

config.txt

Here's the version right now that works. Just uncomment the line for "disk" (line 64) and it hangs. I uploaded the file as a .txt so that GitHub would let me paste it, you can just set the extension back to .ps1.

@rashil2000
Copy link
Member

The config file works fine here. Maybe the disk function is problematic. Can you run the following function and paste the output here?

$showdisks = @($env:SystemDrive)

[System.Collections.ArrayList]$lines = @()

function to_units($value) {
	if ($value -gt 1tb) {
		return "$([math]::round($value / 1tb, 1)) TiB"
	} else {
		return "$([math]::floor($value / 1gb)) GiB"
	}
}

$disks = Get-CimInstance -ClassName Win32_LogicalDisk -Property Size, FreeSpace

foreach ($diskInfo in $disks) {
	foreach ($diskLetter in $showDisks) {
		if ($diskInfo.DeviceID -eq $diskLetter -or $diskLetter -eq "*") {
			$total = $diskInfo.Size
			$used = $total - $diskInfo.FreeSpace
			if ($total -gt 0) {
				$usage = [math]::floor(($used / $total * 100))
				[void]$lines.Add(@{
						title   = "Disk ($($diskInfo.DeviceID))"
						content = "$(to_units $used) / $(to_units $total) ($usage%)"
					})
			}
			break
		}
	}
}

return $lines

This will tell if the SystemDrive (usually C:) is getting read properly. If this runs fine, replace $env:SystemDrive with "*" and paste the output here.

@AwesomeCronk
Copy link
Contributor Author

AwesomeCronk commented Jul 9, 2021

Here is the output of the original function:

Name                           Value
----                           -----
title                          Disk (C:)
content                        103 GiB / 930 GiB (11%)

Here is the output of the modified function:

Name                           Value
----                           -----
title                          Disk (C:)
content                        103 GiB / 930 GiB (11%)

The first function took roughly 20 seconds to run each time, new session or not. The second function only took about 15 seconds to run but if I ran it multiple times in the same session it ran instantaneously each time after the first. The time for the first function did not change if I ran it multiple times in the same session.

@rashil2000
Copy link
Member

Looks like the WMIC call itself is very slow on your system - I don't think there's any way to fix it in winfetch since it's the only possible method for getting all the disk info.

Regarding the discrepancy between $env:SystemDrive and "*", well, I'm stumped. @jcwillox any clue?

@AwesomeCronk
Copy link
Contributor Author

I can confirm, running Get-CimInstance -ClassName Win32_LogicalDisk -Property Size, FreeSpace takes a long time to complete. I'll have to look into that...

@rashil2000
Copy link
Member

Yeah, WMIC is weird in it's own way. For example, the command Get-CimInstance Win32_PerfFormattedData_PerfOS_System -Property SystemUptime (used in legacy winfetch) takes full 25 seconds on my system (subsequently instantaneous).

@AwesomeCronk
Copy link
Contributor Author

.NET drives me up the wall sometimes...

@rashil2000
Copy link
Member

...I don't know what WMIC is written in, but how is it related to .NET?

@AwesomeCronk
Copy link
Contributor Author

The problem here is that PowerShell compiles down to .NET runtime during operation (afaik) and the .NET runtime's binding to the WMIC is extraordinarily convoluted.

See https://community.spiceworks.com/topic/1417087-poor-performance-with-cim-commands
image

@rashil2000
Copy link
Member

I don't think .NET is the culprit here, because running the command wmic path Win32_PerfFormattedData_PerfOS_System get SystemUptime in Command Prompt takes the same amount of time. I'd say try running wmic path Win32_LogicalDisk get Size,Freespace in your command prompt, it'll still take the same time as before.

@AwesomeCronk
Copy link
Contributor Author

AwesomeCronk commented Jul 9, 2021

I will try that. I may also start looking for ways to get this data without WMIC, possibly through a system dll.

@jcwillox
Copy link
Member

Regarding the discrepancy between $env:SystemDrive and "*", well, I'm stumped. @jcwillox any clue?

There shouldn't be any difference between using these, if there appears to be then it's probably related to something else.

PowerShell is based in .NET, (I've heard that's one of the reasons it's so slow to startup) and the methods it calls are using the .NET methods, but it's unlikely that these methods would behave differently on different systems. My guess is that it's caused by the underlying WMI interface, which is separate from PowerShell and .NET. I'm not sure why it would be so slow unless you have to some odd hardware configuration, like lots or drives or something.

There are ways to fetch disk information without WMI, such as this, however, I'm not sure how easy it would be to implement in PowerShell, as the language really struggles to do complex or low-level interactions.

@AwesomeCronk
Copy link
Contributor Author

AwesomeCronk commented Jul 12, 2021

@jcwillox maybe winfetch could break out to C# for low level operations like that. I’m not 100% sure what they’re doing because I don’t know Go at all, but I think C# has a better handle on low level stuff and I know it can run dll calls.

@rashil2000
Copy link
Member

rashil2000 commented Jul 12, 2021

...as the language really struggles to do complex or low-level interactions.

That's not really true, in fact, PowerShell is the only shell/scripting language that allows using DLLs directly. And it's fairly easy, see
https://github.com/rashil2000/scripts/blob/b5707ec7e4ee20576ad28bb6f08ab94c49b630ed/ThemeSwitch.ps1#L3-L12
and
https://github.com/rashil2000/scripts/blob/b5707ec7e4ee20576ad28bb6f08ab94c49b630ed/ThemeSwitch.ps1#L31
for a tiny example.
@AwesomeCronk is right. Of course this requires that you already know .NET or C# quite well, to use those low-level calls in the first place. I don't know either, to be frank.

@jcwillox
Copy link
Member

That's not really true, in fact, PowerShell is the only shell/scripting language that allows using DLLs directly. And it's fairly easy, see

That's not technically using PowerShell, but yes using C# would probably be your best bet.

@rashil2000 rashil2000 added enhancement Enhance an existing feature help wanted Extra attention is needed labels Jul 12, 2021
@AwesomeCronk
Copy link
Contributor Author

I have fiddled with PS/C# and DLLs before. I read through that Go code again and saw references to GetDiskFreeSpaceExW, GatLogicalDriveStringsW, GetDriveTypeW, and GetVolumeInformationW, all from kernel32.dll. I am going to see if I can hack something together to call these and then maybe make a PR with it.

@rashil2000
Copy link
Member

That'd be awesome

@AwesomeCronk
Copy link
Contributor Author

All we need is an array of drive letters and their free space/total space, right?

@rashil2000
Copy link
Member

rashil2000 commented Jul 13, 2021

Precisely!

@AwesomeCronk
Copy link
Contributor Author

AwesomeCronk commented Jul 13, 2021

Sweet! I think I have what I need, I’m going to rename the function for drive usage to something like diskusage-old and write up a version using API calls.

@rashil2000
Copy link
Member

Looking forward to it!

(if you need to refer a script that uses C#, look no further than PS2Exe; it's one behemoth of an example!)

@AwesomeCronk
Copy link
Contributor Author

AwesomeCronk commented Jul 13, 2021

I think I got the whole deal working now. I put the C# code in disk_info, though it may fit better near the top of the script alongside general variable definitions if anything else winds up using the API in the future. I went ahead and moved it to the VARIABLES section.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Enhance an existing feature help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants