)]}'
{
  "commit": "4c195b43504c0d2e2c87673f25dfc8075fd640c1",
  "tree": "8ce0f839a5dccc1927fdac8c1affb7f89103a3cb",
  "parents": [
    "1cb4de41c1e0d0a48438c3b1790509973f7acad8"
  ],
  "author": {
    "name": "Neil Conway",
    "email": "neil.conway@gmail.com",
    "time": "Fri Mar 20 18:14:00 2026 -0400"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Fri Mar 20 22:14:00 2026 +0000"
  },
  "message": "perf: Optimize `strpos()` for scalar needle, plus optimize UTF-8 codepath (#20754)\n\n## Which issue does this PR close?\n\n- Closes #20753.\n\n## Rationale for this change\n\nThis PR implements two mostly unrelated optimizations for `strpos`:\n\n1. When the needle is scalar, we can build a single `memmem::Finder` and\nuse it to search each row of the haystack. It turns out that this is\nsignificantly faster than using `memchr`, and the cost of constructing\nthe finder is cheap because it is amortized over the batch.\n2. We previously optimized strpos to use memchr for searching when both\nhaystack and needle are ASCII-only (#20295). That was needlessly\nconservative: UTF-8 is self-stabilizing, so it should be safe to use\n`memchr` to search for matches for any combination of ASCII and UTF-8\nneedle and haystack.\n\nThe performance improvement depends on a bunch of factors (ASCII vs.\nUTF-8, scalar vs array needle, length of haystack strings), but ranges\nfrom 5% for short ASCII strings with a scalar needle to 15x for long\nUTF-8 strings with a scalar needle.\n\n## What changes are included in this PR?\n\n* Improve SLT test coverage for `strpos`\n* Refactor and extend `strpos` benchmarks to cover the scalar case\n* Implement optimizations described above\n* Code cleanup and refactoring for the `strpos` implementation\n\n## Are these changes tested?\n\nYes; new test cases and benchmarks added.\n\n## Are there any user-facing changes?\n\nNo.",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "94ce919c3d8016ce47a8fe0f6da9bfda067b2e8f",
      "old_mode": 33188,
      "old_path": "datafusion/functions/benches/strpos.rs",
      "new_id": "549186dbab14d13805df326621f8fc55aff661b0",
      "new_mode": 33188,
      "new_path": "datafusion/functions/benches/strpos.rs"
    },
    {
      "type": "modify",
      "old_id": "ee854c3c9d1f4ee6592846b3751f44c687040ab7",
      "old_mode": 33188,
      "old_path": "datafusion/functions/src/unicode/strpos.rs",
      "new_id": "1ec93365ee732307a66d0caf820bc8a45ffad58f",
      "new_mode": 33188,
      "new_path": "datafusion/functions/src/unicode/strpos.rs"
    },
    {
      "type": "modify",
      "old_id": "e91ec1cb848ba84b6c210267d0127fac9be52f2a",
      "old_mode": 33188,
      "old_path": "datafusion/sqllogictest/test_files/scalar.slt",
      "new_id": "9d0bc4f7e41b7dae5872fd4374472cc296fa0a3a",
      "new_mode": 33188,
      "new_path": "datafusion/sqllogictest/test_files/scalar.slt"
    }
  ]
}
