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(rumqttc): Replace Vec with FixedBitSet for QoS 2 packet trac… #869

Merged
merged 4 commits into from
May 22, 2024

Conversation

hippalus
Copy link
Contributor

@hippalus hippalus commented May 21, 2024

…king.(#868)

Type of change

  • Refactor (code improvements and optimizations)
  • Replaced Vec<Option<u16>> with FixedBitSet for outgoing_rel and incoming_pub.
  • Updated methods to accommodate the new data structure, including clean, handle_incoming_pubrec, handle_incoming_pubrel, and others.
  • Updated unit tests to ensure correct functionality with the new data structure.
    refactor(mqtt_state): Replace Vec with FixedBitSet for QoS 2 packet tracking (rumqttc: Reduce memory usage of MqttState #868)

Refactored the MqttState struct to use FixedBitSet instead of Vec<Option<u16>> for the outgoing_rel and incoming_pub fields. This change optimizes memory usage and improves performance for tracking packet identifiers in QoS 2 operations.

Before
Screenshot 2024-05-06 at 15 14 22

After
Screenshot 2024-05-21 at 17 07 01

Checklist:

  • Formatted with cargo fmt
  • Make an entry to CHANGELOG.md if it's relevant to the users of the library. If it's not relevant mention why.

Copy link
Member

@de-sh de-sh left a comment

Choose a reason for hiding this comment

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

Thanks for the PR, these are some really good changes, would appreciate if you could undo the unrelated ones and apply similar updates to v5/state.rs. Please update CHANGELOG.md as well.

@@ -1,7 +1,8 @@
use crate::{Event, Incoming, Outgoing, Request};

use crate::mqttbytes::v4::*;
use crate::mqttbytes::{self, *};
use crate::mqttbytes::*;
Copy link
Member

Choose a reason for hiding this comment

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

This change seems to be unrelated to the core of this PR

@@ -28,7 +29,7 @@ pub enum StateError {
#[error("A Subscribe packet must contain atleast one filter")]
EmptySubscription,
#[error("Mqtt serialization/deserialization error: {0}")]
Deserialization(#[from] mqttbytes::Error),
Deserialization(#[from] Error),
Copy link
Member

Choose a reason for hiding this comment

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

same as above

Copy link
Member

Choose a reason for hiding this comment

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

We have placed things this way to make it clear where that particular error is trickling down from.

@coveralls
Copy link

coveralls commented May 22, 2024

Pull Request Test Coverage Report for Build 9192788128

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 26 of 35 (74.29%) changed or added relevant lines in 2 files are covered.
  • 97 unchanged lines in 4 files lost coverage.
  • Overall coverage decreased (-0.07%) to 36.133%

Changes Missing Coverage Covered Lines Changed/Added Lines %
rumqttc/src/state.rs 15 18 83.33%
rumqttc/src/v5/state.rs 11 17 64.71%
Files with Coverage Reduction New Missed Lines %
rumqttc/src/state.rs 3 78.37%
rumqttc/src/v5/state.rs 5 67.09%
rumqttc/src/eventloop.rs 29 83.85%
rumqttc/src/v5/eventloop.rs 60 8.65%
Totals Coverage Status
Change from base Build 9170133164: -0.07%
Covered Lines: 5975
Relevant Lines: 16536

💛 - Coveralls

Copy link
Member

@de-sh de-sh left a comment

Choose a reason for hiding this comment

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

LGTM
Great first PR @hippalus! 🎊

edit: sorry, forgot to mention that we need an update to the rumqttc/CHANGELOG.md file, e.g.

* Use `FixedBitSet` instead of `Vec<Option<u16>>` to improve memory utilization.

@de-sh de-sh merged commit 005c60e into bytebeamio:main May 22, 2024
2 of 3 checks passed
@Arend-Jan
Copy link
Contributor

now that is what I call an improvement. Thanks @hippalus 🙏

@xiaocq2001
Copy link
Contributor

xiaocq2001 commented May 27, 2024

@hippalus

Reduce the pkid to fixed bit seems work, but it assumes the pkids from host is within 1 to max inflight. It seems in MQTT spec there is no rule to limit packet identifiers in this way.
I think there could be issue to handle if a broker sending randomized or very large pkids, or scattered pkids, e.g., the bit to pkid value issue, the pkid actual ordering issue.

@de-sh
Copy link
Member

de-sh commented May 27, 2024

I think there could be issue to handle if a broker sending randomized or very large pkids, or scattered pkids, e.g., the bit to pkid value issue, the pkid actual ordering issue.

Is this with regards to v4/5?

@swanandx
Copy link
Member

Is this with regards to v4/5?

both. I think what @xiaocq2001 wants to say is let's say we have max inflight set to 100, but nothing is stopping broker from using 200 as pkid right?

so now when we get incoming pub with pkid 200, we will try to insert it and crash! please correct me if wrong.

btw, if this is the issue, then i think it was still there before this PR.

@hippalus
Copy link
Contributor Author

Thank you, @xiaocq2001, @de-sh, and @swanandx, for the feedback.

You are correct about the potential issue with pkids beyond the assumed range. As @swanandx mentioned, the previous implementation depended on a limited range.

To address this, I've updated the implementation locally to use FixedBitSet::with_capacity(u16::MAX as usize + 1) for both outgoing_rel and incoming_pub. This ensures we handle the full range of pkids (1 to 65536) as per the MQTT spec. All test cases now pass with this change, with just an 8 KB memory increase.

It would be nice to add resiliency tests for handling large, randomized, or out-of-order pkids from the broker.

@xiaocq2001
Copy link
Contributor

xiaocq2001 commented May 28, 2024

There is another issue, while re-sending the PUBREL packets, as described in MQTTv5 spec, "The Client MUST send PUBREC packets in the order in which the corresponding PUBLISH packets were received (QoS 2 messages) [MQTT-4.6.0-3]", this means if a connection is resumed the previous order of outgoing PUBREL must be restored, but FixedBitSet of outgoing_ref does not support ordering other than continuous and increasing pkid.

E.g., if broker sending publish packets with pkids 4,3,2,1 the expected outgoing_ref should be 4,3,2,1, but currently if it's disconnected and reconnected before the outgoing_ref sent, the resumed packet ordering is 1,2,3,4 which is not expected.

Another consideration is, for outgoing PUBLISH and PUBREL packets, they may need more information for status notification (#805), in such cases we must use larger structs instead of just one bit for each packet.

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.

6 participants