Skip to content

Conversation

@hannesm
Copy link
Owner

@hannesm hannesm commented Oct 20, 2025

This improves my usecase (a single file diffed with 2000 hunks) by a factor of 20

GitHub workflow: run on 4.08 as well

@hannesm hannesm requested a review from kit-ty-kate October 20, 2025 16:55
@hannesm hannesm force-pushed the use-a-rope-of-string-array branch 3 times, most recently from 1c2a055 to 0295c6b Compare October 20, 2025 17:05
@hannesm
Copy link
Owner Author

hannesm commented Oct 20, 2025

On my computer (FreeBSD, OCaml 4.14.2), this works nicely and is a great improvement. I can see that there is the big test with leads to stack overflows for OCaml 4. I am not entirely sure where (and can't produce locally), but may spend some time soon to look into it somehow. EDIT: I used List.append while I should List.rev_append. Issue solved now.

As a matter of fact, before this change, there are some code paths in conex that take an unbearable amount of time (3 minutes) -- with this change, it works nicely in 10 seconds. So, I really would like to get this merged.

This improves my usecase (a single file diffed with 2000 hunks by a factor of 20

GitHub workflow: run on 4.08 as well
@hannesm hannesm force-pushed the use-a-rope-of-string-array branch from ed59358 to 26dd217 Compare October 23, 2025 11:28
Copy link
Contributor

@shym shym left a comment

Choose a reason for hiding this comment

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

I had only a cursory look at Rope, since I assume it has been reviewed and tested more thoroughly elsewhere. The squash of the last 3 commits (aka recognizing a List.rev_append) is good to go.
The changes in src/patch.ml seem to pick up exactly the equivalent operations in Rope.
So this looks good to me.
I also tested the new opatch on the patch series in OCaml/Solo5 and it yields the expected result.

@hannesm
Copy link
Owner Author

hannesm commented Oct 23, 2025

while the initial rope has been copied from utcp, it was modified extensively. it may actually be worth to write some unit testing for it...

@hannesm
Copy link
Owner Author

hannesm commented Oct 28, 2025

I used the test.sh with the following output:

Run on the Mon 27 Oct 2025 22:22:30 CET:
Time of old run:
real 6123.59
user 1432.27
sys 476.03
Time of new run:
real 4801.03
user 0.00
sys 0.00
Diff:
Only in ./old/core.109.07.00: disable_warn_error.patch
Only in ./old/core.109.07.00: fix_META.patch
Only in ./old/core.109.07.00: opam
Files ./old/dbm.1.0/Makefile and ./new/dbm.1.0/Makefile differ
Only in ./new: gappa.1.3.5
Files ./old/graphics.3.12.0/configure and ./new/graphics.3.12.0/configure differ
Only in ./new/graphics.3.12.0: configure.orig
Only in ./new/graphics.3.12.0: opam
Files ./old/libsvm.0.8.3/examples/svm_cli.ml and ./new/libsvm.0.8.3/examples/svm_cli.ml differ
Files ./old/libsvm.0.8.3/lib/libsvm.ml and ./new/libsvm.0.8.3/lib/libsvm.ml differ
Files ./old/mikmatch.1.0.7/Makefile.rej and ./new/mikmatch.1.0.7/Makefile.rej differ
Only in ./old: ocamlsdl.0.9.1
Files ./old/ocp-indent.0.6.0/src/ocp-indent.ocp and ./new/ocp-indent.0.6.0/src/ocp-indent.ocp differ
Files ./old/ocp-indent.0.6.2/src/ocp-indent.ocp and ./new/ocp-indent.0.6.2/src/ocp-indent.ocp differ
Files ./old/ocp-indent.0.9.0/src/ocp-indent.ocp and ./new/ocp-indent.0.9.0/src/ocp-indent.ocp differ
Only in ./old: ppx_deriving.4.1
Only in ./new: why3-base.0.87.1
Only in ./new: why3-base.0.87.2
Only in ./new: why3.0.73
Only in ./new: why3.0.81
Only in ./new: why3.0.82
Only in ./new: why3.1.6.0
Done

grepping for errors in old.log:

[ERROR] Download failed: https://patch-diff.githubusercontent.com/raw/janestreet/base/pull/180.diff (Bad checksum, expected sha256=bf1bdef00acd7a75ff84ad56b951cc68f0a08404629e4560762fafe622ecfda3)
[ERROR] Download failed: https://gappa.gitlabpages.inria.fr/releases/gappa-1.3.5.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-72044-894db0/gappa-1.3.5.tar.gz.part --user-agent opam/2.3.0 -- https://gappa.gitlabpages.inria.fr/releases/gappa-1.3.5.tar.gz" exited with code 1 "fetch: https://gappa.gitlabpages.inria.fr/releases/gappa-1.3.5.tar.gz: Bad Gateway")
[ERROR] Download failed: https://why3.gitlabpages.inria.fr/releases/why3-1.6.0.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-81868-5e5536/why3-1.6.0.tar.gz.part --user-agent opam/2.3.0 -- https://why3.gitlabpages.inria.fr/releases/why3-1.6.0.tar.gz" exited with code 1 "fetch: https://why3.gitlabpages.inria.fr/releases/why3-1.6.0.tar.gz: Bad Gateway")
[ERROR] Download failed: http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc21.tgz (Download command failed: "/usr/bin/fetch -o /tmp/opam-83471-d12b04/coccinelle-1.0.0-rc21.tgz.part --user-agent opam/2.3.0 -- http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc21.tgz" exited with code 1 "fetch: http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc21.tgz: Bad Gateway")
[ERROR] Download failed: http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0.tgz (Download command failed: "/usr/bin/fetch -o /tmp/opam-83488-435474/coccinelle-1.0.0.tgz.part --user-agent opam/2.3.0 -- http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0.tgz" exited with code 1 "fetch: http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0.tgz: Bad Gateway")
[ERROR] Download failed: http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc22.tgz (Download command failed: "/usr/bin/fetch -o /tmp/opam-83501-7600a8/coccinelle-1.0.0-rc22.tgz.part --user-agent opam/2.3.0 -- http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc22.tgz" exited with code 1 "fetch: http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc22.tgz: Bad Gateway")
[ERROR] Download failed: https://www.lri.fr/~filliatr/ftp/ocaml/cgi/cgi-0.8.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-85040-67d87e/cgi-0.8.tar.gz.part --user-agent opam/2.3.0 -- https://www.lri.fr/~filliatr/ftp/ocaml/cgi/cgi-0.8.tar.gz" exited with code 1)
[ERROR] Download failed: https://gitlab.com/tezos/tezos/-/archive/v7.4/tezos-v7.4.tar.bz2 (Bad checksum, expected sha256=72665376e177d3530c2ad26d12215c237fa511484c577b8ee21ced2ba62613a4)
[ERROR] Download failed: http://www.ocamlpro.com/contribs/ocaml-french/ocaml-4.00.1.fr.patch (Download command failed: "/usr/bin/fetch -o /tmp/opam-86356-eecc13/ocaml-4.00.1.fr.patch.part --user-agent opam/2.3.0 -- http://www.ocamlpro.com/contribs/ocaml-french/ocaml-4.00.1.fr.patch" exited with code 1 "fetch: http://www.ocamlpro.com/contribs/ocaml-french/ocaml-4.00.1.fr.patch: Not Found")
[ERROR] Download failed: http://www.ocamlpro.com/files/omit-frame-pointer-4.00.0.patch (Download command failed: "/usr/bin/fetch -o /tmp/opam-87608-d99b5c/omit-frame-pointer-4.00.0.patch.part --user-agent opam/2.3.0 -- http://www.ocamlpro.com/files/omit-frame-pointer-4.00.0.patch" exited with code 1 "fetch: http://www.ocamlpro.com/files/omit-frame-pointer-4.00.0.patch: Not Found")
[ERROR] Download failed: https://bitbucket.org/camlspotter/spotinstall/raw/26c014770721e44be11f364f09b149cff54a047f/ocaml-annot-4.00.1.patch (Download command failed: "/usr/bin/fetch -o /tmp/opam-87931-9276ba/ocaml-annot-4.00.1.patch.part --user-agent opam/2.3.0 -- https://bitbucket.org/camlspotter/spotinstall/raw/26c014770721e44be11f364f09b149cff54a047f/ocaml-annot-4.00.1.patch" exited with code 1 "fetch: https://bitbucket.org/camlspotter/spotinstall/raw/26c014770721e44be11f364f09b149cff54a047f/ocaml-annot-4.00.1.patch: Not Found")
[ERROR] Download failed: https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-88419-239274/dose3-3.2.2.tar.gz.part --user-agent opam/2.3.0 -- https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz" exited with code 1 "fetch: https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz: Forbidden")
[ERROR] Download failed: https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-88439-7c8399/dose3-3.2.2.tar.gz.part --user-agent opam/2.3.0 -- https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz" exited with code 1 "fetch: https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz: Forbidden")
[ERROR] Download failed: https://why3.gitlabpages.inria.fr/releases/why3-0.87.2.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-88515-c428c7/why3-0.87.2.tar.gz.part --user-agent opam/2.3.0 -- https://why3.gitlabpages.inria.fr/releases/why3-0.87.2.tar.gz" exited with code 1 "fetch: https://why3.gitlabpages.inria.fr/releases/why3-0.87.2.tar.gz: Bad Gateway")
[ERROR] Download failed: https://why3.gitlabpages.inria.fr/releases/why3-0.87.1.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-88528-e057f0/why3-0.87.1.tar.gz.part --user-agent opam/2.3.0 -- https://why3.gitlabpages.inria.fr/releases/why3-0.87.1.tar.gz" exited with code 1 "fetch: https://why3.gitlabpages.inria.fr/releases/why3-0.87.1.tar.gz: Bad Gateway")
[ERROR] Download failed: http://www.lri.fr/~filliatr/combine/download/combine-0.42.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-89216-5f456b/combine-0.42.tar.gz.part --user-agent opam/2.3.0 -- http://www.lri.fr/~filliatr/combine/download/combine-0.42.tar.gz" exited with code 1)
[ERROR] Download failed: http://www.algo-prog.info/ocapic/web/lib/exe/fetch.php?media=ocamlclean-2.0.tar.bz2 (Download command failed: "/usr/bin/fetch -o /tmp/opam-89459-d335a0/fetch.php?media=ocamlclean-2.0.tar.bz2.part --user-agent opam/2.3.0 -- http://www.algo-prog.info/ocapic/web/lib/exe/fetch.php?media=ocamlclean-2.0.tar.bz2" exited with code 1 "fetch: http://www.algo-prog.info/ocapic/web/lib/exe/fetch.php?media=ocamlclean-2.0.tar.bz2: Operation timed out")
[ERROR] Download failed: https://gitlab.com/tezos/tezos/-/archive/v7.4/tezos-v7.4.tar.bz2 (Bad checksum, expected sha256=72665376e177d3530c2ad26d12215c237fa511484c577b8ee21ced2ba62613a4)
[ERROR] Download failed: https://why3.gitlabpages.inria.fr/releases/why3-0.82.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-90154-43ffdc/why3-0.82.tar.gz.part --user-agent opam/2.3.0 -- https://why3.gitlabpages.inria.fr/releases/why3-0.82.tar.gz" exited with code 1 "fetch: https://why3.gitlabpages.inria.fr/releases/why3-0.82.tar.gz: Bad Gateway")
[ERROR] Download failed: https://why3.gitlabpages.inria.fr/releases/why3-0.81.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-90167-040232/why3-0.81.tar.gz.part --user-agent opam/2.3.0 -- https://why3.gitlabpages.inria.fr/releases/why3-0.81.tar.gz" exited with code 1 "fetch: https://why3.gitlabpages.inria.fr/releases/why3-0.81.tar.gz: Bad Gateway")
[ERROR] Download failed: https://why3.gitlabpages.inria.fr/releases/why3-0.73.tar.gz (Download command failed: "/usr/bin/fetch -o /tmp/opam-90180-db4c6b/why3-0.73.tar.gz.part --user-agent opam/2.3.0 -- https://why3.gitlabpages.inria.fr/releases/why3-0.73.tar.gz" exited with code 1 "fetch: https://why3.gitlabpages.inria.fr/releases/why3-0.73.tar.gz: Bad Gateway")
[ERROR] Patch file "/tmp/test-patch/tmp/graphics.3.12.0/file_download.php?file_id=418&type=bug" not found.
[ERROR] Download failed: http://www.ocamlpro.com/patches/3.11.2_binutils.patch (Download command failed: "/usr/bin/fetch -o /tmp/opam-92993-d546de/3.11.2_binutils.patch.part --user-agent opam/2.3.0 -- http://www.ocamlpro.com/patches/3.11.2_binutils.patch" exited with code 1 "fetch: http://www.ocamlpro.com/patches/3.11.2_binutils.patch: Not Found")
[ERROR] Download failed: https://gitlab.com/tezos/tezos/-/archive/v7.4/tezos-v7.4.tar.bz2 (Bad checksum, expected sha256=72665376e177d3530c2ad26d12215c237fa511484c577b8ee21ced2ba62613a4)

and in new.log:

[ERROR] Download failed: https://patch-diff.githubusercontent.com/raw/janestreet/base/pull/180.diff (Bad checksum, expected sha256=bf1bdef00acd7a75ff84ad56b951cc68f0a08404629e4560762fafe622ecfda3)
[ERROR] Download failed: http://downloads.sourceforge.net/project/ocamlsdl/OCamlSDL/ocamlsdl-0.9.1/ocamlsdl-0.9.1.tar.gz (code 503 while downloading http://downloads.sourceforge.net/project/ocamlsdl/OCamlSDL/ocamlsdl-0.9.1/ocamlsdl-0.9.1.tar.gz)
[ERROR] Download failed: http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc21.tgz (code 404 while downloading http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc21.tgz)
[ERROR] Download failed: http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0.tgz (code 404 while downloading http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0.tgz)
[ERROR] Download failed: http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc22.tgz (code 404 while downloading http://coccinelle.lip6.fr/distrib/coccinelle-1.0.0-rc22.tgz)
[ERROR] Download failed: https://www.lri.fr/~filliatr/ftp/ocaml/cgi/cgi-0.8.tar.gz (curl failed: "/usr/local/bin/curl --write-out %{http_code}\\n --retry 3 --retry-delay 2 --user-agent opam/2.6.0~alpha1~dev -L -o /tmp/opam-32965-d6c180/cgi-0.8.tar.gz.part -- https://www.lri.fr/~filliatr/ftp/ocaml/cgi/cgi-0.8.tar.gz" exited with code 60)
[ERROR] Download failed: https://gitlab.com/tezos/tezos/-/archive/v7.4/tezos-v7.4.tar.bz2 (Bad checksum, expected sha256=72665376e177d3530c2ad26d12215c237fa511484c577b8ee21ced2ba62613a4)
[ERROR] Download failed: https://github.com/whitequark/ppx_deriving/archive/v4.1.tar.gz (curl failed: "/usr/local/bin/curl --write-out %{http_code}\\n --retry 3 --retry-delay 2 --user-agent opam/2.6.0~alpha1~dev -L -o /tmp/opam-33623-64b92d/v4.1.tar.gz.part -- https://github.com/whitequark/ppx_deriving/archive/v4.1.tar.gz" exited with code 6)
[ERROR] Download failed: http://www.ocamlpro.com/contribs/ocaml-french/ocaml-4.00.1.fr.patch (code 404 while downloading http://www.ocamlpro.com/contribs/ocaml-french/ocaml-4.00.1.fr.patch)
[ERROR] Download failed: http://www.ocamlpro.com/files/omit-frame-pointer-4.00.0.patch (code 404 while downloading http://www.ocamlpro.com/files/omit-frame-pointer-4.00.0.patch)
[ERROR] Download failed: https://bitbucket.org/camlspotter/spotinstall/raw/26c014770721e44be11f364f09b149cff54a047f/ocaml-annot-4.00.1.patch (code 404 while downloading https://bitbucket.org/camlspotter/spotinstall/raw/26c014770721e44be11f364f09b149cff54a047f/ocaml-annot-4.00.1.patch)
[ERROR] Download failed: https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz (code 403 while downloading https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz)
[ERROR] Download failed: https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz (code 403 while downloading https://gforge.inria.fr/frs/download.php/file/33677/dose3-3.2.2.tar.gz)
[ERROR] Download failed: https://raw.githubusercontent.com/ocaml/opam-source-archives/main/patches/core/disable_warn_error.patch (curl failed: "/usr/local/bin/curl --write-out %{http_code}\\n --retry 3 --retry-delay 2 --user-agent opam/2.6.0~alpha1~dev -L -o /tmp/opam-36296-6f5761/disable_warn_error.patch.part -- https://raw.githubusercontent.com/ocaml/opam-source-archives/main/patches/core/disable_warn_error.patch" exited with code 7)
[ERROR] Download failed: http://www.lri.fr/~filliatr/combine/download/combine-0.42.tar.gz (curl failed: "/usr/local/bin/curl --write-out %{http_code}\\n --retry 3 --retry-delay 2 --user-agent opam/2.6.0~alpha1~dev -L -o /tmp/opam-36960-d3e11d/combine-0.42.tar.gz.part -- http://www.lri.fr/~filliatr/combine/download/combine-0.42.tar.gz" exited with code 60)
[ERROR] Download failed: http://www.algo-prog.info/ocapic/web/lib/exe/fetch.php?media=ocamlclean-2.0.tar.bz2 (curl failed: "/usr/local/bin/curl --write-out %{http_code}\\n --retry 3 --retry-delay 2 --user-agent opam/2.6.0~alpha1~dev -L -o /tmp/opam-37195-d3cd37/fetch.php?media=ocamlclean-2.0.tar.bz2.part -- http://www.algo-prog.info/ocapic/web/lib/exe/fetch.php?media=ocamlclean-2.0.tar.bz2" exited with code 28)
[ERROR] Download failed: https://gitlab.com/tezos/tezos/-/archive/v7.4/tezos-v7.4.tar.bz2 (Bad checksum, expected sha256=72665376e177d3530c2ad26d12215c237fa511484c577b8ee21ced2ba62613a4)
[ERROR] Patch file "/tmp/test-patch/tmp/graphics.3.12.0/file_download.php?file_id=418&type=bug" not found.
[ERROR] Download failed: http://www.ocamlpro.com/patches/3.11.2_binutils.patch (code 404 while downloading http://www.ocamlpro.com/patches/3.11.2_binutils.patch)
[ERROR] Download failed: https://gitlab.com/tezos/tezos/-/archive/v7.4/tezos-v7.4.tar.bz2 (curl failed: "/usr/local/bin/curl --write-out %{http_code}\\n --retry 3 --retry-delay 2 --user-agent opam/2.6.0~alpha1~dev -L -o /tmp/opam-41599-ce75e2/tezos-v7.4.tar.bz2.part -- https://gitlab.com/tezos/tezos/-/archive/v7.4/tezos-v7.4.tar.bz2" exited with code 7)

I'm not sure what I'm supposed to do with this output. The test script is very nice, but is equivalence achieved with patch released as 3.0.0?

@kit-ty-kate
Copy link
Collaborator

I'm not sure what I'm supposed to do with this output.

With this output in particular, nothing beyond a simple diff. The real output is in test.log which shows the difference of the two trees with all the patches applied.

Copy link
Collaborator

@kit-ty-kate kit-ty-kate left a comment

Choose a reason for hiding this comment

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

A couple of comments at a glance

@hannesm
Copy link
Owner Author

hannesm commented Nov 3, 2025

I'm not sure what I'm supposed to do with this output.

With this output in particular, nothing beyond a simple diff. The real output is in test.log which shows the difference of the two trees with all the patches applied.

The test.log is exactly the first thing I pasted in the comment. To reduce confusion, here it is again:

Run on the Mon 27 Oct 2025 22:22:30 CET:
Time of old run:
real 6123.59
user 1432.27
sys 476.03
Time of new run:
real 4801.03
user 0.00
sys 0.00
Diff:
Only in ./old/core.109.07.00: disable_warn_error.patch
Only in ./old/core.109.07.00: fix_META.patch
Only in ./old/core.109.07.00: opam
Files ./old/dbm.1.0/Makefile and ./new/dbm.1.0/Makefile differ
Only in ./new: gappa.1.3.5
Files ./old/graphics.3.12.0/configure and ./new/graphics.3.12.0/configure differ
Only in ./new/graphics.3.12.0: configure.orig
Only in ./new/graphics.3.12.0: opam
Files ./old/libsvm.0.8.3/examples/svm_cli.ml and ./new/libsvm.0.8.3/examples/svm_cli.ml differ
Files ./old/libsvm.0.8.3/lib/libsvm.ml and ./new/libsvm.0.8.3/lib/libsvm.ml differ
Files ./old/mikmatch.1.0.7/Makefile.rej and ./new/mikmatch.1.0.7/Makefile.rej differ
Only in ./old: ocamlsdl.0.9.1
Files ./old/ocp-indent.0.6.0/src/ocp-indent.ocp and ./new/ocp-indent.0.6.0/src/ocp-indent.ocp differ
Files ./old/ocp-indent.0.6.2/src/ocp-indent.ocp and ./new/ocp-indent.0.6.2/src/ocp-indent.ocp differ
Files ./old/ocp-indent.0.9.0/src/ocp-indent.ocp and ./new/ocp-indent.0.9.0/src/ocp-indent.ocp differ
Only in ./old: ppx_deriving.4.1
Only in ./new: why3-base.0.87.1
Only in ./new: why3-base.0.87.2
Only in ./new: why3.0.73
Only in ./new: why3.0.81
Only in ./new: why3.0.82
Only in ./new: why3.1.6.0
Done

Copy link
Collaborator

@kit-ty-kate kit-ty-kate left a comment

Choose a reason for hiding this comment

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

ah yes i see, sorry i missed that part. The diff shows a couple of differences, it might be worth looking into it to make sure these aren't real issues (some of them are expected to fail, e.g. if they use context diffs instead of unified diffs)

@hannesm
Copy link
Owner Author

hannesm commented Nov 3, 2025

Digging a bit deeper, using grep WARNING new.log | cut -d ' ' -f 3-7 | sort (and of course in old.log as well), we can see which packages failed to apply patches -- here we have some context diffs:

/tmp/test-patch/tmp/dbm.1.0/mkdir-stublibs.patch uses context diffs which
/tmp/test-patch/tmp/libsvm.0.8.3/calc_scc_fix.patch uses context diffs which
/tmp/test-patch/tmp/libsvm.0.8.3/svm_cli_fix.patch uses context diffs which
/tmp/test-patch/tmp/ocp-indent.0.6.0/fix-warn-error.patch uses context diffs which
/tmp/test-patch/tmp/ocp-indent.0.6.2/fix-warn-error.patch uses context diffs which
/tmp/test-patch/tmp/ocp-indent.0.9.0/fix-warn-error.patch uses context diffs which

And the remaining (we actually need only field 6, and can observe the difference:

--- old-patch-errors    2025-11-03 12:27:38.535182000 +0100
+++ new-patch-errors    2025-11-03 12:27:30.318247000 +0100
@@ -10,11 +10,16 @@
 /tmp/test-patch/tmp/core_extended.109.07.00:
 /tmp/test-patch/tmp/core_extended.113.00.00:
 /tmp/test-patch/tmp/core.108.08.00:
-/tmp/test-patch/tmp/core.109.07.00:
+/tmp/test-patch/tmp/dbm.1.0:
 /tmp/test-patch/tmp/fieldslib.109.07.00:
+/tmp/test-patch/tmp/graphics.3.12.0:
+/tmp/test-patch/tmp/libsvm.0.8.3:
 /tmp/test-patch/tmp/mikmatch.1.0.7:
 /tmp/test-patch/tmp/ocamlgraph.1.8.3:
 /tmp/test-patch/tmp/ocamlnet.3.6.0:
+/tmp/test-patch/tmp/ocp-indent.0.6.0:
+/tmp/test-patch/tmp/ocp-indent.0.6.2:
+/tmp/test-patch/tmp/ocp-indent.0.9.0:
 /tmp/test-patch/tmp/pa_ounit.109.07.00:
 /tmp/test-patch/tmp/pipebang.109.07.00:
 /tmp/test-patch/tmp/sexplib.109.07.00:
@@ -24,6 +29,7 @@
 /tmp/test-patch/tmp/why.2.31:
 /tmp/test-patch/tmp/why.2.32:
 /tmp/test-patch/tmp/why.2.33:
+/tmp/test-patch/tmp/why3.0.81:

To go through them one-by-one:

core 109.07.00

diff -ur old/core.109.07.00/ new/core.109.07.00/
Only in old/core.109.07.00: disable_warn_error.patch
Only in old/core.109.07.00: fix_META.patch
Only in old/core.109.07.00: opam

I've no clue why there was no warning in new.

dbm 1.0

This is a context diff

graphics 3.12.0

[ERROR] Patch file "/tmp/test-patch/tmp/graphics.3.12.0/file_download.php?file_id=418&type=bug" not found.
[WARNING] Some errors extracting to /tmp/test-patch/tmp/graphics.3.12.0:
            These patches didn't apply at /tmp/test-patch/tmp/graphics.3.12.0:
            - file_download.php?file_id=418&type=bug: Not_found

So, there was a download failure.

libsvm 0.8.3

context diffs

ocp-indent 0.6.0

context diff

ocp-indent 0.6.2

context diff

ocp-indent 0.9.0

context diff

why3 0.81

[WARNING] Some errors extracting to /tmp/test-patch/tmp/why3.0.81:
These patches didn't apply at /tmp/test-patch/tmp/why3.0.81:
- configure.patch: Failure("wrong prefix")

Looking back at old.log, the why3 server was down when that test was run.

Conclusion

I can't find any divergence, but I'm not sure what to look for. For sure, context diffs are not supported anymore. Also, "bad prefix" is a common cause. I was curious whether you @kit-ty-kate have a saved run from earlier versions (so what should the test.log look like for a successful test)?

@kit-ty-kate
Copy link
Collaborator

I'll review again tomorrow but so far it looks great. I'm starting to understand the little invariants of the new Rope datatype. Here's the diff i got between 2.5.0~alpha1 (OCaml 4.14) and 2.5.0~alpha1 (OCaml 5.4 + this branch patch):

Run on the Mon Nov  3 20:13:55 GMT 2025:
Time of old run:
real 2044.33
user 748.52
sys 127.65
Time of new run:
real 1760.96
user 493.22
sys 128.72
Diff:
Done

No diff, which is perfect. The time difference isn't the most accurate data so disregard it for now. I'll open a PR in opam to have more reliable performance numbers.

@kit-ty-kate
Copy link
Collaborator

ocaml/opam#6772 (ocaml-benchmark) doesn't see any difference in terms of performance compared to before (it might actually very slightly take more time), but maybe it's because opam update doesn't really encounter the same corner-case compared to conex

@hannesm
Copy link
Owner Author

hannesm commented Nov 4, 2025

Thanks for testing. I added a test case (many-hunks) with lots of hunks which should show the performance difference.

@kit-ty-kate
Copy link
Collaborator

Thanks a lot for these tests. I can indeed confirm that the time taken running the tests went from ~20s to ~2s with both OCaml 4.14 and 5.4.

One side note/question i have about that commit is: the new files add about ~2MB to the repository, do you want to keep them in or move them to https://codeberg.org/kit-ty-kate/ocaml-patch-tests (aka. test/data/external) ? I personally think they would fit right in, in the latter.

@hannesm
Copy link
Owner Author

hannesm commented Nov 4, 2025

Oh please feel free to move them over to your repo, I can force-push here to avoid having them in this repository.

@hannesm
Copy link
Owner Author

hannesm commented Nov 4, 2025

@hannesm hannesm force-pushed the use-a-rope-of-string-array branch from 004ab8e to 4f36296 Compare November 4, 2025 15:35
@hannesm
Copy link
Owner Author

hannesm commented Nov 4, 2025

and force-pushed to remove the test here, but use the external files (many-hunks.*).

@hannesm
Copy link
Owner Author

hannesm commented Nov 4, 2025

hmm, so the diff is actually not what diff -u does.. but this is unrelated to this change. we can work on that separately.

@hannesm hannesm force-pushed the use-a-rope-of-string-array branch from 4f36296 to 01d557e Compare November 4, 2025 15:47
Copy link
Collaborator

@kit-ty-kate kit-ty-kate left a comment

Choose a reason for hiding this comment

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

lgtm modulo squash/clean-off of the branch.

I find the new Rope abstraction quite complex, and i'm personally not huge fan of adding such a complex datatype with hidden invariants that can be subtly broken later into the codebase (the nl parameter also seems particularly ad-hoc in that regard), but the performance improvement is worth it and it shown to work with the largest set of test that we have so it's ok for now.

Further improvements could be made in the future by changing our hunk type to use the rope type, this might avoid the extra copies and simplify some operations.

Let's merge this and i'm personally hoping to find a way to simplify the definition or something like that, later. Thanks a lot for this huge work!

@hannesm hannesm merged commit 4df4702 into main Nov 6, 2025
7 checks passed
@hannesm hannesm deleted the use-a-rope-of-string-array branch November 6, 2025 08:10
@hannesm
Copy link
Owner Author

hannesm commented Nov 6, 2025

Thanks @kit-ty-kate. I squash-merged and will cut a release.

hannesm added a commit to hannesm/opam-repository that referenced this pull request Nov 6, 2025
CHANGES:

* Use a rope data structure instead of lists. Improves performance especially
  with many hunks (hannesm/patch#37 @hannesm, review by @shym @kit-ty-kate)
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.

4 participants