Skip to content

Conversation

@tomas-zijdemans
Copy link
Contributor

@tomas-zijdemans tomas-zijdemans commented Dec 27, 2025

  • Optimizes sortBy performance by eliminating wrapper object allocations and reducing redundant computations in the comparison hot path.
  • Added more test cases

Benchmark Results:
Tested on Apple M1. Results vary by array size and iteration count, but I observed improvements across all test scenarios on all my various runs. Here's a typical result:

Benchmark Before After Improvement
Numbers (identity selector) 538.27ms 372.90ms 30.7%
Objects by number field 523.60ms 378.41ms 27.7%
Numbers descending 709.18ms 513.22ms 27.6%
Strings by length 58.69ms 43.45ms 26.0%
Already sorted array 64.60ms 48.06ms 25.6%
Reverse sorted array 65.16ms 57.30ms 12.1%
Objects by string field 1162.69ms 1023.97ms 11.9%
Objects by Date field 3232.32ms 2951.31ms 8.7%
Total 6354.53ms 5388.62ms 15.2%

Test script used:

/**
 * Performance benchmark for sortBy
 * Run with: deno run test.ts
 */

import { sortBy } from "@std/collections/sort-by";

const ARRAY_SIZE = 1_000_000;
const ITERATIONS = 50;

function generateTestData() {
  const numbers = Array.from({ length: ARRAY_SIZE }, () => Math.random());

  const objects = Array.from({ length: ARRAY_SIZE }, (_, i) => ({
    id: i,
    value: Math.random(),
    name: `item-${Math.random().toString(36).slice(2, 10)}`,
  }));

  const dates = Array.from({ length: ARRAY_SIZE }, () => ({
    timestamp: new Date(Date.now() - Math.random() * 1e12),
  }));

  const strings = Array.from(
    { length: ARRAY_SIZE },
    () => Math.random().toString(36).slice(2, 12),
  );

  return { numbers, objects, dates, strings };
}

function benchmark(name: string, fn: () => void): number {
  fn();

  const times: number[] = [];
  for (let i = 0; i < ITERATIONS; i++) {
    const start = performance.now();
    fn();
    times.push(performance.now() - start);
  }

  const avg = times.reduce((a, b) => a + b, 0) / times.length;
  const min = Math.min(...times);
  const max = Math.max(...times);

  console.log(
    `  ${name}: avg=${avg.toFixed(2)}ms, min=${min.toFixed(2)}ms, max=${
      max.toFixed(2)
    }ms`,
  );
  return avg;
}

console.log(`\n sortBy Performance Benchmark`);
console.log(`   Array size: ${ARRAY_SIZE.toLocaleString()} elements`);
console.log(`   Iterations: ${ITERATIONS}\n`);

console.log("Generating test data...");
const data = generateTestData();
console.log("Done.\n");

let totalTime = 0;

console.log("Benchmarks:");

totalTime += benchmark("Numbers (identity selector)", () => {
  sortBy(data.numbers, (n) => n);
});

totalTime += benchmark("Objects by number field", () => {
  sortBy(data.objects, (o) => o.value);
});

totalTime += benchmark("Objects by string field", () => {
  sortBy(data.objects, (o) => o.name);
});

totalTime += benchmark("Objects by Date field", () => {
  sortBy(data.dates, (d) => d.timestamp);
});

totalTime += benchmark("Strings by length", () => {
  sortBy(data.strings, (s) => s.length);
});

totalTime += benchmark("Numbers descending", () => {
  sortBy(data.numbers, (n) => n, { order: "desc" });
});

const sorted = [...data.numbers].sort((a, b) => a - b);
totalTime += benchmark("Already sorted array", () => {
  sortBy(sorted, (n) => n);
});

const reversed = [...sorted].reverse();
totalTime += benchmark("Reverse sorted array", () => {
  sortBy(reversed, (n) => n);
});

console.log(`\nTotal average execution time: ${totalTime.toFixed(2)}ms`);

@codecov
Copy link

codecov bot commented Dec 27, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.17%. Comparing base (13e5527) to head (9d1f709).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6916   +/-   ##
=======================================
  Coverage   94.17%   94.17%           
=======================================
  Files         584      584           
  Lines       43087    43095    +8     
  Branches     6875     6877    +2     
=======================================
+ Hits        40578    40586    +8     
  Misses       2457     2457           
  Partials       52       52           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

1 participant