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

Moved to atomic field updaters. #1246

Merged

Conversation

akarnokd
Copy link
Member

Replaced the AtomicBoolean, AtomicInteger, AtomicLong and AtomicReference instances with volatile fields and field updaters to save on memory and allocation.

Unfortunately, the Clojure test chunk_test.clj:test-chunk fails and I don't know why since I don't understand what it is supposed to do. It appears numbers get lost somehow.

@cloudbees-pull-request-builder

RxJava-pull-requests #1146 FAILURE
Looks like there's a problem with this pull request

@akarnokd
Copy link
Member Author

I've been digging into the failure case and it seems something in the Clojure wrapper calls the merger's Subscriber.onCompleted multiple times which is a violation of the observer contract. The call comes from chunk.clj:68.

@benjchristensen
Copy link
Member

This looks like a great set of changes ... however, huge amounts of code have been touched so it's making it really hard to review this. Most of the changes seem to be formatting changes, is that the case? If so, can you prevent that so as to simplify the review? This is 1800 lines of code to review :-)

@akarnokd
Copy link
Member Author

Whenever I use fix-indent in Netbeans, this is the result, few spaces added here, few spaces removed there. But only a fraction is just formatting changes.

@vinc3m1
Copy link

vinc3m1 commented May 23, 2014

Adding ?w=1 ignores whitespace changes and seems to make it a bit better

@daschl
Copy link
Contributor

daschl commented May 23, 2014

@vinc3m1 :octocat: nice hidden feature

return buf.take();
}

void setWaiting(int value) {
WAITING_UPDATER.lazySet(this, value);
Copy link
Member

Choose a reason for hiding this comment

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

Help me understand why lazySet is safe to use here. It seems we want to have visibility of this value when we next read, but my understanding of lazySet is that it does not guarantee that.

Copy link
Member

Choose a reason for hiding this comment

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

I read up further on lazySet and added another comment to code above.

Copy link
Member Author

Choose a reason for hiding this comment

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

The value set here is eventually visible, which may take a few nanoseconds. The benefit is that the lazySet doesn't flush the store buffer whereas a volatile write does, which incurs 10-40 nanosecond cache-coherency traffic. Generally, the lazySet only makes sure writes that happened before are not reordered after the lazy write; which is generally enough in a SPSC value transmission case.

Copy link
Member

Choose a reason for hiding this comment

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

Why is eventually visible safe here? It doesn't seem to be.

Copy link
Member Author

Choose a reason for hiding this comment

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

My main guide was a blog you recommended:
http://psy-lob-saw.blogspot.co.uk/2012/12/atomiclazyset-is-performance-win-for.html

If you wish, I can eliminate all lazySet calls so there won't be any visibility concerns.

Copy link
Member

Choose a reason for hiding this comment

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

I'm trying to understand when it's safe. I get the use case for setting something null in cleanup, I'm more concerned in places where we set it and need to read it without any further writes guaranteed to happen before.

@benjchristensen
Copy link
Member

What do you think needs to be changed before merging? Do any of the lazySet uses concern you after reviewing them again?

@benjchristensen
Copy link
Member

Ah I see you just reverted the use of lazySet. I think that's a good step for now until we can prove those better, but I think it's worth us looking at those more going forward, particularly in hot code paths.

@cloudbees-pull-request-builder

RxJava-pull-requests #1154 FAILURE
Looks like there's a problem with this pull request

@akarnokd
Copy link
Member Author

Let's be on the safe side for now; the fact that it works on x86 doesn't mean it works properly on other platforms.

@benjchristensen
Copy link
Member

Hmm, we need to figure out that clojure test failure. @daveray Can you help us understand what's going on? It's not obvious why anything this PR changes should affect a single test in Clojure code.

@akarnokd
Copy link
Member Author

What I could understand is that the chunk_test.clj creates an Observable which invokes onNext after a random delay. It seems this observable emits onCompleted several times. The reason this fails now because merge() is changed to match the other mergeXYZ behavior by counting down a wip in both the outer and inner subscribers. For normal behaving sources, it makes sure the last one to reach wip = 0 will call onCompleted on the actual. The previous merge() didn't do this; it set a completed flag and checked for wip = 0; I suspect this oddity came from this problematic test and its misbehaving observable.

@akarnokd
Copy link
Member Author

I can revert the merge() behavior to make that test work again and allow merging this PR, but we need to fix that test and have merge() implement the correct onCompleted behavior.

@cloudbees-pull-request-builder

RxJava-pull-requests #1155 SUCCESS
This pull request looks good

@benjchristensen
Copy link
Member

Thanks for reverting that change. Submit that as a separate request.

benjchristensen added a commit that referenced this pull request May 27, 2014
@benjchristensen benjchristensen merged commit 84b7030 into ReactiveX:master May 27, 2014
@akarnokd akarnokd deleted the AtomicReferencesToFieldUpdaters branch May 27, 2014 06:26
@benjchristensen benjchristensen mentioned this pull request Jun 1, 2014
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

5 participants