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

improve std bench and add significant-digits #859

Merged
merged 17 commits into from
Jun 1, 2024

Conversation

maxim-uvarov
Copy link
Contributor

Hi! I propose several changes to std bench:

  • Remove insignificant precision by default (can be reverted with --sign-digits=0).
  • Remove the 'times' field by default (can be returned with --list-timings).
  • Add an option to set time units (inactive by default).

For removing insignificant precision, I needed a new command significant-digits which is also included in this PR. This command has tests.

image image image

@maxim-uvarov maxim-uvarov marked this pull request as draft May 31, 2024 13:56
@maxim-uvarov
Copy link
Contributor Author

I will add tests to bench itself too

@maxim-uvarov maxim-uvarov marked this pull request as ready for review June 1, 2024 04:10
@maxim-uvarov
Copy link
Contributor Author

Dear maintainers, please, take a look. I think it is ready for review

@fdncred
Copy link
Collaborator

fdncred commented Jun 1, 2024

I like it. Thanks!

@fdncred fdncred merged commit 5271d68 into nushell:main Jun 1, 2024
1 check failed
@amtoine
Copy link
Member

amtoine commented Jun 1, 2024

@maxim-uvarov 👋

i have a question: when --units is set, what is the type of the durations in the output? it looks like a string with ms at the end in your example, rigth?

@amtoine
Copy link
Member

amtoine commented Jun 1, 2024

generally, i would say that all these changes are nice improvements but pretty much out of the scope of std bench 😕

std bench is just for measuring, formatting could be done in another command, e.g.

bench { sleep 0.1sec; 1 + 2 } --rounds 5 --verbose # the current `std bench` command
    | reject times                                 # same as not using `--list-timings` in your implementation
    | bench format --units ms --sign-digits 2      # same as your `--units` and `--sign-digits`

of course, that's my way of thinking, i like commands that do one thing 😌

@maxim-uvarov maxim-uvarov deleted the bench-sign-digits branch June 1, 2024 10:51
@maxim-uvarov
Copy link
Contributor Author

maxim-uvarov commented Jun 1, 2024

@amtoine, I understand your concern! I really envisioned this and spent a number of hours polishing my proposal before submitting it. My motivation was to create a more convenient function with better defaults.

My motivation comes from the perspective of a non-developer, for whom typing every symbol is much more effortful than for a seasoned professional like you (who might be the target audience for std bench).

Maybe you would agree with me that this representation is very wordy and unnecessary, even for a professional?

1sec 333ms 333µs 333ns

And times are expaneded by default with my settings.

image

Perhaps we can:

  1. Incorporate the feature of truncating resetting digits after the fourth one for results (maximum error 0.05%, plus a duration stays as a duration).
  2. Get rid of the times field from std bench since it is quite easy to produce times for further operations with
1..50 | each {timeit{something}}

and not introduce any new options and flags to std bench?

@amtoine What do you think?

@maxim-uvarov
Copy link
Contributor Author

maxim-uvarov commented Jun 1, 2024

i have a question: when --units is set, what is the type of the durations in the output? it looks like a string with ms at the end in your example, rigth?

--units is an option. If it is unset - all the values are produced as duration. If it is set to some unit - it will produce formatted strings accordingly.

@amtoine
Copy link
Member

amtoine commented Jun 1, 2024

@amtoine, I understand your concern! I really envisioned this and spent a number of hours polishing my proposal before submitting it. My motivation was to create a more convenient function with better defaults.

My motivation comes from the perspective of a non-developer, for whom typing every symbol is much more effortful than for a seasoned professional like you (who might be the target audience for std bench).

yeah, the target audience of std bench is people who would want to run benchmarks in Nushell, i.e. very likely seasoned professionals 😉

Maybe you would agree with me that this representation is very wordy and unnecessary, even for a professional?

1sec 333ms 333µs 333ns

maybe, but then i would argue the issue comes from the formatting nushell does on durations, not from std bench, it's just that Nushell will show every part of the duration 😕

And times are expaneded by default with my settings.

image

