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

Refactor Binds to Source members #12

Merged
merged 3 commits into from
Dec 1, 2022
Merged

Refactor Binds to Source members #12

merged 3 commits into from
Dec 1, 2022

Conversation

TheAngryByrd
Copy link
Owner

@TheAngryByrd TheAngryByrd commented Nov 30, 2022

Proposed Changes

This uses the Source member overloads to provide a more stripped down version of the ColdTask and CancellableTask CEs.

Similar to the work I did in demystifyfp/FsToolkit.ErrorHandling#83

Types of changes

What types of changes does your code introduce to IcedTasks?
Put an x in the boxes that apply

  • Refactoring

Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.

  • Build and tests pass locally
  • I have added tests that prove my fix is effective or that my feature works (if appropriate)
  • I have added necessary documentation (if appropriate)

Further comments

If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...

@TheAngryByrd
Copy link
Owner Author

@dsyme do you know of any reason I should not use Source member overloads like this to reduce the complexity of a resumable CE?

cc @abelbraaksma @NinoFloris

@abelbraaksma
Copy link

Let's /cc @gusty. He mentioned to me the other day that this has been around since a long time, but only covered in the spec, not in docs. As far as I know this is safe to do, but maybe Gus can glance over these changes if he knows the intrinsics of this approach?

@NinoFloris
Copy link

Not as far as I know @TheAngryByrd. There are of course some overload resolution cases where having the continuation arguments in the same resolution as the value can influence the outcome to be a better fit but in almost all cases I've been able to restructure to still be able to use Source.

Copy link

@abelbraaksma abelbraaksma left a comment

Choose a reason for hiding this comment

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

This is a pretty awesome change. Are the timing differences due to .NET 7 or caused by the move to Source? They are quite impressive.

@@ -324,6 +324,8 @@ module Helpers =
[<CategoriesColumn>]
type AsyncBenchmarks() =

let getTempFileName () =
Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("n"))

Choose a reason for hiding this comment

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

Just a thought: if you dump these in an IDisposable, you can actually delete the files after the tests. Or use setup/teardown, which I believe BenchmarkDotnet also supports.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Yeah, i need to steal my disposabledirectory/file code from other repos

| AsyncBinds_cancellableTask_bindCancellableTask | AsyncBinds | 20,201.2 μs | 400.21 μs | 852.88 μs | 20,049.0 μs | 1.25 | 0.15 | 31.2500 | - | - | 320 KB |
| Method | Categories | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio |
|------------------------------------------------ |-------------- |-------------:|-------------:|-------------:|-------------:|-------:|--------:|-----------:|-------------:|------------:|
| AsyncBinds_CSharpTasks | AsyncBinds | 3,329.6 μs | 28.27 μs | 26.45 μs | 3,334.1 μs | 1.00 | 0.00 | 3.9063 | 109.39 KB | 1.00 |
Copy link

@abelbraaksma abelbraaksma Nov 30, 2022

Choose a reason for hiding this comment

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

This (AsyncBinds_CSharpTasks /AsyncBinds) went from 17μs to 3μs? Is this due to the changed setup or can "old vs new" be compared? It's a pretty amazing perf gain!

Copy link
Owner Author

Choose a reason for hiding this comment

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

I wouldn't read too much into these as this has changed machines.

and ^Awaiter: (member get_IsCompleted: unit -> bool)
and ^Awaiter: (member GetResult: unit -> 'TResult1)>
(
sm: byref<ResumableStateMachine<CancellableTaskStateMachineData<'TOverall>>>,
task: ^TaskLike,
[<InlineIfLambda>] getAwaiter: CancellationToken -> ^Awaiter,

Choose a reason for hiding this comment

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

Not sure this makes a difference, since the argument is already static (i.e., it uses an SRTP constraint, so it has to be inlined). Did you see a difference in the generated code?

Copy link
Owner Author

Choose a reason for hiding this comment

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

No I still haven't gotten around to investigating the different state machine generation and yeah I'm unsure how often I'd actually need InlineIfLambda if at all in most cases in this file anyway.

Choose a reason for hiding this comment

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

For (some) insights, see this answer by Don: dotnet/fsharp#14123 (comment)

@gusty
Copy link

gusty commented Nov 30, 2022

I don't think there's something special about Source it can be overloaded as any other methods at the risk of the scaling (logical) limitations of doing Ad-hoc overloading for the sole purpose of saving keystrokes.

@abelbraaksma
Copy link

abelbraaksma commented Nov 30, 2022

@gusty I think the main use-case here is that by using Source, you'd have less boilerplate to write in the Bind and Yield functions. In other words, it's not just saving keystrokes, but making the implementation more resilient, where Source is used like a "gateway" and the rest is unified. At least that's what I take from it.

The main question at hand is: is there any caveat to using it? (also asking because of my own interest in the method).

@gusty
Copy link

gusty commented Nov 30, 2022

you'd have less boilerplate to write in the Bind and Yield functions. In other words, it's not just saving keystrokes,

Well, you're saving keystrokes there already. Ideally the user should explicitly convert. Moving it to Source won't change anything in that regard.

But going to your main question:

The main question at hand is: is there any caveat to using it? (also asking because of my own interest in the method).

Not that I know. I never used it in my OSS projects, but I used it in many prototypes and I wouldn't hesitate to use it in any OSS project, it's just that I still didn't find a problem that it would solve there.

@abelbraaksma
Copy link

Great, thanks! Looking at the diff here, the main use case is simplification. That, of course, isn't needed in each and every CE.

@TheAngryByrd TheAngryByrd merged commit 88d5c6a into master Dec 1, 2022
@TheAngryByrd
Copy link
Owner Author

Thank you everyone for your feedback. Highly appreciated!

@TheAngryByrd TheAngryByrd changed the title Source members Refactor Binds to Source members Dec 1, 2022
TheAngryByrd added a commit that referenced this pull request Dec 1, 2022
## [0.3.2-beta001] - 2022-11-30

### Changed
- [Refactor Binds to Source members](#12) Credits @TheAngryByrd
TheAngryByrd added a commit that referenced this pull request Dec 1, 2022
## [0.3.2-beta002] - 2022-11-30

### Changed

- [Refactor Binds to Source members](#12) Credits @TheAngryByrd
- [Expand TFMs to netstandard2.0 and 2.1](#13) Credits @TheAngryByrd
- [InlineIfLambda was just adding compile time without benefit](#14) Credits @TheAngryByrd

- [Refactor Binds to Source members](#12) Credits @TheAngryByrd
TheAngryByrd added a commit that referenced this pull request Dec 1, 2022
## [0.3.2] - 2022-11-30

### Changed
- [Refactor Binds to Source members](#12) Credits @TheAngryByrd
- [Expand TFMs to netstandard2.0 and 2.1](#13) Credits @TheAngryByrd
- [InlineIfLambda was just adding compile time without benefit](#14) Credits @TheAngryByrd
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