8000 Add benchmark for ppxlib driver by gridbugs · Pull Request #376 · ocaml-ppx/ppxlib · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add benchmark for ppxlib driver #376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 17, 2022
Merged

Conversation

gridbugs
Copy link
Contributor

This adds a target make bench which measures the time taken to run the ppxlib driver on some input files. I've added two drivers to be benchmarked:

  • one which applies ppx_sexp_conv (which is added as a vendored package)
  • one which does nothing

Each driver specifies some input files copied from MIT licensed projects. The benchmark runner invokes each driver on each of its specified inputs and measures the mean and stddev of the time it took to run each driver on each of its inputs.

< 8000 div class="pr-1 flex-shrink-0" style="width: 16px;">
Signed-off-by: Stephen Sherratt <stephen@sherra.tt>
@tmattio
Copy link
Collaborator
tmattio commented Sep 29, 2022

This is awesome, thanks @gridbugs!! 🎉

I'm curious to know if we could integrate it with current-bench? (that would allow us to have benchmark reports in GitHub PRs automatically IIUC?)

Do you know how easy that would be @shakthimaan?

@gridbugs
Copy link
Contributor Author

Thanks @tmattio! I forgot to mention in the description, but integrating with current-bench is the goal for this.

@gridbugs gridbugs force-pushed the driver-benchmark branch 2 times, most recently from db00a43 to d1f15be Compare September 29, 2022 12:57
@gridbugs
Copy link
Contributor Author

This fails to build on 4.04 and 4.05 because it uses standard library functions that didn't exist in those versions of the language. Also, the pinned version of ppx_sexp_conv is too new to be built by those versions of the compiler. Is it making sure that the benchmarks build on old versions of the compiler?

@panglesd
Copy link
Collaborator

Thanks a lot @gridbugs for the great contribution! It is awesome that we will able to have benchmarks integrated with current-bench!

I'll review the code next week.
About the CI failure, yes the CI is making sure that it builds on each OCaml version compatible with ppxlib. I see several ways to fix it:

  • Manually fix the vendored package to make it compatible with older versions. Might be simple or hard, but I don't think it's a good solution!
  • Dropping old OCaml compatibility. I personally think that would be OK as those are really old versions, but I'm not sure if everyone agree, and maybe we can do without it:
  • defining another package (ppxlib-bench) with different requirements on the ocaml version. For instance, this is what has been done with yojson in this PR.

I think the last solution is the best one, I hope it works!

@pitag-ha
Copy link
Member
pitag-ha commented Sep 30, 2022

Hey @gridbugs. Also from my side, thanks a lot! I'm really looking forward to enrolling the ppxlib driver to current-bench!

To add a fourth possible solution for the CI failure: what we usually do to locally turn off CI builds on old compilers is to add a

(enabled_if
  (>= %{ocaml_version} "4.06.0"))

field to the dune files. Since I know you only wanted to work on ppxlib for a couple of days and have already done that (with a really great result!), that might be a good option.

@panglesd
Copy link
Collaborator

There is actually another problem with not separating the benchmark in another package: the dependencies of the benchmark and the core library are mixed. This means that:

  • yojson is added as a dependency while it is not useful to ppxlib itself
  • Any time we want to add a new benchmark, we might add extra dependencies.

Since ppxlib is meant to be the "goto" library for all ppx rewriters, I think we should avoid as much as possible adding new dependencies. So I think that we should really go for solution 3.

If you do not have that much time to give to ppxlib, I could try to implement this solution myself. In any case, thanks a lot for the work! As @pitag-ha said, it is really great result!

@pitag-ha
Copy link
Member

the dependencies of the benchmark and the core library are mixed

To avoid that, @gridbugs has added it as a with-test dependency, not as a hard dependency. I myself don't have a preference between the two things: with-test dependency or separate opam package. I've also asked @kit-ty-kate if one of them would be better from an opam point of view and she's said that both are equally fine. So I'd say it's up to you, @gridbugs and @panglesd.

@panglesd
Copy link
Collaborator

To avoid that, @gridbugs has added it as a with-test dependency

Yes, that's right, sorry I forgot about that!

So in fact, the reasoning for separating benchmark from the tests in yojson was that it can be time costly (and also, depending on your definition of test, it is not exactly a test as there are no exact failing/succeeding conclusion).

In this case, if the tests run sufficiently fast and are not computation-intensive, I'm fine with any solution!

@shakthimaan
Copy link

I'm curious to know if we could integrate it with current-bench?