again, that's not the fault of std bench, but rather probably your display_output hook 😉
the intent of returning $.times is to allow the developer to perform other operations on the raw measurements without blindly trusting the $.mean and $.std! (seed nushell/nushell#12913)

Perhaps we can:

  1. Incorporate the feature of truncating resetting digits after the fourth one for results (maximum error 0.05%, plus a duration stays as a duration).
  2. Get rid of the times field from std bench since it is quite easy to produce times for further operations with
1..50 | each {timeit{something}}

and not introduce any new options and flags to std bench?

@amtoine What do you think?

  1. maybe, i dunno 🤣 i think users that really want to run std bench in the REPL and not in a script could just throw format duration ms on the times and that would solve evertything without changing anything
  2. i wouldn't because returning the raw times was one of the intent of std bench and i would argue it's not a huge burden for the users to add reject times 😋

again, these are just my two cents, i would not die on that, it's not critical 😌

@maxim-uvarov
Copy link
Contributor Author

maxim-uvarov commented Jun 1, 2024

@amtoine thank you for explaining.

I just leave my opinion here without intention of convincing you. I won't die either if my proposal won't be accepted, no worries :)

  1. maybe, i dunno 🤣 i think users that really want to run std bench in the REPL and not in a script could just throw format duration ms on the times and that would solve evertything without changing anything

AFAIK there is no easy way to format durations in the all record fields now. update cells works only with tables.

> bench -n 10 {sleep 0.1sec} | format duration ms
Error: nu::shell::only_supports_this_input_type
  1. i wouldn't because returning the raw times was one of the intent of std bench and i would argue it's not a huge burden for the users to add reject times 😋

I have intuition, that users will need to write reject times much more often than to use bench without it. And when they need it - it is really easy to type.

1..50 | each {timeit{something}}

@amtoine
Copy link
Member

amtoine commented Jun 1, 2024

@amtoine thank you for explaining.

🙏

I just leave my opinion here without intention of convincing you. I won't die either if my proposal won't be accepted, no worries :)

❤️

AFAIK there is no easy way to format durations in the all record fields now. update cells works only with tables.

> bench -n 10 {sleep 0.1sec} | format duration ms
Error: nu::shell::only_supports_this_input_type

i took out my wizard wand and found a solution to this 😉

bench -n 10 {sleep 0.1sec} | reject times | format duration ms ...($in | columns)

I have intuition, that users will need to write reject times much more often than to use bench without it. And when they need it - it is really easy to type.

1..50 | each {timeit{something}}

true, but that last command is precisely what std bench has been written for, to avoid writing that each time, but bench { something } --rounds 50 instead 😏

@maxim-uvarov
Copy link
Contributor Author

maxim-uvarov commented Jun 1, 2024

bench -n 10 {sleep 0.1sec} | reject times | format duration ms ...($in | columns)

that is cool! thank you, @amtoine! 🙏

--units is really unnecessary then

fdncred pushed a commit that referenced this pull request Jun 3, 2024
@amtoine gave me valuable feedback about the [PR of `std bench`
improvement](#859) CANDIDATE
into `stdlib-candidates`.

I understood and respected his reasoning about his position. Yet, I
still believe that users of `std bench` will benefit from my proposal.

I incorporated some of @amtoine advice in this PR.

I removed the `bench --units` option as I now believe it is better to
encourage users to use core functionality for formatting duration (which
I had not thought of initially) and to avoid multiplying `--options`.

```
bench -n 10 {sleep 0.1sec} | format duration ms mean min max stddev
# or
bench -n 10 {sleep 0.1sec} | format duration ms ...($in | columns)
```

Also, I removed the option of `--sign-digits` and just hard-coded the
precision of conversion to the fourth significant digit (which will give
a maximum relative error of 0.05%, which I still think is unnecessarily
precise).

To explain my motivation, I added some context from our previous
conversation:

>> Maybe you would agree with me that this representation is very wordy
and unnecessary, even for a professional?
>> `1sec 333ms 333µs 333ns`

> maybe, but then i would argue the issue comes from the formatting
nushell does on durations, not from std bench, it's just that Nushell
will show every part of the duration 😕

And I add here that if Nushell adds the setting for resetting
insignificant digits from displaying, those conversions could be removed
for the better. Yet, we don't have such a setting yet, but we already
use bench and use it quite often. So, I propose this usability
improvement.

In my defense, I would add that the existing `--pretty` option will only
benefit from the proposed changes (while it can't benefit from `| format
duration ms`).

```diff
> bench {sleep (10sec / 3)} --rounds 2 --pretty
- 3sec 335ms 974µs 264ns +/- 1ms 108µs 748ns
+ 3sec 335ms +/- 1ms 108µs
```

Finally, I kept the `--list-timings` option because I strongly believe
that users much more often will not need expanded 50 lines of timing
results on their screen (which they can get rid of by adding `| reject
time` in the second execution of the `bench` command - but I would like
to avoid this second execution).

I won't be hurt if my proposed changes aren't accepted and applied to
mainstream. Yet, I feel like my initial PR is still valuable and will
benefit from my current PR's additions.
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.

None yet

3 participants