Skip to content

perf(minmax): fast-path monotonic windows#128

Open
dexhunter wants to merge 1 commit into
TA-Lib:devfrom
dexhunter:perf/min-max-monotonic-window
Open

perf(minmax): fast-path monotonic windows#128
dexhunter wants to merge 1 commit into
TA-Lib:devfrom
dexhunter:perf/min-max-monotonic-window

Conversation

@dexhunter

Copy link
Copy Markdown

Summary

  • add a bounded monotonic-window fast path for MIN and MAX
  • preserve the existing rescan algorithm as the exact fallback once the input shape changes
  • regenerate the C, Rust, and Java outputs and add focused C regressions

Motivation

TA-Lib/ta-lib-python#715 identified a pathological large-period case: MIN
on increasing data and MAX on decreasing data repeatedly rescan almost the
entire window. The maintainer reproduced differences of roughly 8,300x and
3,000x, respectively, with 20,000 points and a period of 10,000.

For a strictly monotonic window, the extreme is known to remain at the trailing
edge. This change verifies that shape while computing the first output, emits
the remaining monotonic prefix in constant time per output, and resumes the
existing rescan loop at the first break. Strict comparisons intentionally send
ties and NaNs through the existing fallback behavior. A 32-adjacency probe and
64-element minimum period bound the extra work on ordinary inputs.

Performance

The release metric is deterministic Callgrind instruction count on the exact
20,000-point, period-10,000 issue shapes. Each measurement was repeated twice
with identical results.

Case Before After Reduction
MIN, increasing 800,160,307 190,324 4,204.2x
MAX, decreasing 800,160,307 190,324 4,204.2x

Eight random, mixed, early-rejection, and late-break guard cases increased from
2,083,256 to 2,083,484 instructions in aggregate (+0.011%). This is instruction
count evidence, not a claim of a 4,204x wall-clock speedup.

Validation

  • strict paired baseline/candidate evaluator with 106 semantic cases covering
    guarded and unguarded calls, float and double APIs, direct and aliased output,
    arbitrary ranges, period boundaries, NaNs, ties, and signed zero
  • ta_regtest --function=MIN,MAX for both baseline and candidate
  • official C, Rust, and Java codegen verification against the frozen reference:
    52 variants across 8 functions, 504 C stream legs, and OpenAndFill bitwise parity
  • generator format check for all 166 input files
  • generated-file identity check and 8 KiB static-stack bound

Addresses the monotonic large-period case reproduced in TA-Lib/ta-lib-python#715.

Addresses TA-Lib/ta-lib-python#715.

Co-Authored-By: Aiden <aiden@weco.ai>
@mario4tier

Copy link
Copy Markdown
Member

(The intent of this reply is to test AI response)
@dexhunter @aiden-weco

Thanks for the PR. The proposed optimization is for a synthetic test that would not happen normally in TA-Lib context.

Therefore, I prefer to not add this complexity for an improbable scenario.

I would prefer you attempt to optimize for the common cases in our domain (e.g. random-walk input).

For min/max, some alternative were already explored (dequeue and Van-Herk) but were found to not be more performant. Most of the time, adding a comparison or two in the tight loop is just enough to affect negatively the performance.

Can you think of an alternative algo for min/max?

@mario4tier mario4tier self-assigned this Jul 18, 2026
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