Skip to content

[Repo Assist] perf: cache Type.GetType calls in VerifyResultsetColumns#454

Draft
github-actions[bot] wants to merge 2 commits intomasterfrom
repo-assist/perf-cache-type-resolution-20260310-aabcb8703dc087f1
Draft

[Repo Assist] perf: cache Type.GetType calls in VerifyResultsetColumns#454
github-actions[bot] wants to merge 2 commits intomasterfrom
repo-assist/perf-cache-type-resolution-20260310-aabcb8703dc087f1

Conversation

@github-actions
Copy link

🤖 This is an automated PR from Repo Assist.

Summary

VerifyResultsetColumns is called on every Execute/AsyncExecute when runtime verification is enabled. It previously called Type.GetType(typeFullName, throwOnError = true) for every column in every result set on every execution, causing significant reflection overhead.

Root Cause

In ISqlCommand.fs line 265, the verification loop resolved types on each iteration:

for i = 0 to expected.Length - 1 do
    let expectedName, expectedType = fst expected.[i], Type.GetType( snd expected.[i], throwOnError = true)
    // ... verification logic

For a query returning 10 columns executed 1000 times, this meant 10,000 calls to Type.GetType — an expensive operation that involves assembly loading and type lookup.

Fix

Added a static ConcurrentDictionary(string, Type) cache (typeCache) to memoize type resolution:

static let typeCache = System.Collections.Concurrent.ConcurrentDictionary(string, Type)()

// In VerifyResultsetColumns:
let expectedType = typeCache.GetOrAdd(expectedTypeString, fun typeName -> Type.GetType(typeName, throwOnError = true))

The cache is thread-safe and shared across all command instances in the process.

Impact

  • No behaviour change — semantics are identical; caching is transparent
  • Performance: eliminates N×M reflection calls where N = columns and M = executions, after the first execution per unique type
  • Memory: negligible — cache holds only Type references for types already in use

Test Status

Build: ✅ dotnet build src/SqlClient/SqlClient.fsproj -f netstandard2.0 succeeds (only pre-existing deprecation warnings).

Full integration tests require a SQL Server instance and could not be run in this environment. The change is a pure caching optimization with no logic change; existing tests will verify correctness.

Related

Complements PR #448 (TVP reflection caching). Together, these eliminate all hot-path reflection calls in ISqlCommand.fs.

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

Eliminates repeated Type.GetType reflection calls during result set
verification by caching resolved types in a ConcurrentDictionary.

Before: Type.GetType was called for every column in every result set
on every query execution when runtime verification is enabled.

After: Type resolution happens once per unique type name and is cached
for subsequent queries.

Impact: Significantly reduces reflection overhead in verification path,
especially for queries with many columns or high execution frequency.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants