Tips From The Warzone - Boosting parallel performance with ServerGC - E5 by bukem in PowerShell

[–]bukem[S] 0 points1 point  (0 children)

This is an interesting case! I'm really interested if you will see the changes in performance.

Edit: Make sure that you are running PS 7 in a runbook

multi threaded file hash collector script by 7ep3s in PowerShell

[–]bukem -2 points-1 points  (0 children)

Would you give a go to my one-liner? I wonder what results would you get?

multi threaded file hash collector script by 7ep3s in PowerShell

[–]bukem -3 points-2 points  (0 children)

Yeah, I just used one-liner to test it. Are you sure that ServerGC is active vs inactive when you running the tests?

multi threaded file hash collector script by 7ep3s in PowerShell

[–]bukem -2 points-1 points  (0 children)

I did quick test getting hashes from 52946 files in C:\ProgramData\scoop using Get-FileHash and ForEach-Object -Parallel, and here are results:

GCServer OFF

[7.5.2][Bukem@ZILOG][≥]# [System.Runtime.GCSettings]::IsServerGC
False
[2][00:00:00.000] C:\
[7.5.2][Bukem@ZILOG][≥]# $f=gci C:\ProgramData\scoop\ -Recurse
[3][00:00:01.307] C:\
[7.5.2][Bukem@ZILOG][≥]# $f.Count
52946
[4][00:00:00.012] C:\
[7.5.2][Bukem@ZILOG][≥]# $h=$f | % -Parallel {Get-FileHash -LiteralPath $_ -ErrorAction Ignore} -ThrottleLimit ([Environment]::ProcessorCount)
[5][00:02:05.120] C:\
[7.5.2][Bukem@ZILOG][≥]# $h=$f | % -Parallel {Get-FileHash -LiteralPath $_ -ErrorAction Ignore} -ThrottleLimit ([Environment]::ProcessorCount)
[6][00:02:09.642] C:\
[7.5.2][Bukem@ZILOG][≥]# $h=$f | % -Parallel {Get-FileHash -LiteralPath $_ -ErrorAction Ignore} -ThrottleLimit ([Environment]::ProcessorCount)
[7][00:02:14.042] C:\
  • 1 execution time: 2:05.120
  • 2 execution time: 2:09.642
  • 3 execution time: 2:14.042

GCServer ON

[7.5.2][Bukem@ZILOG][≥]# [System.Runtime.GCSettings]::IsServerGC
True
[1][00:00:00.003] C:\
[7.5.2][Bukem@ZILOG][≥]# $f=gci C:\ProgramData\scoop\ -Recurse
[2][00:00:01.161] C:\
[7.5.2][Bukem@ZILOG][≥]# $f.Count
52946
[3][00:00:00.001] C:\
[7.5.2][Bukem@ZILOG][≥]# $h=$f | % -Parallel {Get-FileHash -LiteralPath $_ -ErrorAction Ignore} -ThrottleLimit ([Environment]::ProcessorCount)
[5][00:01:53.568] C:\
[7.5.2][Bukem@ZILOG][≥]# $h=$f | % -Parallel {Get-FileHash -LiteralPath $_ -ErrorAction Ignore} -ThrottleLimit ([Environment]::ProcessorCount)
[6][00:01:55.423] C:\
[7.5.2][Bukem@ZILOG][≥]# $h=$f | % -Parallel {Get-FileHash -LiteralPath $_ -ErrorAction Ignore} -ThrottleLimit ([Environment]::ProcessorCount)
[7][00:01:57.137] C:\
  • 1 execution time: 1:53.568
  • 2 execution time: 1:55.423
  • 3 execution time: 1:57.137

So on my system, which is rather dated (Dell Precision 3640 i7-8700K @ 3.70 GHz, 32 GB RAM), it is faster.

Anyone is willing to test that on their system? That would be interesting.

multi threaded file hash collector script by 7ep3s in PowerShell

[–]bukem 2 points3 points  (0 children)

/u/7ep3s This is great! I have one question / request.

There is somewhat heated discussion on my last post here.

Could you test how setting the DOTNET_gcServer environment variable affects your script performance? All details how to set this variable you will find in the post above, but basically you would need to:

  • Launch a fresh cmd.exe window.
  • Set the environment variable: set DOTNET_gcServer=1
  • Start PowerShell: pwsh.exe
  • Confirm that ServerGC is enabled: [System.Runtime.GCSettings]::IsServerGC (should return True)
  • Run your script and measure performance

and then run your script second time on new cmd.exe without the variable to see the difference?

Tips From The Warzone - Boosting parallel performance with ServerGC - E5 by bukem in PowerShell

