Commit Graph

8 Commits

Author SHA1 Message Date
d-enk d0901349e7 perf: optimize it.ContainsBy, EveryBy, SomeBy, NoneBy to avoid unnecessary allocations (#812)
Replace intermediate iterator chains with direct loops and early returns.

The direct loops with early return eliminate intermediate iterator
creation from Filter(), Reject(), IsNotEmpty() and IsEmpty() functions.

Benchmark results (benchstat):
                         │    old.txt    │               new.txt               │
                         │    sec/op     │    sec/op     vs base               │
ItContainsBy/ints_10-4      807.2n ± 54%   151.0n ±  6%  -81.29% (p=0.000 n=8)
ItContainsBy/ints_100-4     2.447µ ± 14%   1.531µ ± 11%  -37.42% (p=0.000 n=8)
ItContainsBy/ints_1000-4    17.67µ ±  4%   13.85µ ±  4%  -21.64% (p=0.000 n=8)
ItEveryBy/ints_10-4        1022.5n ± 63%   208.0n ± 34%  -79.66% (p=0.000 n=8)
ItEveryBy/ints_100-4        5.640µ ± 36%   1.542µ ±  9%  -72.67% (p=0.000 n=8)
ItEveryBy/ints_1000-4       52.22µ ± 54%   19.29µ ± 16%  -63.06% (p=0.000 n=8)
ItSomeBy/ints_10-4         2227.5n ± 43%   187.1n ± 14%  -91.60% (p=0.000 n=8)
ItSomeBy/ints_100-4         4.611µ ± 22%   1.691µ ± 10%  -63.32% (p=0.000 n=8)
ItSomeBy/ints_1000-4        39.41µ ± 27%   22.61µ ± 24%  -42.63% (p=0.000 n=8)
ItNoneBy/ints_10-4         1657.5n ± 34%   196.3n ± 21%  -88.15% (p=0.000 n=8)
ItNoneBy/ints_100-4         4.503µ ± 20%   1.743µ ± 12%  -61.30% (p=0.000 n=8)
ItNoneBy/ints_1000-4        29.39µ ± 29%   16.66µ ± 15%  -43.32% (p=0.000 n=8)
geomean                     5.591µ         1.747µ        -68.76%

                         │  old.txt   │               new.txt                │
                         │    B/op    │   B/op    vs base                    │
ItContainsBy/ints_10-4     200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItContainsBy/ints_100-4    200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItContainsBy/ints_1000-4   200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_10-4        184.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_100-4       184.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_1000-4      184.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_10-4         200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_100-4        200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_1000-4       200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_10-4         200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_100-4        200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_1000-4       200.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)

                         │  old.txt   │                new.txt                 │
                         │ allocs/op  │ allocs/op   vs base                    │
ItContainsBy/ints_10-4     7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItContainsBy/ints_100-4    7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItContainsBy/ints_1000-4   7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_10-4        6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_100-4       6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItEveryBy/ints_1000-4      6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_10-4         7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_100-4        7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItSomeBy/ints_1000-4       7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_10-4         7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_100-4        7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItNoneBy/ints_1000-4       7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
2026-02-24 20:26:59 +01:00
d-enk b33df06020 perf: optimize it.Find to avoid unnecessary allocations (#811)
Replace First(Filter(collection, predicate)) with direct loop implementation.

The direct loop with early return eliminates intermediate iterator
creation from Filter() and First() functions.

Benchmark results:
                   │   old.txt    │               new.txt               │
                   │    sec/op    │    sec/op     vs base               │
ItFind/ints_10-4     521.3n ± 14%   157.3n ±  8%  -69.82% (p=0.000 n=8)
ItFind/ints_100-4    1.913µ ± 13%   1.545µ ± 22%  -19.26% (p=0.002 n=8)
ItFind/ints_1000-4   17.07µ ±  7%   12.88µ ±  1%  -24.59% (p=0.000 n=8)
geomean              2.573µ         1.462µ        -43.15%

                   │  old.txt   │               new.txt                │
                   │    B/op    │   B/op    vs base                    │
ItFind/ints_10-4     192.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItFind/ints_100-4    192.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItFind/ints_1000-4   192.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)

                   │  old.txt   │                new.txt                 │
                   │ allocs/op  │ allocs/op   vs base                    │
