Skip to content

Conversation

@rubennorte
Copy link
Contributor

@rubennorte rubennorte commented Aug 12, 2025

This implements a feature to allow task functions to return a custom duration to be used for the benchmark.

This is useful in cases where we want to measure a subset of the function logic, where splitting that logic into beforeEach and afterEach wouldn't be possible or would be very inconvenient.

For example, if we want to measure the time spent rendering components in React without including the time executing their effects, we would do something like:

bench.add('my task', () => {
  let endTime;
  
  function ReportEndTime() {
    endTime = bench.opts.now();
  }
  
  function BenchmarkComponent() {
    return (
      <>
       {someViews}
       <ReportEndTime />
      </>
    );
  }
  
  const startTime = bench.opts.now();
  render(<BenchmarkComponent />);
  
  return { overriddenDuration: endTime - startTime };
});

@pkg-pr-new
Copy link

pkg-pr-new bot commented Aug 12, 2025

Open in StackBlitz

npm i https://pkg.pr.new/tinylibs/tinybench@329

commit: e481a91

@rubennorte
Copy link
Contributor Author

rubennorte commented Aug 12, 2025

I don't have strong opinions in terms of API design.

An alternative API could be something like this:

```javascript
bench.add('my task', (handle) => {
  let endTime;
  
  function ReportEndTime() {
    endTime = bench.opts.now();
  }
  
  function BenchmarkComponent() {
    return (
      <>
       {someViews}
       <ReportEndTime />
      </>
    );
  }
  
  const startTime = bench.opts.now();
  render(<BenchmarkComponent />);
  
  handle.overrideDuration(endTime - startTime);
});

@jerome-benoit
Copy link
Collaborator

jerome-benoit commented Aug 12, 2025

Sounds reasonable to propose an object with a keys namespace that can override some tinybench internal measurements. And I do not have any better idea at the moment.
The only issue I see is that the measurement done is not using the timestamping method in tinybench. It would be better for consistency in benchmarking to expose it and try to enforce its usage in that use case.

@rubennorte
Copy link
Contributor Author

Sounds reasonable to propose an object with a keys namespace that can override some tinybench internals measurements. And I do not have any better idea at the moment.

Thanks for the reply!

Are you supporting the option in the PR or the alternative solution I suggested in the comment?

@jerome-benoit
Copy link
Collaborator

jerome-benoit commented Aug 12, 2025

Sounds reasonable to propose an object with a keys namespace that can override some tinybench internals measurements. And I do not have any better idea at the moment.

Thanks for the reply!

Are you supporting the option in the PR or the alternative solution I suggested in the comment?

The option in the PR, looks more inline with an "natural" coding experience. My only concerns are about timestamping consistency: #329 (comment)

@rubennorte
Copy link
Contributor Author

The only issue I see is that the measurement done is not using the timestamping method in tinybench. It would be better for consistency in benchmarking to expose it and try to enforce its usage in that use case.

How would you suggest we do this?

I see that we can already customize a now option via BenchOptions but it just returns a number. We could introduce a new method to get an opaque benchmark from tinybench that provides a timestamp from it under the hood, but I think that would be unnecessarily complex, as it would now be added on top of the now() method that is already part of the public API.

@jerome-benoit
Copy link
Collaborator

jerome-benoit commented Aug 12, 2025

The only issue I see is that the measurement done is not using the timestamping method in tinybench. It would be better for consistency in benchmarking to expose it and try to enforce its usage in that use case.

How would you suggest we do this?

I see that we can already customize a now option via BenchOptions but it just returns a number. We could introduce a new method to get an opaque benchmark from tinybench that provides a timestamp from it under the hood, but I think that would be unnecessarily complex, as it would now be added on top of the now() method that is already part of the public API.

I have to check, but would it be difficult to add now as a possible argument to bench.add() ?

@rubennorte
Copy link
Contributor Author

The only issue I see is that the measurement done is not using the timestamping method in tinybench. It would be better for consistency in benchmarking to expose it and try to enforce its usage in that use case.

How would you suggest we do this?
I see that we can already customize a now option via BenchOptions but it just returns a number. We could introduce a new method to get an opaque benchmark from tinybench that provides a timestamp from it under the hood, but I think that would be unnecessarily complex, as it would now be added on top of the now() method that is already part of the public API.

I have to check, but would it be difficult to add now as a possible argument to bench.add() ?

We could, but the question is how do you force users to use that version instead of any other.

Unless you provide a new API that provides special values and you validate that the custom duration (or custom start/end) uses them, I don't think it's possible.

@jerome-benoit
Copy link
Collaborator

We could, but the question is how do you force users to use that version instead of any other.

Unless you provide a new API that provides special values and you validate that the custom duration (or custom start/end) uses them, I don't think it's possible.

The idea is to at least offer a way to reuse the custom or the default timestamping easily for that use case. Let's users shoot themselves in the foot if mixing timestamping methods and accuracy. I think we can assume that they have a clue on what they are doing and documentation on proper usage should be enough.

@rubennorte
Copy link
Contributor Author

rubennorte commented Aug 12, 2025

We could, but the question is how do you force users to use that version instead of any other.
Unless you provide a new API that provides special values and you validate that the custom duration (or custom start/end) uses them, I don't think it's possible.

The idea is to at least offer a way to reuse the custom or the default timestamping easily for that use case. Let's users shoot themselves in the foot if mixing timestamping methods and accuracy. I think we can assume that they have a clue on what they are doing and documentation on proper usage should be enough.

Oh, I see. We can add a now() method to Bench that's just the resolved value for the now option. I'll do that and update the documentation.

Edit: the option already exists via bench.opts.now() but it was incorrectly typed as nullable. I fixed that and we can use that in benchmarks (I indicate that in the test).

@rubennorte rubennorte force-pushed the allow-overridding-fn-duration branch 2 times, most recently from d844275 to c83ea6e Compare August 13, 2025 09:56
@rubennorte rubennorte force-pushed the allow-overridding-fn-duration branch from c83ea6e to e481a91 Compare August 13, 2025 09:59
Copy link
Collaborator

@jerome-benoit jerome-benoit left a comment

Choose a reason for hiding this comment

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

A 4.1 release will be done shortly after the merge.

Thanks.

@jerome-benoit jerome-benoit merged commit 67b46e7 into tinylibs:main Aug 13, 2025
15 checks passed
@rubennorte
Copy link
Contributor Author

A 4.1 release will be done shortly after the merge.

Thanks.

thanks for the review, @jerome-benoit !

@rubennorte rubennorte deleted the allow-overridding-fn-duration branch August 13, 2025 11:08
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