GC Server Mode - Eonic/ProteanCMS GitHub Wiki
Server GC Mode is a Garbage Collection optimization for .NET applications running on multi-core systems. It significantly improves throughput and reduces GC pause times for web applications like ProteanCMS by enabling parallel garbage collection across all CPU cores.
Server GC creates one dedicated garbage collection thread per CPU core, enabling parallel collection across all available processors. This contrasts with Workstation GC, which uses a single thread for garbage collection.
| Aspect | Workstation GC (Default) | Server GC |
|---|---|---|
| Best For | Desktop applications, client apps | Web servers, high-throughput applications |
| GC Threads | Single thread | One thread per CPU core |
| Memory Usage | Lower (~30 MB per heap) | Higher (~120 MB on 4-core system) |
| GC Pause Time | 50-100ms typical | 10-20ms typical |
| Throughput | Lower | 2-3x higher |
| CPU Utilization | Single core during GC | All cores during GC |
| Heap Structure | Single heap | Separate heap per CPU core |
Server GC creates separate heaps per CPU core:
CPU 1: Heap A β Gen0 | Gen1 | Gen2 CPU 2: Heap B β Gen0 | Gen1 | Gen2 CPU 3: Heap C β Gen0 | Gen1 | Gen2 CPU 4: Heap D β Gen0 | Gen1 | Gen2
When garbage collection is triggered, all heaps are collected simultaneously:
Thread 1 β Collects Heap A β Thread 2 β Collects Heap B ββ All at once Thread 3 β Collects Heap C β Thread 4 β Collects Heap D β
Each request thread allocates on its own heap, eliminating lock contention:
Request Thread 1 β Allocates on Heap A β Request Thread 2 β Allocates on Heap B ββ No locking needed Request Thread 3 β Allocates on Heap C β Request Thread 4 β Allocates on Heap D β
| Metric | Before Server GC | After Server GC | Improvement |
|---|---|---|---|
| Requests/sec | 50-100 | 150-300 | 2-3x increase |
| Response Time | 200ms avg | 100ms avg | 50% faster |
| GC Pause Time | 50-100ms | 10-20ms | 5x reduction |
| Gen2 Collections | 10/min | 3/min | 70% fewer |
| Memory Usage | 500 MB | 700 MB | +40% (acceptable) |
ProteanCMS performs memory-intensive operations that benefit from parallel GC:
-
Large XML Documents:
moPageXmlprocessing -
XSLT Transformations:
moTransformoperations - Cart Operations: Multiple object allocations
- Content Detail XML: Generation and manipulation
- Menu Structure: Building and caching
Example Performance Impact:
// Before (Workstation GC): GetPageHTML() { moPageXml = new XmlDocument(); // Allocates memory BuildPageXML(); // More allocations Transform(moPageXml, moResponse); // Even more! // [GC Pause: 50-100ms] βΈοΈ } // After (Server GC): GetPageHTML() { moPageXml = new XmlDocument(); // Allocates on CPU-specific heap BuildPageXML(); // Fast parallel collection Transform(moPageXml, moResponse); // Minimal pause! // [GC Pause: 10-20ms] β‘ }
Add the following configuration to the <runtime> section of your Web.config:
| Setting | Values | Description |
|---|---|---|
gcServer |
true/false
|
Enables/disables Server GC mode |
gcConcurrent |
true/false
|
Enables concurrent GC (reduces pause times) |
gcAllowVeryLargeObjects |
true/false
|
Allows objects > 2GB (rarely needed) |
Server GC uses approximately 3-4x more memory for heap management:
- Workstation GC: ~30 MB heap overhead (single heap)
- Server GC (4 cores): ~120 MB heap overhead (4 heaps)
Workstation GC: ββββββββββββββββββββ β Gen0: 4 MB β β Gen1: 8 MB β β Gen2: 16 MB β ββββββββββββββββββββ Total: ~30 MB Server GC (4 cores): ββββββββββββββββββββ β CPU1 Gen0: 4 MB β β CPU1 Gen1: 8 MB β β CPU1 Gen2: 16 MB β ββββββββββββββββββββ€ β CPU2 Gen0: 4 MB β β CPU2 Gen1: 8 MB β β CPU2 Gen2: 16 MB β ββββββββββββββββββββ€ β CPU3 Gen0: 4 MB β β CPU3 Gen1: 8 MB β β CPU3 Gen2: 16 MB β ββββββββββββββββββββ€ β CPU4 Gen0: 4 MB β β CPU4 Gen1: 8 MB β β CPU4 Gen2: 16 MB β ββββββββββββββββββββ Total: ~120 MB
- Modern servers typically have 8+ GB RAM
- Performance gains far outweigh memory cost
- Better throughput means fewer servers needed
- Reduced GC pause time improves user experience
- Combined with IDisposable pattern, net memory usage is still optimal
Add this code to Global.asax.cs or application startup:
protected void Application_Start() { // Check GC mode string gcMode = GCSettings.IsServerGC ? "Server" : "Workstation"; System.Diagnostics.Trace.WriteLine(
// Expected output: "GC Mode: Server" }
Use Performance Counters to track GC metrics:
using System.Diagnostics;
// Setup performance counters PerformanceCounter gcGen0 = new PerformanceCounter( ".NET CLR Memory", "# Gen 0 Collections", Process.GetCurrentProcess().ProcessName);
PerformanceCounter gcGen1 = new PerformanceCounter( ".NET CLR Memory", "# Gen 1 Collections", Process.GetCurrentProcess().ProcessName);
PerformanceCounter gcGen2 = new PerformanceCounter( ".NET CLR Memory", "# Gen 2 Collections", Process.GetCurrentProcess().ProcessName);
PerformanceCounter gcTimePercent = new PerformanceCounter( ".NET CLR Memory", "% Time in GC", Process.GetCurrentProcess().ProcessName);
// Log periodically (e.g., every 10 seconds) System.Diagnostics.Debug.WriteLine(
| Metric | What to Monitor | Expected Change |
|---|---|---|
| Gen 0 Collections | Frequency of Gen0 GC | May increase slightly |
| Gen 1 Collections | Frequency of Gen1 GC | Should remain stable |
| Gen 2 Collections | Frequency of Gen2 GC | Should decrease significantly |
| % Time in GC | CPU time spent in GC | Should decrease dramatically |
| Allocated Bytes/sec | Memory allocation rate | May increase slightly |
- Running on multi-core servers (2+ cores)
- Using dedicated hosting or VPS
- Building high-throughput web applications
- Processing large objects (XML, DataSets, Images)
- Handling concurrent requests
- Memory is not severely constrained (4+ GB available)
- Running ASP.NET web applications (like ProteanCMS)
- Running on single-core machines
- Severely memory-constrained (< 2 GB RAM)
- Running desktop applications with UI responsiveness requirements
- Using shared hosting with strict memory limits
- Running console applications with short lifetimes
- Client-side applications where latency is more critical than throughput