Yes. Please follow the steps in Enrolling a repository section provided in the following blog post to add your project to current-bench:
https://tarides.com/blog/2021-08-26-benchmarking-ocaml-projects-with-current-bench

@pitag-ha
8000 Copy link
Member
pitag-ha commented Oct 3, 2022

Yes. Please follow the steps in Enrolling a repository section provided in the following blog post

Yes, I'll do that as soon as this PR is merged.

Btw, im currently at the MirageOs retreat and won't have much time to review this and next week. If you have time, @panglesd , that'd be very cool. If not, I'll review as soon as I'm back.

@gridbugs gridbugs force-pushed the driver-benchmark branch 2 times, most recently from 38e6bf8 to 939762d Compare October 4, 2022 01:44
@gridbugs
Copy link
Contributor Author
gridbugs commented Oct 4, 2022

I added a ppxlib-bench package to this repo with the extra deps needed for benchmarks. This package relies on a newer version of ocaml (4.10 rather than 4.04 due to its dependency on ppx_sexp_conv). This has resulted in ci only being run on versions of the compiler >= 4.10.

An alternative would be to move the benchmark to a separate repo. How important is it that ppxlib continue to support versions of ocaml older than 4.10?

@pitag-ha
Copy link
Member
pitag-ha commented Oct 4, 2022

How important is it that ppxlib continue to support versions of ocaml older than 4.10?

Short and concrete answer to this: I'd prefer to avoid dropping compiler support up to 4.10 to add benchmarks.

Longer and more general answer to this: For the same reason @panglesd mentioned above why we never add new hard dependencies to ppxlib, we also tend to try to avoid dropping compiler version support for ppxlib: a big part of the opam ecosystem depends transitively on ppxlib and some package maintainers wouldn't be happy if they'd have to drop support for some compilers because of ppxlib. That being said, when there's a good reason to drop old compilers, we do so. Usually the hard lower bound is the min of the versions rescript etc use (I think that's currently still lower than 4.10.0).

This has resulted in ci only being run on versions of the compiler >= 4.10.

As mentioned above, to fix this I think you could have a compiler >= 4.04.1 bound in the opam file and desable the builds of the benchmark files in the CI by adding

(enabled_if
  (>= %{ocaml_version} "4.10.0"))

to their dune files.

Signed-off-by: Stephen Sherratt <stephen@sherra.tt>
This prevents ppx_sexp_conv from being compiled in CI on versions of the
ocaml compiler which it does not support.

Signed-off-by: Stephen Sherratt <stephen@sherra.tt>
@gridbugs gridbugs force-pushed the driver-benchmark branch 3 times, most recently from 15547d2 to f87e922 Compare October 5, 2022 02:55
@gridbugs
Copy link
Contributor Author
gridbugs commented Oct 5, 2022

I've updated all the benchmarking dune files so that they only build on ocaml >= 4.10, and now the tests for older version of the compiler are running again.

@panglesd
Copy link
Collaborator
panglesd commented Oct 5, 2022

Thanks! Sorry for leading you into the wrong direction with the package thing.

I'll review the code soon!

Copy link
8000
Collaborator
@panglesd panglesd left a comment

Choose a reason for hiding this comment

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

Looks good to me!

I made a suggestion for a more human-readable output for local benchmarking, otherwise the code, and benchmark organization, looks great! It will be easy to add new benchmarks.

bench/bench.ml Outdated
let n_warmup = 10 in
let n = 100 in
Benchmark_suite.run_benchmarks ~n_warmup ~n
|> Yojson.to_string |> print_endline
Copy link
Collaborator

Choose a reason for hiding this comment

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

If that's not impacting current-bench (I guess no!) it could be nice to print the results in a more user-friendly way, to be able to read the results locally as well.

Suggested change
|> Yojson.to_string |> print_endline
|> Yojson.pretty_to_string |> print_endline

