Skip to content
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

Add a note on whether microlens-th is recommended for libraries in the README #78

Open
seagreen opened this issue Jul 6, 2016 · 9 comments

Comments

@seagreen
Copy link
Contributor

seagreen commented Jul 6, 2016

Right now the README helpfully suggests that library authors start with microlens instead of microlens-platform and add packages as needed.

I'm curious if microlens-th is appropriate for library authors, or whether slowing down the library's compile time isn't worth the tradeoff of conveniently deriving lenses. Has how much makeLenses slows down compilation been researched? If it hasn't would that be a useful thing for me to look into and contribute to the README?

@neongreen
Copy link
Collaborator

Has how much makeLenses slows down compilation been researched?

I don't think it has been.

would that be a useful thing for me to look into

Yep! I can think of several questions off the top of my head:

  • How does compilation time increase when makeLenses is applied to a record with one field? Two? Ten? Thirty?
  • Does the increase depend on whether there's lots of other code in the file, or is it independent of it?
  • How does enabling/disabling optimisations influence compilation time?
  • How big of a difference does writing lenses manually make?

@neongreen
Copy link
Collaborator

Note that if you simply compile a module with lenses, the optimiser might remove unused code instead of optimising it further (I don't know whether it's actually possible but it seems plausible), so don't forget to export the derived lenses. Benchmarking can probably be done with bench.

@seagreen
Copy link
Contributor Author

seagreen commented Jul 6, 2016

Thanks for the thoughts, this is going on my todo list.

@seagreen
Copy link
Contributor Author

Make an initial experimental repo:

Here are manual lenses: https://github.com/seagreen/microlens-th-experiments/blob/master/plain-lenses/src/Experiment.hs#L121

Here are th lenses: https://github.com/seagreen/microlens-th-experiments/blob/master/th-lenses/src/Experiment.hs#L122

And here are the results: https://github.com/seagreen/microlens-th-experiments/blob/master/results.txt

The test sources are the most boring thing I could think of. 5 data types, each with 20 fields, nothing else (the only exception is the small-data project which has 5 data types with 1 field each).

I've got some thoughts on the results, but take a look at the code first and let me know what you think.

@seagreen
Copy link
Contributor Author

PS bench was a great recommendation.

@neongreen
Copy link
Collaborator

Thanks!

I modified the test to call ghc on one file instead of stack (and also to run longer with -L 300). With 7.10.3 I'm getting that lens generation takes 400ms (and compilation – 1s):

small-data
benchmarking rm -f src/*.hi; rm -f src/*.o; ghc -O src/Experiment.hs
time                 160.5 ms   (155.7 ms .. 165.3 ms)

no-lenses
benchmarking rm -f src/*.hi; rm -f src/*.o; ghc -O src/Experiment.hs
time                 335.8 ms   (331.1 ms .. 339.7 ms)

plain-lenses
benchmarking rm -f src/*.hi; rm -f src/*.o; ghc -O src/Experiment.hs
time                 1.063 s    (1.054 s .. 1.073 s)

th-lenses
benchmarking rm -f src/*.hi; rm -f src/*.o; ghc -O src/Experiment.hs
time                 1.457 s    (1.437 s .. 1.484 s)

With stack ghc and GHC 8 lens generation takes the same 400ms, but compilation jumps to 1.3s (might be because of compiling dyn files too, I don't know how to turn it off):

small-data
benchmarking rm -f src/*.hi; rm -f src/*.o; rm -f src/*.dyn_hi; rm -f src/*.dyn_o; stack ghc --resolver nightly-2016-07-04 -- -O src/Experiment.hs
time                 327.5 ms   (318.4 ms .. 336.3 ms)

no-lenses
benchmarking rm -f src/*.hi; rm -f src/*.o; rm -f src/*.dyn_hi; rm -f src/*.dyn_o; stack ghc --resolver nightly-2016-07-04 -- -O src/Experiment.hs
time                 550.2 ms   (537.5 ms .. 564.4 ms)

plain-lenses
benchmarking rm -f src/*.hi; rm -f src/*.o; rm -f src/*.dyn_hi; rm -f src/*.dyn_o; stack ghc --resolver nightly-2016-07-04 -- -O src/Experiment.hs
time                 1.324 s    (1.317 s .. 1.335 s)

th-lenses
benchmarking rm -f src/*.hi; rm -f src/*.o; rm -f src/*.dyn_hi; rm -f src/*.dyn_o; stack ghc --resolver nightly-2016-07-04 -- -O src/Experiment.hs
time                 1.727 s    (1.701 s .. 1.763 s)

@neongreen
Copy link
Collaborator

Interestingly, in your tests the difference between manual and TH lenses is much smaller. Can you rerun them with a bigger -L? (It controls how many seconds the benchmark will run)

@neongreen
Copy link
Collaborator

Another thing to do, by the way, is to figure out how the added time depends on the number of fields vs the number of records. Does it matter if the fields are in different records, or not?

@seagreen
Copy link
Contributor Author

Here are my results with -L 300. The difference between manual and TH lenses stayed small.

benchmarking cd ~/code/mine/microlens-th-experiments/small-data; rm -rf ./.stack-work; stack build
time                 2.688 s    (2.677 s .. 2.696 s)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 2.695 s    (2.689 s .. 2.705 s)
std dev              15.70 ms   (8.709 ms .. 25.10 ms)

benchmarking cd ~/code/mine/microlens-th-experiments/no-lenses; rm -rf ./.stack-work; stack build
time                 2.913 s    (2.893 s .. 2.926 s)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 2.934 s    (2.921 s .. 2.959 s)
std dev              30.07 ms   (5.817 ms .. 43.02 ms)

benchmarking cd ~/code/mine/microlens-th-experiments/plain-lenses; rm -rf ./.stack-work; stack build
time                 3.778 s    (3.732 s .. 3.830 s)
                     1.000 R²   (0.999 R² .. 1.000 R²)
mean                 3.756 s    (3.745 s .. 3.780 s)
std dev              27.24 ms   (14.54 ms .. 42.07 ms)

benchmarking cd ~/code/mine/microlens-th-experiments/th-lenses; rm -rf ./.stack-work; stack build
time                 3.985 s    (3.967 s .. 4.005 s)
                     1.000 R²   (1.000 R² .. 1.000 R²)
mean                 3.979 s    (3.973 s .. 3.987 s)
std dev              11.94 ms   (7.659 ms .. 15.89 ms)

Want to push up your changes (you've got push access to the repo) and then I can rerun them with an identical setup to you?

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

No branches or pull requests

2 participants