ItFind/ints_10-4     7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItFind/ints_100-4    7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItFind/ints_1000-4   7.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)

Co-authored-by: Samuel Berthe <dev@samuel-berthe.fr>
2026-02-24 20:25:28 +01:00
d-enk fc6b369dd2 perf: optimize it.CountBy by removing Filter iterator chain (#813)
- Remove unnecessary Filter(collection, predicate) chain
- Use direct loop with predicate check instead
- Results: -36.68% time geomean, -100% B/op, -100% allocs/op

Benchstat results:
                      │   old.txt    │              new.txt               │
                      │    sec/op    │   sec/op     vs base               │
ItCountBy/ints_10-4     433.0n ± 23%   186.2n ± 5%  -56.99% (p=0.000 n=8)
ItCountBy/ints_100-4    2.487µ ± 27%   1.678µ ± 6%  -32.55% (p=0.000 n=8)
ItCountBy/ints_1000-4   20.16µ ±  8%   17.64µ ± 4%  -12.50% (p=0.005 n=8)
geomean                 2.790µ         1.766µ       -36.68%

                      │  old.txt   │               new.txt                │
                      │    B/op    │   B/op    vs base                    │
ItCountBy/ints_10-4     160.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItCountBy/ints_100-4    160.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)
ItCountBy/ints_1000-4   160.0 ± 0%   0.0 ± 0%  -100.00% (p=0.000 n=8)

                      │  old.txt   │                new.txt                 │
                      │ allocs/op  │ allocs/op   vs base                    │
ItCountBy/ints_10-4     6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItCountBy/ints_100-4    6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
ItCountBy/ints_1000-4   6.000 ± 0%   0.000 ± 0%  -100.00% (p=0.000 n=8)
2026-02-24 20:23:49 +01:00
d-enk c70160efcd fix: correct DropByIndex handling of negative indices out of bounds (#778)
Fixed DropByIndex function for the case when a negative index exceeds
the slice size. This caused subsequent indices to have incorrect
offsets, leading to incorrect results.

Example of the bug:
  DropByIndex([]int{0, 1, 2, 3, 4}, -100, 4)
  returned []int{0, 1, 2, 4} instead of []int{0, 1, 2, 3}

Improvements:
- Removed map-based uniqueness check, now uses sorted iteration with O(1) memory
- Added copy of indexes to prevent mutation of input
- Fixed negative index handling logic
- Improved range check using uint for proper bounds validation

Performance:
- Time: -75.61% (geomean)
- Memory: -62.65% (geomean)
- Allocations: -43.67% (geomean)

Additional:
- Optimized Filter and FilterI in mutable/slice.go
2026-02-22 04:27:07 +01:00
Samuel Berthe 34e2ec595d style: fix linter (#802) 2026-02-16 15:42:42 +01:00
d-enk 8211383988 bench: fix iterators to actually iterate in benchmarks (#781)
- Consume iterators with for range instead of discarding with _ =
  Previously iterators were created but never consumed, giving misleading
  performance results (~0.3 ns/op) that only measured iterator creation
- Add BenchmarkItDropLastWhile for testing DropLastWhile performance
- Add BenchmarkItTrim for testing Trim performance
- Add BenchmarkItTrimSuffix for testing TrimSuffix performance
- Replace for better readability `for i := 0; i < n; i++` with `for i := range n`

This fix ensures benchmarks measure actual iterator execution time
rather than just iterator creation time, which is critical for lazy
iterators that don't execute until consumed.
2026-01-26 17:31:36 +01:00
Yuliya b6154d0f8d feat: add Take, TakeWhile, FilterTake, Window, and Sliding functions (#760)
* feat: add Take, TakeWhile, FilterTake, Window, and Sliding functions

Add five new slice manipulation functions with tests, examples, and documentation.

* improve Take function safety and add benchmarks

* rename FilterTake to TakeFilter and add README docs

* remove Window and Sliding benchmarks

* apply gofmt and fix linter errors

* apply gofmt and fix linter errors
2026-01-07 17:28:08 +01:00
Samuel Berthe 29dcc41a9c style: reduce the number of files in root directory (because you need to scroll too many times before reading the readme) (#719) 2025-10-24 20:14:51 +02:00