Skip to content

optimizations for KMP - #492

Merged
c-cube merged 13 commits into
mainfrom
simon/optim-kmp
Aug 20, 2026
Merged

c-cube merged 13 commits into
mainfrom
simon/optim-kmp

Conversation

@c-cube

@c-cube c-cube commented Jun 14, 2026

Copy link
Copy Markdown
Owner

alongside benchmarks.

@c-cube
c-cube marked this pull request as ready for review June 14, 2026 03:31

@FardaleM FardaleM left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When giving an empty needle, Find.compile and Find.rcompile now raise Invalid_argument.
This behaviour is not yet documented in the Split module for Split.{gen,list,seq,iter}(_copy)? functions. Also, the documentation of CCStringLabel need the same changes as CCString.

Maybe this should be in the release note as breaking change. For most functions, it is more a bug fix, but for String.find and String.mem for example, the previous behaviour (0 and true) were kind of making sense and could be legitimately used.

The main concern I have is with respect to the lazy construction of the failure table and if it works when sharing a pattern in multiple domain. But I don't know enough how multicore works to tell.

Otherwise, nice improvement! It was fun to review. Where does this idea come from?

Comment thread tests/core/t_string.ml
Comment thread benchs/run_benchs.ml Outdated
Comment thread benchs/run_benchs.ml
Comment thread benchs/run_benchs.ml
Comment on lines +1682 to +1689
if fail_offset >= 0 then (
assert (fail_offset < !j);
i := !i + !j - fail_offset;
j := fail_offset
) else (
j := 0;
incr i
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if fail_offset >= 0 then (
assert (fail_offset < !j);
i := !i + !j - fail_offset;
j := fail_offset
) else (
j := 0;
incr i
)
assert (fail_offset < !j);
i := !i + !j - fail_offset;
if fail_offset >= 0 then j := fail_offset;

If I understand the algorithm correctly, we have the following:
fail_offset < 0 iff fail_offset = -1 iff j = 0.
Therefore, in the case fail_offset <0:
i := !i + !j - fail_offset correspond to i := !i + 0 - (-1) which is incr i
j := 0 is not useful, as j is already 0.

Comment thread benchs/run_benchs.ml Outdated
target instead of re-comparing it and failing again *)
for k = 1 to len - 1 do
let b = failure.(k) in
if b >= 0 && CCChar.equal pat.[k] pat.[b] then

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if b >= 0 && CCChar.equal pat.[k] pat.[b] then
if CCChar.equal pat.[k] pat.[b] then

b >= 0 should always be true when k>0.

Comment thread src/core/CCString.ml Outdated
Comment thread src/core/CCString.ml
Comment thread src/core/CCString.ml
Comment on lines 118 to 127
if fail_offset >= 0 then (
assert (fail_offset < !j);
(* follow the failure link *)
i := !i + !j - fail_offset;
j := fail_offset
) else (
(* beginning of pattern *)
j := 0;
incr i
(* no usable border: advance past the mismatch *)
i := !i + !j + 1;
j := 0
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as in the benchmark file. This can be simplied.

Comment thread src/core/CCString.ml
i := !i + !j + 1;
j := 0
)
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same simplification as in run_benchs.ml is possible here.

Comment thread src/core/CCString.ml
Comment on lines 154 to 163
if fail_offset >= 0 then (
assert (fail_offset < !j);
(* follow the failure link *)
i := !i + !j - fail_offset;
j := fail_offset
) else (
(* beginning of pattern *)
j := 0;
incr i
(* no usable border: advance past the mismatch *)
i := !i + !j + 1;
j := 0
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same here.

Simon Cruanes added 3 commits August 18, 2026 16:22
try to get closer to the behavior of the new String functions in OCaml
5.6
Simon Cruanes added 5 commits August 18, 2026 16:49
…laces

`gen` isn't thread safe here, but otherwise we make sure to use
`compile` and not `compile_lazy` when intermediate state is reachable in
the result (as opposed as used in a transient computation that yields a
proper value as result).
@c-cube
c-cube merged commit 1bd1c4b into main Aug 20, 2026
4 checks passed
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