aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-05 03:58:12 +0100
committertv <tv@krebsco.de>2026-11-05 03:58:12 +0100
commitf7ce22ed0ba4a758bdc7de0f21b6d0cb45a866b1 (patch)
tree7c35b83e5ae21bb6253c1f82bbed347667af31b9 /src/swarm
parenta02ed87abf6a0dc9d3f36bafcf333272586093aa (diff)
deflate blob chunks
Diffstat (limited to 'src/swarm')
-rw-r--r--src/swarm/stats.rs12
-rw-r--r--src/swarm/sync.rs37
2 files changed, 44 insertions, 5 deletions
diff --git a/src/swarm/stats.rs b/src/swarm/stats.rs
index ed91db0..6332901 100644
--- a/src/swarm/stats.rs
+++ b/src/swarm/stats.rs
@@ -133,6 +133,10 @@ pub(crate) struct Relay {
pub(crate) framed: u64,
pub(crate) framing_bytes: u64,
pub(crate) framing_id_bytes: u64,
+ /// Sync messages deflated (`compress`), their bytes before and after.
+ pub(crate) deflated: u64,
+ pub(crate) deflated_from: u64,
+ pub(crate) deflated_to: u64,
/// Sync messages received that carried changes, all of which we had already, and
/// their payload's bytes: changes that came twice. Of those, how many came along a
/// writer's tree (`SyncEnvelope::writer`), and how many were taken as delivered by
@@ -254,6 +258,14 @@ impl NodeStats {
self.lock().relay.tree_forwards += 1;
}
+ /// A sync message of `from` bytes went out deflated to `to`.
+ pub(crate) fn deflated(&self, from: usize, to: usize) {
+ let mut inner = self.lock();
+ inner.relay.deflated += 1;
+ inner.relay.deflated_from += from as u64;
+ inner.relay.deflated_to += to as u64;
+ }
+
/// A sync message went out whose envelope added `bytes` to its Automerge message,
/// `ids` of them the epoch.
pub(crate) fn sync_framing(&self, bytes: usize, ids: usize) {
diff --git a/src/swarm/sync.rs b/src/swarm/sync.rs
index 394e589..8190e5c 100644
--- a/src/swarm/sync.rs
+++ b/src/swarm/sync.rs
@@ -238,11 +238,27 @@ async fn deliver_sync_to_peer(state: &AppState, peer: &str) -> Result<()> {
let Some(body) = body else {
return (session, Ok(None));
};
+ // A large message deflated, if it shrinks (`compress`).
+ let body = match body {
+ transport::SyncBody::Message(payload) => {
+ match crate::compress::deflate(&payload.0) {
+ Some(deflated) => {
+ stats.deflated(payload.0.len(), deflated.len());
+ transport::SyncBody::Deflated(transport::SyncPayload(
+ deflated.into(),
+ ))
+ }
+ None => transport::SyncBody::Message(payload),
+ }
+ }
+ other => other,
+ };
// What the envelope adds to an Automerge message (`swarm::stats`), and of
// that, the epoch's tag (msgpack: 12 bytes, up to 20 for generations past
// 127).
let inner = match &body {
- transport::SyncBody::Message(payload) => Some(payload.0.len()),
+ transport::SyncBody::Message(payload)
+ | transport::SyncBody::Deflated(payload) => Some(payload.0.len()),
transport::SyncBody::Delta(_) => None,
};
let ids = rmp_serde::encode::to_vec(&transport::EpochTag::of(epoch))
@@ -418,8 +434,9 @@ pub(crate) async fn handle_sync(
let from_ready = envelope.ready;
let writer = envelope.writer;
let delivered = envelope.delivered;
- let payload = match envelope.body {
- transport::SyncBody::Message(payload) => payload,
+ let (payload, deflated) = match envelope.body {
+ transport::SyncBody::Message(payload) => (payload, false),
+ transport::SyncBody::Deflated(payload) => (payload, true),
transport::SyncBody::Delta(spec) => {
fetch_delta(state, peer, epoch, spec);
return Ok(());
@@ -430,7 +447,6 @@ pub(crate) async fn handle_sync(
warn!(peer = %peer, bytes = payload.0.len(), "Dropping a sync message larger than any sender should send");
return Ok(());
}
- state.stats.sync_received(payload.0.len());
let applied = {
let doc = Arc::clone(&state.doc);
@@ -458,8 +474,19 @@ pub(crate) async fn handle_sync(
(Vec<(String, Vec<crate::document::ChangeHash>)>, bool),
);
tokio::task::spawn_blocking(move || -> Result<Option<Applied>> {
- // Before the lock: decoding a large message takes a while.
+ // Before the lock: inflating and decoding a large message takes a while. No
+ // larger than any sender should send, deflated or not.
+ let message = if deflated {
+ transport::SyncPayload(
+ crate::compress::inflate(&message.0, crate::swarm::blob::MAX_SYNC_MESSAGE)
+ .context("Inflating a sync message")?
+ .into(),
+ )
+ } else {
+ message
+ };
let payload_len = message.0.len();
+ stats.sync_received(payload_len);
let message = crate::document::sync::decode(&message)?;
let carried = message.carries_changes();
let sizes = if carried { message.sizes() } else { (0, 0) };