Improve the bundle and defer mechanism

Instead of always bundling when the queue is empty, only bundle once the
queue has become empty and then only if it has been become empty again.

The previous algorithm would also bundle and defer the last element
found in the queue. This is not the case now.
This commit is contained in:
Florian Schmaus 2015-02-22 10:44:22 +01:00
parent 8b0ccd7420
commit 90969e252a
2 changed files with 19 additions and 2 deletions

View File

@ -20,7 +20,7 @@ package org.jivesoftware.smack.tcp;
* This callback is used to get the current value of the period in which Smack does bundle and defer
* outgoing stanzas.
* <p>
* Smack will bundle and defer stanzas if the connection is authenticated, the send queue is empty
* Smack will bundle and defer stanzas if the connection is authenticated
* and if a bundle and defer callback is set, either via
* {@link XMPPTCPConnection#setDefaultBundleAndDeferCallback(BundleAndDeferCallback)} or
* {@link XMPPTCPConnection#setBundleandDeferCallback(BundleAndDeferCallback)}, and

View File

@ -1177,6 +1177,16 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
private volatile boolean instantShutdown;
/**
* True if some preconditions are given to start the bundle and defer mechanism.
* <p>
* This will likely get set to true right after the start of the writer thread, because
* {@link #nextStreamElement()} will check if {@link queue} is empty, which is probably the case, and then set
* this field to true.
* </p>
*/
private boolean shouldBundleAndDefer;
/**
* Initializes the writer in order to be used. It is called at the first connection and also
* is invoked if the connection is disconnected by an error.
@ -1262,6 +1272,10 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* @return the next element for writing or null.
*/
private Element nextStreamElement() {
// It is important the we check if the queue is empty before removing an element from it
if (queue.isEmpty()) {
shouldBundleAndDefer = true;
}
Element packet = null;
try {
packet = queue.take();
@ -1292,7 +1306,10 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
// If the preconditions are given (e.g. bundleAndDefer callback is set, queue is
// empty), then we could wait a bit for further stanzas attempting to decrease
// our energy consumption
if (localBundleAndDeferCallback != null && isAuthenticated() && queue.isEmpty()) {
if (localBundleAndDeferCallback != null && isAuthenticated() && shouldBundleAndDefer) {
// Reset shouldBundleAndDefer to false, nextStreamElement() will set it to true once the
// queue is empty again.
shouldBundleAndDefer = false;
final AtomicBoolean bundlingAndDeferringStopped = new AtomicBoolean();
final int bundleAndDeferMillis = localBundleAndDeferCallback.getBundleAndDeferMillis(new BundleAndDefer(
bundlingAndDeferringStopped));