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

Fix WithLatestFrom potential memory visibility issues #247

Merged
merged 4 commits into from Sep 23, 2016

Conversation

akarnokd
Copy link
Collaborator

@akarnokd akarnokd commented Aug 5, 2016

As I reported in #227, setting a volatile hasLatest doesn't ensure proper visibility of the latest value and one needs at least an ordered store for the whole element (by boxing it and writing the reference in with an ordered store).

Cost of correctness: one boxing and one unboxing of structure types.

Possible tradeoff choice: using Volatile.Write instead of Interlocked.Exchange; both are correct but the former may only become visible a bit delayed (once the CPU write buffer is emitted) whereas the latter is "immediately" visible to other cores.

@dnfclas
Copy link

dnfclas commented Aug 5, 2016

Hi @akarnokd, I'm your friendly neighborhood .NET Foundation Pull Request Bot (You can call me DNFBOT). Thanks for your contribution!

This seems like a small (but important) contribution, so no Contribution License Agreement is required at this point. Real humans will now evaluate your PR.

TTYL, DNFBOT;

@dnfclas
Copy link

dnfclas commented Aug 5, 2016

@akarnokd, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR.

Thanks, DNFBOT;

@akarnokd
Copy link
Collaborator Author

akarnokd commented Aug 5, 2016

=== TEST EXECUTION SUMMARY ===
   Tests.System.Reactive  Total: 3419, Errors: 0, Failed: 0, Skipped: 2, Time: 20.187s

Tests passed but then something failed.

@akarnokd akarnokd closed this Aug 5, 2016
@akarnokd akarnokd reopened this Aug 5, 2016
@dnfclas
Copy link

dnfclas commented Aug 5, 2016

Hi @akarnokd, I'm your friendly neighborhood .NET Foundation Pull Request Bot (You can call me DNFBOT). Thanks for your contribution!
You've already signed the contribution license agreement. Thanks!

The agreement was validated by .NET Foundation and real humans are currently evaluating your PR.

TTYL, DNFBOT;

@bartdesmet
Copy link
Collaborator

Please rework to avoid the boxing. I'd prefer a plain old lock over boxing with arbitrary box lifetimes which solely depend on the incoming sequence's timing.

@akarnokd
Copy link
Collaborator Author

akarnokd commented Aug 5, 2016

@bartdesmet That may only be possible if I use locks; I don't know the cost of boxing but I'd assume its less than taking a lock.

@bartdesmet
Copy link
Collaborator

bartdesmet commented Aug 5, 2016

@akarnokd - I'm not as much concerned about the cost of boxing than I am about the effects down the line. In the Bing service I'm working on now, we're very allergic to any boxing without prior knowledge about the eventual lifetime of the box: if it's known to be short-lived, it's ok (if the box can't be avoided at all); if it's known to be very long-lived (ideally infinitely long), it's ok to let it age to Gen-2 (if the box can't be avoided at all); if it's somewhere in the middle, we'll pay the cost during a GC down the line. In this particular case, we're dealing with lifetimes dependent on the velocity of the TSecond stream and the struct may be arbitrarily big (think the new ValueTuple<...> for C# 7.0 as a great source of N-ary composite objects).

My recommendation would be to use a lock (correctness above everything else), as we do in many places, and keep the costs in the control plane (IDisposable, cf. your other PR, thanks!) and on the input side (subjects) low by exploring lock free approaches. For high-performance scenarios, the best advice I'd have is to have many instances of single-threaded Rx executors with operators that don't do any locking at all. That's closer to what we do in Bing with single-threaded schedulers (N of which run in a process, where N is aligned with the number of cores) that merge events from many sources (a la what Tx does) onto a single event dispatch loop. It makes an assumption though about being able to control the threading and where the sources produce their messages (easier to do in a service where all the input comes from big pipes over the network). This would also work well for UI frameworks etc. that are single-threaded anyway.

@akarnokd
Copy link
Collaborator Author

akarnokd commented Aug 5, 2016

Okay. I'll change it to use a lock.

@bartdesmet
Copy link
Collaborator

Cool, thanks! Do you still have issues with contribution agreement we have to look into?

@akarnokd
Copy link
Collaborator Author

akarnokd commented Aug 5, 2016

No, found another link and signed it (see cla-already-signed label).

@akarnokd
Copy link
Collaborator Author

akarnokd commented Aug 5, 2016

Updated the PR, not sure what takes so long for the CI (I get access denied is it may not even run yet).

@@ -39,12 +40,14 @@ public _(WithLatestFrom<TFirst, TSecond, TResult> parent, IObserver<TResult> obs
}

private object _gate;
private volatile bool _hasLatest;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you change the field name back to _hasLatest for consistency and to minimize the diff?

@akarnokd
Copy link
Collaborator Author

akarnokd commented Aug 5, 2016

Done.

@shiftkey
Copy link
Contributor

shiftkey commented Aug 8, 2016

👍

@clairernovotny
Copy link
Member

@shiftkey @bartdesmet @mattpodwysocki is this good to merge?

@shiftkey shiftkey merged commit 24eba2a into dotnet:master Sep 23, 2016
@akarnokd akarnokd deleted the WithLatestFromFix branch May 2, 2018 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants