Skip to content

replace List with [] in static series, then covert at end return (it’s faster) #1259

@DaveSkender

Description

@DaveSkender

For static series implementations, use array for internal calculations instead of instantiating List to fill as calculations roll through the quotes or sorcery data time series.

See EMA in v3 for example. Keep in mind, this approach is only faster in certain circumstances, so performance test comparison is required to see where it's better. For example, the simple ADL indicator remains faster with List<AdlResult> composition.

To avoid copying the underlying array, remember to use:

return new List<TrResult>(results);

Instead of:

return results.ToList();

References and examples:

EmaResult[] results = new EmaResult[length];

Analysis: Replace List with [] in Static Series

Status: Feasible - Selective Application Recommended

Summary: Replace List<T> composition with array allocation (T[]) and return as new List<T>(results) to avoid copying the underlying array.

Current State Analysis:

The codebase shows a mixed pattern:

  • EMA, SMA, TR already use array allocation
  • ADL, WMA, MACD, ADX, and ~50+ others use List<T> with .Add()

Benchmark Data (from #1792 experiment):

Approach Mean (502 periods) Notes
Current (List) 9,300 ns Baseline
Array + new List(array) 4,384 ns ~2x faster
Pure array 1,768 ns ~5x faster (loop)
Pure array (rolling) 581 ns ~16x faster

Feasibility Assessment:

Pros:

  • No API breaking changes
  • Array allocation with capacity is faster than List.Add for known-size results
  • new List<T>(array) wraps without copying (constructor takes ownership)
  • Already proven in EMA implementation

⚠️ Considerations:

  • Not all indicators benefit equally (ADL test showed List was faster)
  • Requires per-indicator benchmarking
  • Complex indicators with conditional additions may be harder to convert

Recommendation: Implement on indicator-by-indicator basis with mandatory before/after benchmarking.

Implementation Strategy:

  1. Identify indicators with simple, predictable result counts (≈40 candidates)

  2. Convert pattern from:

    List<Result> results = new(length);
    for (...) results.Add(new Result(...));
    return results;

    To:

    Result[] results = new Result[length];
    for (...) results[i] = new Result(...);
    return new List<Result>(results);
  3. Benchmark each conversion; revert if no improvement

Estimated Impact: 5-20% per-indicator improvement for applicable indicators

Metadata

Metadata

Labels

on holdOn hold / waiting

Projects

Status

Icebox

Relationships

None yet

Development

No branches or pull requests

Issue actions