AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Framework Jit Optimization

skill-jeremykuhne-agent-skills-framework-jit-optimization · by JeremyKuhne

Optimize hot-path code for the `net481` (.NET Framework) target in a multi-targeted library's Framework-only sources. Use when writing or reviewing performance-sensitive loops, deciding whether to specialize a generic method for primitive types, choosing between scalar/unrolled/BCL-delegating implementations, or diagnosing why a net481 micro-benchmark regresses on the older RyuJIT. Also covers th…

No reviews yet
0 installs
20 views
0.0% view→install

Install

$ agentstack add skill-jeremykuhne-agent-skills-framework-jit-optimization

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-jeremykuhne-agent-skills-framework-jit-optimization)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
27d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Framework Jit Optimization? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

.NET Framework 4.8.1 JIT optimization

If overlay.md exists beside this file, read it before acting; it contains repository-specific bindings. This core remains usable without it.

A multi-targeted library targets net481 in addition to modern .NET. Code in the Framework-only source tree (the Framework/ subtree by convention, excluded from the modern build) only ever runs on the older RyuJIT. Treat net481 as a separate optimization target with its own rules.

This skill captures decisions distilled from real BenchmarkDotNet experiments in the repo's perf project (.perf by convention). The deep span-walking field manual is bundled alongside this skill in [references/framework-span-performance.md](references/framework-span-performance.md).

Always validate with the performance-testing skill workflow before committing a change, and run the pre-pr-self-review checklist before opening a PR - in particular its framework-correctness items (allocation-free over raw speed; perf claims must name the JIT and be measured) apply directly to changes guided by this skill.

For the broader "how do I polyfill API X for net472?" question (which packages to prefer, when to hand-roll), see the polyfill-dotnet-api skill. This skill picks up after that decision is already made and the polyfill lives in the Framework-only tree.

For choosing how a hot path gets its scratch buffer (zeroed stackalloc vs [SkipLocalsInit] vs a stack-with-pool-fallback buffer vs an ArrayPool rental, and the net481/net10 size crossovers), see the scratch-buffer-strategy skill.

The net481 rules below have two companions. What the modern target enables that net481 does not (vectorization, hardware intrinsics, struct-generic kernels, and the JIT-friendly shapes you should not hand-tune away) is in [modern-net.md](modern-net.md). The codegen fundamentals that hold on both targets (arithmetic and branchless lowering, uint-for-non-negative, struct layout, zero-allocation static data, hot-path allocation anti-patterns) are in [cross-tfm-codegen.md](cross-tfm-codegen.md).

A consuming repository wires the concrete cross-skill links and source-tree paths in its overlay.

What is and isn't available on net481

  • No auto-vectorization. The BCL MemoryExtensions methods on net481 ship with

System.Memory. They are hand-tuned scalar / integer-stride implementations - they do not use SIMD.

  • No System.Runtime.Intrinsics. Vector128/Vector256/Vector512,

Sse2.CompareEqual, Avx2.MoveMask are .NET 5+. Not available here.

  • No tiered JIT or PGO. What you write is what gets compiled, once.
  • Vector from System.Numerics.Vectors technically exists but does not

auto-vectorize equality-replace loops on the older JIT, and per-load/store overhead loses to a plain unrolled scalar loop at typical sizes.

  • No source-level loop alignment controls.

"Integer-stride" means routines like IndexOf and SequenceEqual internally process multiple elements per loop step (e.g. compare a ulong chunk that spans 4 chars or 8 bytes) rather than one element at a time. This is not vectorization - just careful scalar code - but it still substantially beats a naive per-element loop for whole-buffer primitives.

Practical consequence: do not assume "the BCL is vectorized so my generic code is fine." On net481 a hand-written specialized loop frequently beats the BCL by 2-3× for full-scan workloads.

Decision flow for a new framework-only fast path

  1. Start with the simplest possible scalar loop and measure it as the baseline.

Capture the baseline on both net10.0 and net481 before editing, and keep the full BenchmarkDotNet rows (Mean/Error/StdDev/Allocated), not a one-line summary - see the before/after discipline in the performance-testing skill. EventPipe line profiling is net10-only, but every change still has to be re-measured on net481 overall.

  1. Decide whether to specialize. See [specialization.md](specialization.md) for the

typeof(T) pattern and primitive equivalence classes.

  1. Decide whether to defer to a BCL primitive. See

[bcl-tradeoffs.md](bcl-tradeoffs.md) for the visit-most-vs-skip-runs rule.

  1. If specializing, add [MethodImpl(MethodImplOptions.AggressiveInlining)] on the

generic entry point. The net481 JIT's default heuristics are conservative; small specialized loops often will not inline without it.

  1. If the loop is the hot path, unroll by 4 with indexed reads + bulk pointer

increment. See [unrolling.md](unrolling.md) for the right form (and the wrong ones).

  1. Stop there. Do not pursue SIMD, SWAR, or branchless tricks without data

showing they win - in practice they regress more often than they help. See [antipatterns.md](antipatterns.md).

  1. Run the same benchmark on net10.0 to confirm you have not regressed the

modern path. If a specialization is harmful on net10 (because the BCL is actually vectorized there), guard it with #if NETFRAMEWORK so only net481 gets the loop.

  1. Report both TFMs' before/after tables together, and confirm the targeted hot

line/method from the net10 trace actually shrank (e.g. System.Array.Copy self-time dropping). A faster Mean with the targeted frame unchanged is usually noise or an unrelated win.

Quick reference: ratios from real benchmarks

All numbers are from the smoke benchmarks in the repo's perf project. Treat as order-of-magnitude, not exact - rerun before claiming a specific number in a PR.

| Decision | Net481 effect (length 4096, full scan) | | --- | --- | | typeof(T) specialization vs generic IEquatable loop | 1.42× faster | | [AggressiveInlining] on a tight scalar loop (length 16) | 1.82× → 1.07× vs baseline | | Unroll-4 indexed (ptr[0..3] + ptr += 4) | 1.5× faster than scalar | | Unroll-8 same form | 1.6× slower than scalar at 256+ | | Per-iteration *ptr; ptr++ instead of indexed reads | ~1.4× slower than indexed | | Integer-indexed unroll (ptr[i+0..3]; i += 4) | Worse than the scalar baseline | | Branchless *ptr = v == old ? new : v (sparse matches) | 1.5-3× slower than branchful conditional store | | SWAR haszero for char Replace (dense matches) | 3× slower than scalar | | BCL IndexOf for Replace (full-scan) | 2.18-3.08× slower than specialized scalar | | BCL IndexOf for Count (sparse matches, 1/64 density) | 2-3× faster than full-scan specialization | | Exponential SequenceEqual probe for CommonPrefixLength (4096, full match) | 3.3× faster than per-element scalar | | Tuple swap (a, b) = (b, a) for plain locals | ~23% slower than T t = a; a = b; b = t; | | Tuple swap on paired Span indexed swap (sort hot path) | ~9% slower than explicit temps | | Tuple swap on a single Span indexed swap or two ref locals | Equivalent (within noise) |

The two BCL rows look contradictory. They aren't. See [bcl-tradeoffs.md](bcl-tradeoffs.md).

Sub-pages

  • [specialization.md](specialization.md) - typeof(T) pattern, Unsafe.As,

primitive bit-equality classes, when generic methods get inlined.

  • [unrolling.md](unrolling.md) - the only unroll form that wins on net481,

and three that don't.

  • [bcl-tradeoffs.md](bcl-tradeoffs.md) - when to defer to BCL IndexOf /

SequenceEqual on net481 despite no vectorization.

  • [antipatterns.md](antipatterns.md) - specific tricks that look clever but

regress on the older JIT.

  • [modern-net.md](modern-net.md) - the net10 counterpart: BCL-first

(SearchValues/TensorPrimitives), the canonical vectorized loop, hardware intrinsics, struct-generic kernels, sealing/devirtualization, escape analysis, and why to keep the modern source simple.

  • [cross-tfm-codegen.md](cross-tfm-codegen.md) - fundamentals for both targets:

division/modulo lowering, uint-for-non-negative, BitOperations, struct field ordering, AoS->SoA, false sharing, ReadOnlySpan blobs, [InlineArray], const-vs-static readonly, and hot-path allocation anti-patterns.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.