Skip to content

Instantly share code, notes, and snippets.

@davidfowl
Last active January 25, 2026 16:20
Show Gist options
  • Select an option

  • Save davidfowl/268449e5443b47a80d4b80a039536bbc to your computer and use it in GitHub Desktop.

Select an option

Save davidfowl/268449e5443b47a80d4b80a039536bbc to your computer and use it in GitHub Desktop.

Aspire Bundle Size Analysis - Team Summary

Date: January 2025
Current Bundle Size (Windows x64): 577 MB on disk, 204 MB compressed

Executive Summary

Component Size #1 Bloat Source Top Recommendation Potential Savings
DCP 286 MB 5 large Go binaries (50-65 MB each) UPX compression 80-140 MB
.NET Runtime 200 MB Full SDK extraction Already optimized (runtime only) -
Dashboard 43 MB FluentUI Icons (21 MB) Manual icon subsetting 18-20 MB
CLI 22 MB Native AOT binary Already optimized -
AppHost Server 21 MB KubernetesClient.dll (9.3 MB) Remove XML docs 1.3 MB

Total Potential Savings: 100-160 MB (17-28% reduction)


Component Deep Dive

1. DCP (286 MB) - Highest Priority

Current State:

Binary Size Purpose
dcp.exe 64 MB Main orchestrator
dcpctrl.exe 61 MB Controller host
dcptun_c 56 MB Tunnel client (Linux, for containers)
dcptun.exe 52 MB Tunnel server
dcpproc.exe 52 MB Process monitor

Build Configuration Analysis:

βœ… CONFIRMED: Binaries ARE properly stripped. The Azure DevOps pipeline (common-build.yml) uses make release which includes:

release: BUILD_ARGS := $(BUILD_ARGS) -buildmode=pie -ldflags "-bindnow -s -w $(version_values)"

The -s -w flags strip debug symbols and DWARF info. The 50-65 MB sizes are expected given:

  1. Kubernetes API Server dependency - Each binary imports k8s.io/apiserver which is a heavy dependency
  2. Full Go runtime - Each binary includes the complete Go runtime (~5-10 MB base)
  3. gRPC/Protobuf libraries - Required for communication between components
  4. Five separate binaries - Code duplication across binaries (shared libraries compiled into each)

Root Causes (Architecture, not build settings):

  1. Code duplication - Each binary includes full Go runtime + shared K8s client libraries
  2. Heavy K8s dependencies - The Kubernetes API machinery is inherently large
  3. Cross-platform binary - dcptun_c (Linux) is included in Windows bundle for container support

Recommendations:

Priority Action Savings Effort Notes
🟑 Medium Apply UPX compression 80-140 MB Low ⚠️ See trade-offs below
🟑 Medium Lazy-download dcptun_c 56 MB on-disk Medium Only for Windows bundles
🟒 Low Consolidate binaries 30-50 MB High Major refactor

UPX Compression Trade-offs:

UPX can compress Go binaries by 50-70%, but consider:

Pro Con
Significant disk space reduction Adds 100-200ms startup latency per execution
Reduces download size May trigger antivirus false positives
Simple to implement Breaks code signing (must sign after UPX)
macOS notarization may fail
Decompresses to full size in memory

Recommendation: Test UPX thoroughly before adopting. Consider it primarily for reducing download/distribution size, not memory footprint.


2. Dashboard (43 MB) - Medium Priority

Size Breakdown:

Category Size %
FluentUI Icon DLLs 21.2 MB 50%
AI packages (OpenAI, MCP, etc.) 7.4 MB 17%
Dashboard + other DLLs 9.5 MB 22%
JavaScript (Plotly, etc.) 2.1 MB 5%
Source maps, docs, other 2.5 MB 6%

Top Files:

File Size
Icons.Regular.dll 9.6 MB
Icons.Filled.dll 8.1 MB
OpenAI.dll 4.2 MB
Aspire.Dashboard.dll 3.5 MB
Icons.Color.dll 3.3 MB