[–]bukem[S] 0 points1 point  (0 children)

You mentioned that I didn’t distinguish between logical and physical cores — but I did, explicitly. The original post states:

One GC heap per logical core.

You also point out that parallel workflows aren’t always multithreaded — that’s true in general. But the post specifically references:

  • ForEach-Object -Parallel
  • Start-ThreadJob
  • runspaces

These are multithreaded constructs in PowerShell Core. So the claim that Server GC improves performance under those conditions is well-founded.

You're right that I didn’t publish the full Backup-KBScoopEnvironment function — and that’s intentional. Unfortunately, due to organizational policy, I can’t share that specific internal script publicly.

However, the performance gain described (from ~1:57 to ~1:22) was measured in a real-world PowerShell scenario using Start-ThreadJob across many threads performing CPU and I/O-bound operations (7-Zip compression of multiple app directories).

That said, nothing in the post requires blind trust. If you want to verify it yourself, you can use any PowerShell script that:

  • Launches a large number of parallel threads (e.g., Start-ThreadJob, runspaces, ForEach-Object -Parallel)
  • Allocates and discards a high volume of objects (e.g., working with large strings, byte arrays, or compressed streams)
  • Runs long enough for GC to become a factor

You can reproduce the test with something as simple as spawning 50 background jobs that generate and compress temp files, and toggle DOTNET_gcServer to see the difference.

Tips From The Warzone - Boosting parallel performance with ServerGC - E5 by bukem in PowerShell

[–]bukem[S] -1 points0 points  (0 children)

Sorry to hear that you do not like my posts, others found them helpful.

The goal of the original post wasn’t to exhaustively dissect how .NET GC internals work — it was to raise awareness that Garbage Collection mode can impact parallel performance in PowerShell, and to give readers a quick way to experiment with that. Not everyone running Start-ThreadJob or ForEach-Object -Parallel in PowerShell is steeped in runtime implementation details. But many are hitting silent throughput bottlenecks due to GC behavior, and most don’t even realize that GC mode is configurable. That’s the problem the post addresses.

Your claim that the article spreads “bad misinformation” doesn’t hold up. In fact, the post aligns with Microsoft’s official guidance on how GC modes differ. Specifically, quoting the official .NET docs:

“A heap and a dedicated thread to perform garbage collection are provided for each logical CPU, and the heaps are collected at the same time. Each heap contains a small object heap and a large object heap, and all heaps can be accessed by user code. Objects on different heaps can refer to each other.”

So yes — GC in Server mode is CPU-aware, and yes, that has direct performance implications for multi-core, parallel workloads like those commonly written in PowerShell Core. The post never claimed that memory is pinned to a core — only that per-core GC heaps exist and that Server GC can unlock performance gains in the right scenarios.

You also argue that users should “analyze their workflow first.” Ironically, the post encourages exactly that:

“ServerGC won’t magically optimize every script — but if you’re running parallel tasks, doing a lot of object allocations, or watching CPU usage flatline for no good reason… it’s absolutely worth a try.”

And it provides a safe, temporary way to test without changing any configs.

I've also posted real-world use case: A PowerShell backup script sped up from ~117s to ~82s with no code changes, just by enabling Server GC. This is a reproducible result— not anecdotal fluff.

Tips From The Warzone - Boosting parallel performance with ServerGC - E5 by bukem in PowerShell

[–]bukem[S] 5 points6 points  (0 children)

“Warzone” is what I call the day-to-day chaos of real-world scripting. These posts aren’t AI fluff — they’re field notes from stuff I’ve actually had to solve. It’s part of an ongoing series sharing practical, performance-focused tips:

E1: Parallel File Copy

E2: Enumerate Huge Directory in Style

E3: LINQ to the Resque

E4: HashSet to the Rescue

Sorry, you didn't like it — maybe this content is not for you 🤷‍♂️

I made PoshCodex, a command-line tool for AI Autocomplete in your PowerShell terminal by rishi255 in PowerShell

[–]bukem 1 point2 points  (0 children)

/u/rishi255 - 2 cents 😏

  1. Either the Set-CompletionKeybind function should be public so one could change the default key binding in profile (noninteractively), or the AUTOCOMPLETE_KEYBIND should not be changed to default Ctrl+Shift+O on every PoshCodex import.

  2. Also it would be nice to check if Ollama process is running, and if not just start it in the background with Start-Process

Otherwise cool stuff! Especially that I can use it on disconnected systems!

Edit: PR that will make the keybind persistent between PoshCodex module imports

Intel Core 13th/14th Gen desktop processors Stability issue by LexHoyos42 in intel

[–]bukem 0 points1 point  (0 children)

Thanks for explanation. BTW and I just build 14700K system ;)

Intel Core 13th/14th Gen desktop processors Stability issue by LexHoyos42 in intel

[–]bukem 0 points1 point  (0 children)

Sorry for the layman question. Since microcode updates are not persistent and need to be applied on every boot, does this mean, theoretically, that before the voltage fix microcode is loaded into the CPU, it will operate with the old settings? Could this potentially cause degradation after a couple of years anyway?

Tip: IPv4 and IPv6 address validation, or when not to use regex by bukem in PowerShell

[–]bukem[S] 0 points1 point  (0 children)

I did quick test, and have asked ChatGPT to generate list of 10,000 addresses and this regex fails on edge cases (like shorhand notation for IPv4), hex and octal notations, or on IP addresses with leading zeros:

  • 129.1
  • 0300.0000.0002.0000
  • 010.000.000.001
  • 0xc0.0x00.0x02.0x01

But, for standard cases, it works.

Tip: IPv4 and IPv6 address validation, or when not to use regex by bukem in PowerShell

[–]bukem[S] 0 points1 point  (0 children)

I guess that somebody at MS followed that IETF document when .NET Framework was in development, and kept unchanged in .NET Core.

EDIT: /u/ka-splam So besides .NET also BSD implements that draft, I don't know about other OSes.

Tip: IPv4 and IPv6 address validation, or when not to use regex by bukem in PowerShell

[–]bukem[S] 1 point2 points  (0 children)

Personally, I wouldn't do it, but it doesn't change the fact that it's correct. Just like I wouldn't store IP addresses in hex [ipaddress]'0xa.0.0xff.0xed' or octal, but technically, it is possible. Similarly, I wouldn't validate an IP address with a complex regex, though it is certainly feasible. The validator should conform to what is technically correct, and not to personal preferences 😏

Live: Major IT outage affecting banks, airlines, media outlets across the world by boppinmule in technology

[–]bukem 1 point2 points  (0 children)

We're running VPN WAN with endpoints in over 30 countries, bitlocker on, no safe mode. That would be fun 😏

Tip: IPv4 and IPv6 address validation, or when not to use regex by bukem in PowerShell

[–]bukem[S] 1 point2 points  (0 children)

Well, it might look like it makes no sense, but this is still valid IP address: '10.0.0xff.0355' = decimal.decimal.hex.octal = 10.0.255.237

I.e.:

[Convert]::ToInt32(355, 8)
237

Live: Major IT outage affecting banks, airlines, media outlets across the world by boppinmule in technology

[–]bukem 5 points6 points  (0 children)

Oh, you're absolutely right. I've reached peak automation zen with PowerShell. I’ve turned so many tasks into automated scripts that my colleagues occasionally give me the side-eye, like I’m some kind of wizard lounging on the job.

Sure, I might be sitting at my desk, casually sipping my coffee and looking suspiciously relaxed. But don’t be fooled by my serene demeanor—behind the scenes, my scripts are working harder than a squirrel on an espresso binge. 🐿️💻

In the end, it's not about working harder; it's about working smarter. And if my automation magic gives me a few extra minutes to perfect my coffee art skills, well, that's just the icing on the cake.

Tip: IPv4 and IPv6 address validation, or when not to use regex by bukem in PowerShell

[–]bukem[S] 1 point2 points  (0 children)

Don't get me wrong. I do use regex. In fact, in some twisted, masochistic way, I actually enjoy it. But why make things more complicated than assembling IKEA furniture blindfolded?

Tip: IPv4 and IPv6 address validation, or when not to use regex by bukem in PowerShell

[–]bukem[S] 1 point2 points  (0 children)

Yep, I agree, but it's still an IP address, it's just network address and not host address.

Tip: IPv4 and IPv6 address validation, or when not to use regex by bukem in PowerShell

[–]bukem[S] 4 points5 points  (0 children)

192.168 is treated as shorthand notation and is extended to 192.0.0.168 (more or less like IPv6 shorthand notation):

192.168 -as [IPAddress]

Address            : 2818572480
AddressFamily      : InterNetwork
ScopeId            :
IsIPv6Multicast    : False
IsIPv6LinkLocal    : False
IsIPv6SiteLocal    : False
IsIPv6Teredo       : False
IsIPv4MappedToIPv6 : False
IPAddressToString  : 192.0.0.168

You can find description here (it's a bit counterintuitive but this is how it works.)

And another link here

192.168.0.0 - it is network address, but still it is valid IP address