bench/bench.ml Outdated
Comment on lines 174 to 198
module Path_to_current_exe = struct
let via_procfs () =
(* Look up the current executable's path in the proc filesystem. *)
let pid = Unix.getpid () in
let proc_exe_path = Printf.sprintf "/proc/%d/exe" pid in
if Sys.file_exists proc_exe_path then Some (Unix.readlink proc_exe_path)
else None

let via_cwd () =
(* Assume the current working directory is the root of the project (as it
would be if this was run via `make bench`) and find the path to the
current exe relative to the project root *)
let cwd = Unix.getcwd () in
let relative_path_parts = "_build/default/bench/bench.exe" in
let absolute_path = Filename.concat cwd relative_path_parts in
if Sys.file_exists absolute_path then Some absolute_path else None

let methods = [ via_procfs; via_cwd ]

let get () =
let maybe_path = List.find_map (fun m -> m ()) methods in
match maybe_path with
| Some path -> path
| None -> failwith "couldn't determine the path to the current exe"
end
Copy link
Collaborator

Choose a reason for hiding this comment

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

This code is just to deal with the case where bench is called somewhere else than the root of the project. That's a nice attention to details 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

Signed-off-by: Stephen Sherratt <stephen@sherra.tt>
@gridbugs
Copy link
Contributor Author
gridbugs commented Oct 6, 2022

Thanks! Sorry for leading you into the wrong direction with the package thing.

I'll review the code soon!

All good! I still ended up making a ppx-bench package to handle extra dependencies required only for benchmarking.

"dune" {>= "2.7"}
"ocaml" {>= "4.04.1"}
"ppxlib" {= version}
"base"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you add this for consistency with the dune-project file?

Suggested change
"base"
"base" {>= "v0.15" & < "v0.16"}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I ended up removing the versions from dune-project instead because they were causing CI to limit the versions of ocaml used for testing to just those compatible with that range of versions.

Signed-off-by: Stephen Sherratt <stephen@sherra.tt>
@panglesd
Copy link
Collaborator

Thanks, @gridbugs! Looking forward to integrating this with current-bench.

@panglesd panglesd merged commit 9db9491 into ocaml-ppx:main Oct 17, 2022
@panglesd
Copy link
Collaborator

I tried to enrol this repository in ocaml-benchmark, but "This action must be performed by an organization owner".

Also, there are no public people in the ocaml-ppx organization, so I don't know who to ping!

@pitag-ha
Copy link
Member

I already enrolled it on Monday: https://autumn.ocamllabs.io/ocaml-ppx/ppxlib . I think anyone of us could have done it (we should have the same permissions).

There seems to be a bug, though: notice the "No data for selected interval.". We think it's on the current-bench side and @ElectreAAS is already kindly looking into it.

@kit-ty-kate
Copy link
Contributor

Hi, this change broke all most of the packages relying on mirage. Is there a particular reason why ppx_sexp_conv is vendored? Why not pulling it up as a normal opam dependency of the ppxlib-bench package?

@panglesd
Copy link
Collaborator

Ouch, sorry for the mess!

I can't remember or find any reason to vendor instead of pulling it as normal dependency. Maybe it was needed before the ppxlib-bench package was created? @gridbugs do you remember?

Without reason to do otherwise, I'll open a PR removing the vendored bench dependency, and make a 0.29.1 release quickly.

@ceastlund
Copy link
Collaborator

Last I spoke to @pitag-ha about it, it was vendored in order to have more control over its versioning. I don't know any deeper than that what the reasoning was, perhaps Sonja remembers.

@kit-ty-kate
Copy link
Contributor

I may understand why it was done this way, after trying to patch this. ppx_sexp_conv is used as the main user of ppxlib for the benchmark. So you need it to be compiled using ppxlib inside the project. Installing it from opam would use the latest stable instead (and would make the bench target unbuildable)

I'm not sure what's the best way to fix that. So far I'm leaning into reduce the vendor by removing everything that's not used and removing the public libraries, which should fix the issues when vendoring ppxlib itself. I'm having an issue with the extender which i can't get to compile for some reason tho at the moment so i haven't opened a PR yet.

@pitag-ha
Copy link
Member

Arrg. Thanks for pointing this out, @kit-ty-kate!

We can choose a different PPX for benchmarking and vendor that one (and get rid of ppx_sexp_conv). It doesn't need to be ppx_sexp_conv. @kit-ty-kate, do you have an idea/suggestion which PPX we could vendor without breaking anyone on opam? If not, one of us will have a look through the PPXs to find a good fit. In case there's none (although I'd be surprised), we'll write our custom benchmark PPX.

@gridbugs
Copy link
Contributor Author

If I remember correctly I chose to vendor ppx_sexp_conv because I didn't want it to be possible to change the version of ppx_sexp_conv used in the benchmark experiments as this could impact the results of the benchmarks. Apologies for the breakage! Thanks all for sorting it out.

@kit-ty-kate mind sharing why vendoring ppx_sex_conv caused such a breakage? Are there potential dangers of vendoring packages?

@kit-ty-kate
Copy link
Contributor

@gridbugs i wrote about it in the description of #386. If you need more specific information I can add it there

@gridbugs
Copy link
Contributor Author

Excellent, thanks @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.

7 participants
0