Skip to content

Make use of GetMany to improve perf of CopyTo - #2517

Merged
Manodasan Wignarajah (manodasanW) merged 13 commits into
staging/3.0from
manodasanw/getMany
Aug 13, 2026
Merged

Make use of GetMany to improve perf of CopyTo#2517
Manodasan Wignarajah (manodasanW) merged 13 commits into
staging/3.0from
manodasanw/getMany

Conversation

@manodasanW

@manodasanW Manodasan Wignarajah (manodasanW) commented Aug 11, 2026

Copy link
Copy Markdown
Member

Measured IList<T>.CopyTo over 100,000-element native IVector<T> instances using the CollectionsPerf.GetMany* benchmarks.

Scenario Before After Improvement
int 10.55 ns/item 0.111 ns/item ~95× faster
string 61.27 ns/item 37.99 ns/item ~38% faster
projected object 88.24 ns/item 80.49 ns/item ~9% faster

Measured a native component calling IVector<int>.GetMany on a managed int[] containing 100,000 elements.

Implementation Mean per item Relative
Baseline — IList<T> indexer loop 0.652 ns 1.00×
Optimized — direct span copy 0.116 ns 0.18×

The optimized path is approximately 5.6× faster, reducing per-item cost by ~82%, with no managed allocations reported.

Scenario Baseline GetMany optimized Improvement
IList<int>.ToArray() 11.20–11.23 ns/item 0.46–0.49 ns/item 22.7–24.6× faster
IList<string>.ToArray() 104.2–104.7 ns/item 73.4–79.2 ns/item 24–30% faster
IList<WrappedClass>.ToArray() 190.3 ns/item 176.3–177.1 ns/item 7.0–7.4% faster
IVectorView<int>.ToArray() 11.16–11.26 ns/item 0.49–0.52 ns/item 21.5–22.9× faster
IVectorView<WrappedClass>.ToArray() 211.9–224.7 ns/item 177.7–191.5 ns/item 14.8–16.1% faster

ToArray() benefits because LINQ allocates the destination array and invokes ICollection<T>.CopyTo(), which now uses native GetMany.

Copy IList<string> values through a single IVector.GetMany ABI call with balanced HSTRING cleanup, falling back only when a provider returns fewer items.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ddbd67fd-01c2-4b1b-b23f-f9eb0ad8f70e
Batch ICollection<T>.CopyTo through IVector<T>.GetMany across blittable, string, object, reference, value, nullable, key-value pair, Type, and Exception element categories. Add focused native-vector tests and string benchmark coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Validate native counts, preserve E_NOTIMPL fallback compatibility, correct GetMany vtable signatures, and add chunk-boundary string coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
No known conforming IVector implementation returns E_NOTIMPL from GetMany, so preserve normal failure propagation rather than masking incomplete providers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove defensive count clamping because it cannot validate or repair a malformed native provider and conforming implementations must return at most the requested capacity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Use span copies for managed arrays and List<T> exposed through IVector<T>, while retaining the indexer fallback for arbitrary IList<T> implementations. Add coverage for offsets, limited capacity, empty requests, and each implementation path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the TestWinRT-dependent benchmark call commented until the corresponding native benchmark API is available.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Cover writable vectors and vector views for blittable, string, and projected object elements so GetMany improvements through LINQ ToArray remain measurable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the 'GetMany' family out of 'IVectorMethods' and into specialized
extension types in a new 'IVectorMethodsExtensions' file, mirroring the
existing 'IListAdapterExtensions' and 'IEnumeratorAdapterExtensions' files,
so that all specializations expose a uniform 'GetMany' member.

Add a 'GetManyUnsafe' helper to 'IVectorVftbl', matching the '*Unsafe'
convention used by all the other vtable types, and use it from all the
'GetMany' specializations.

Update the interop generator to match the existing patterns: the element
type dispatch in 'InteropMethodDefinitionFactory.IVectorMethods.GetMany'
now uses the same switch expression shape as 'IList1Impl.GetMany', and the
new 'InteropReferences' members follow the naming and documentation of the
equivalent 'IListAdapter*' ones.

Also simplify 'IListMethods<T>.CopyTo' with an early return, and complete
the XML docs on all the new interface and reference members.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f9216861-f68c-437e-8f82-776d072bac2a
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f9216861-f68c-437e-8f82-776d072bac2a
@manodasanW
Manodasan Wignarajah (manodasanW) merged commit 252d474 into staging/3.0 Aug 13, 2026
13 checks passed
@manodasanW
Manodasan Wignarajah (manodasanW) deleted the manodasanw/getMany branch August 13, 2026 23:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants