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

Added BlockingQueue implementation based on JCtools #1682

Merged
merged 7 commits into from
Nov 14, 2018

Conversation

merlimat
Copy link
Contributor

Motivation

Add a BlockingQueue implementation that is suitable for low latency and low contention.

Key points:

  • Optimized for multiple producers and single consumer
  • When waiting for entries, the thread is blocked with busy wait to avoid context switch.

(This will be used in subsequent PRs to optionally enable it)

@merlimat merlimat added this to the 4.9.0 milestone Sep 17, 2018
@merlimat merlimat self-assigned this Sep 17, 2018
@jvrao
Copy link
Contributor

jvrao commented Sep 17, 2018

@merlimat any perf/measurements that you can share?

@dlg99
Copy link
Contributor

dlg99 commented Sep 18, 2018

I am curious why you decided to implement blocking queue on top of JCtools' MPSC vs using disruptor that implements it.
https://github.com/conversant/disruptor
https://github.com/conversant/disruptor/blob/master/src/test/java/com/conversantmedia/util/concurrent/DisruptorBlockingQueueTest.java

I do not have experience or stake in using either of those, but conversant claims to be faster and it already has blocking queue API.

@eolivelli
Copy link
Contributor

Same curiosity from me. Even Netty has its own MCSP queue

Copy link
Contributor

@eolivelli eolivelli left a comment

Choose a reason for hiding this comment

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

Looks good to me +1

@sijie
Copy link
Member

sijie commented Sep 21, 2018

@merlimat can you answer the questions why we are choosing JCtools queues?

@ivankelly
Copy link
Contributor

@sijie @merlimat I suspect JCtools was chosen because this code was written before everyone jumped on the lock-free bandwagon ;)

@merlimat
Copy link
Contributor Author

merlimat commented Nov 8, 2018

@merlimat any perf/measurements that you can share?

@jvrao
Not isolated to this implementation. It's tricky to properly microbenchmark a concurrency queue.

This really brings 2 benefits:

  • Avoiding contention on the enqueuing threads (eg: IO threads passing items to journal, or submitting tasks the OrderedSafeExecutor)
  • Combined with a busy-poll strategy, it will avoid the latency penalty of context switch almost completely since the receiving thread will not "sleep" or wait for a new item in the queue, but it will be actively polling and never descheduled (this when also combining with CpuAffinity, see Added module to enable CPU affinity #1641).

Some test results were shared here: netty/netty#8267 (comment) . Though this was including Pulsar in the mix, on top of BK, with same kind of optimizations applied.

I am curious why you decided to implement blocking queue on top of JCtools' MPSC vs using disruptor that implements it.

@dlg99 @eolivelli I was not aware of conversant library. I was looking at Lmax disruptor but it forces to change all your code to fit into its model of dedicating a thread to it. I wanted to have a regular blocking queue so that this can also be directly plugged into the OrderedSafeExecutor (or any JDK executor), so that existing code doesn't have to be modified.

JCTool seems to be well maintained, the concurrency code is very scrupulously reviewed and is being used in several high profile projects, from Netty, Cassandra, Log4j, etc.

Same curiosity from me. Even Netty has its own MCSP queue

Netty is actually importing JCTools queue :)

@merlimat
Copy link
Contributor Author

merlimat commented Nov 8, 2018

run integration tests
run bookkeeper-server replication tests

@eolivelli
Copy link
Contributor

Yes I noticed that Netty has its own copy of jctools queue.

I am fine with this idea.
Thank you for working on this topic

Copy link
Contributor

@eolivelli eolivelli left a comment

Choose a reason for hiding this comment

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

I left two comments, please take a look.

Overall it looks good to me

handle = MethodHandles.lookup().findStatic(Thread.class, "onSpinWait", MethodType.methodType(void.class));
} catch (Throwable t) {
// Ignore
}
Copy link
Contributor

Choose a reason for hiding this comment

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

We should log this error, so that it is clear that we are not able to leverage this feature

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not strictly critical for performance, it's just a way to consume less CPU power.

Since it's not available in Java8, I'd rather keep this at debug level to avoid printing the warning every time (eg: even if busywait is not used).

@merlimat
Copy link
Contributor Author

merlimat commented Nov 9, 2018

run pr validation

1 similar comment
@merlimat
Copy link
Contributor Author

merlimat commented Nov 9, 2018

run pr validation

@merlimat
Copy link
Contributor Author

merlimat commented Nov 9, 2018

@eolivelli PTAL again

Copy link
Contributor

@eolivelli eolivelli left a comment

Choose a reason for hiding this comment

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

Very good

+1

@merlimat
Copy link
Contributor Author

@jvrao @dlg99 @sijie @ivankelly Are we good to merge this one?

@merlimat
Copy link
Contributor Author

run pr validation
run integrations tests

@jvrao
Copy link
Contributor

jvrao commented Nov 13, 2018

@dlg99 can you please review this? I wish we have some way to validate these perf changes. At lest to make sure it is not introducing perf regression. These changes are tricky - on paper they look like obvious win but in practice it is totally different picture. My comments are not specific to this change, but general category. @sijie

@merlimat
Copy link
Contributor Author

@jvrao all these changes are by default turned off

Copy link
Member

@sijie sijie left a comment

Choose a reason for hiding this comment

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

lgtm if it is not turned on by default.

@merlimat
Copy link
Contributor Author

run integration tests

1 similar comment
@merlimat
Copy link
Contributor Author

run integration tests

@merlimat
Copy link
Contributor Author

merlimat commented Nov 14, 2018

IGNORE IT CI

@merlimat
Copy link
Contributor Author

// Flaky TestCompatUpgrade integration test. Seen failing in other PRs as well

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