Root Causes:

  1. FluentUI ships ALL 11,000+ icons - Dashboard uses ~15-20 icons
  2. AI dependencies always included - OpenAI, MCP even when AI features disabled
  3. Debug artifacts in production - Source maps (1.3 MB), XML docs (0.6 MB)

Recommendations:

Priority Action Savings Effort Notes
πŸ”΄ High Manual FluentUI icon subsetting 18-20 MB Medium No automated solution exists
🟑 Medium Make AI features opt-in/lazy-loaded 7 MB High Architecture change
🟒 Low Remove source maps + XML docs 1.9 MB Low Quick win

FluentUI Icon Subsetting (Manual Process):

⚠️ Note: FluentUI Blazor does NOT support automatic tree-shaking. Options:

  1. Create custom icon package - Fork/copy only the ~20 icons Dashboard uses
  2. Inline SVGs directly - Replace icon components with embedded SVG markup
  3. Wait for upstream solution - Microsoft is aware of this issue (see GitHub #619)
// Instead of:
<FluentIcon Value="@(new Icons.Regular.Size16.Copy())" />

// Consider inlining the SVG:
<svg>...</svg>

3. AppHost Server (21 MB) - Low Priority

Size Breakdown:

Category Size
KubernetesClient.dll 9.3 MB (45%)
Aspire.Hosting.dll 2.0 MB
XML documentation 1.3 MB
Other DLLs 8.1 MB

Root Causes:

  1. Full K8s client required - Used for DCP communication (not optional)
  2. XML docs shipped - Not needed at runtime
  3. Dual JSON libraries - Both Newtonsoft.Json and System.Text.Json

Recommendations:

Priority Action Savings Effort Notes
🟒 Low Remove XML documentation 1.3 MB Low Quick win
⚠️ Risky Enable IL trimming 2-3 MB Medium May break reflection-heavy code

Note on KubernetesClient.dll: This is required for DCP communication - it cannot be removed or made optional.


Realistic Quick Wins (Low Effort, Low Risk)

1. Remove Debug Artifacts (~2 MB)

<!-- Add to Dashboard and AppHost Server csproj -->
<PropertyGroup>
  <PublishDocumentationFile>false</PublishDocumentationFile>
</PropertyGroup>

2. Remove Source Maps from Dashboard (~1.3 MB)

Ensure production builds exclude .map files.


Size Reduction Roadmap

Phase 1: Quick Wins (1-2 days, ~3 MB savings)

  • Remove XML docs from Dashboard/AppHost publish
  • Remove source maps from Dashboard publish

Phase 2: Medium Effort (2-4 weeks, ~20-80 MB savings)

  • Create custom FluentUI icon package with only used icons
  • Evaluate UPX compression for DCP (with thorough testing)
  • Lazy-download dcptun_c for Windows

Phase 3: High Effort (1-2 months, ~15-50 MB savings)

  • Make AI features opt-in for Dashboard
  • Consider DCP binary consolidation (major refactor)

Target Bundle Size (Realistic)

Scenario Current Target (Phase 1+2) Reduction
On Disk 577 MB 470-520 MB 10-18%
Compressed 204 MB 165-185 MB 9-19%

Key Finding: DCP Build Configuration

The DCP binaries ARE properly built with release flags. After analyzing the Azure DevOps pipeline:

  1. Pipeline location: .azure/pipelines/common-build.yml
  2. Build step (line 259): make release
  3. Makefile target (line 316):
    release: BUILD_ARGS := $(BUILD_ARGS) -buildmode=pie -ldflags "-bindnow -s -w $(version_values)"

The -s flag strips the symbol table, and -w omits DWARF debug information. The large binary sizes (50-65 MB each) are inherent to Go binaries with heavy Kubernetes dependencies.


Summary

The bundle is already reasonably optimized. The main opportunities are:

  1. FluentUI icons (18-20 MB) - Requires manual effort to subset
  2. UPX for DCP (80-140 MB) - Has trade-offs, needs evaluation
  3. Debug artifacts (3 MB) - Easy quick win

The architecture decisions (5 separate Go binaries, full K8s client, full icon libraries) are the root causes. Significant reductions would require architectural changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment