Monorepo for Tangled tangled.org
6

Configure Feed

Select the types of activity you want to include in your feed.

at master 8.1 kB View raw
1use std::hint::black_box; 2 3use bobbin_types::edges::Record; 4use criterion::{Criterion, criterion_group, criterion_main}; 5use jacquard_common::DefaultStr; 6use jacquard_common::types::nsid::Nsid; 7use serde::Deserialize; 8use serde_json::value::RawValue; 9 10#[derive(Deserialize)] 11struct ValueFrame { 12 record: ValueRecordFrame, 13} 14 15#[derive(Deserialize)] 16struct ValueRecordFrame { 17 collection: Nsid<DefaultStr>, 18 #[serde(default)] 19 record: Option<serde_json::Value>, 20} 21 22#[derive(Deserialize)] 23struct BorrowedRawFrame<'a> { 24 #[serde(borrow)] 25 record: BorrowedRawRecordFrame<'a>, 26} 27 28#[derive(Deserialize)] 29struct BorrowedRawRecordFrame<'a> { 30 collection: Nsid<DefaultStr>, 31 #[serde(borrow, default)] 32 record: Option<&'a RawValue>, 33} 34 35#[derive(Deserialize)] 36struct OwnedRawFrame { 37 record: OwnedRawRecordFrame, 38} 39 40#[derive(Deserialize)] 41struct OwnedRawRecordFrame { 42 collection: Nsid<DefaultStr>, 43 #[serde(default)] 44 record: Option<Box<RawValue>>, 45} 46 47fn current_path(text: &str) -> Record { 48 let frame: ValueFrame = serde_json::from_str(text).expect("frame"); 49 let value = frame.record.record.expect("upsert body"); 50 let bytes = serde_json::to_vec(&value).expect("re-serialize Value"); 51 Record::from_json_bytes(&frame.record.collection, &bytes).expect("decode record") 52} 53 54fn raw_value_borrowed(text: &str) -> Record { 55 let frame: BorrowedRawFrame<'_> = serde_json::from_str(text).expect("frame"); 56 let raw = frame.record.record.expect("upsert body"); 57 Record::from_json_bytes(&frame.record.collection, raw.get().as_bytes()).expect("decode record") 58} 59 60fn raw_value_owned(text: &str) -> Record { 61 let frame: OwnedRawFrame = serde_json::from_str(text).expect("frame"); 62 let raw = frame.record.record.expect("upsert body"); 63 Record::from_json_bytes(&frame.record.collection, raw.get().as_bytes()).expect("decode record") 64} 65 66fn floor_record_only(collection: &Nsid<DefaultStr>, record_bytes: &[u8]) -> Record { 67 Record::from_json_bytes(collection, record_bytes).expect("decode record") 68} 69 70fn star_text() -> &'static str { 71 r#"{ 72 "id": 1, 73 "type": "record", 74 "record": { 75 "live": false, 76 "did": "did:plc:olaren", 77 "rev": "3lq2zk5wqsh2k", 78 "collection": "sh.tangled.feed.star", 79 "rkey": "abcabcabcabcz", 80 "action": "create", 81 "record": { 82 "$type": "sh.tangled.feed.star", 83 "createdAt": "2026-05-01T00:00:00Z", 84 "subject": { 85 "$type": "sh.tangled.feed.star#repo", 86 "did": "did:plc:limpet" 87 } 88 } 89 } 90 }"# 91} 92 93fn repo_text() -> &'static str { 94 r#"{ 95 "id": 2, 96 "type": "record", 97 "record": { 98 "live": false, 99 "did": "did:plc:nel", 100 "rev": "3lq2zk5wqsh2l", 101 "collection": "sh.tangled.repo", 102 "rkey": "3lq2zk5wq0001", 103 "action": "create", 104 "record": { 105 "$type": "sh.tangled.repo", 106 "createdAt": "2026-05-01T00:00:00Z", 107 "knot": "knot.witchcraft.systems", 108 "name": "limpet", 109 "description": "demonstration repository for the bench corpus", 110 "owner": "did:plc:nel", 111 "repoDid": "did:plc:limpet", 112 "labels": [ 113 "at://did:plc:periwinkle/sh.tangled.label.definition/3lq2zk5wq0010", 114 "at://did:plc:periwinkle/sh.tangled.label.definition/3lq2zk5wq0011" 115 ] 116 } 117 } 118 }"# 119} 120 121fn issue_text() -> &'static str { 122 r#"{ 123 "id": 3, 124 "type": "record", 125 "record": { 126 "live": false, 127 "did": "did:plc:teq", 128 "rev": "3lq2zk5wqsh2m", 129 "collection": "sh.tangled.repo.issue", 130 "rkey": "3lq2zk5wq0100", 131 "action": "create", 132 "record": { 133 "$type": "sh.tangled.repo.issue", 134 "createdAt": "2026-05-01T00:00:00Z", 135 "title": "ingest: single-pass JSON decode follow-up corpus entry", 136 "body": "Long body to give the bench a realistic decode cost. Repeats: blahhhhh meow meow aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 137 "repo": "did:plc:limpet", 138 "mentions": [ 139 "did:plc:nel", 140 "did:plc:olaren", 141 "did:plc:bailey" 142 ], 143 "references": [ 144 "at://did:plc:limpet/sh.tangled.repo.issue/3lq2zk5wq0099", 145 "at://did:plc:limpet/sh.tangled.repo.pull/3lq2zk5wq0098" 146 ] 147 } 148 } 149 }"# 150} 151 152fn pull_comment_text() -> &'static str { 153 r#"{ 154 "id": 4, 155 "type": "record", 156 "record": { 157 "live": false, 158 "did": "did:plc:lyna", 159 "rev": "3lq2zk5wqsh2n", 160 "collection": "sh.tangled.feed.comment", 161 "rkey": "3lq2zk5wq0200", 162 "action": "create", 163 "record": { 164 "$type": "sh.tangled.feed.comment", 165 "createdAt": "2026-05-01T00:00:00Z", 166 "body": { 167 "$type": "sh.tangled.markup.markdown", 168 "text": "lgtm i thinks!!!! but please verify the cursor invariant under buffered(N) before landing. :3" 169 }, 170 "subject": { 171 "uri": "at://did:plc:limpet/sh.tangled.repo.pull/3lq2zk5wq0098", 172 "cid": "bafkqaaa" 173 }, 174 "pullRoundIdx": 0 175 } 176 } 177 }"# 178} 179 180fn follow_text() -> &'static str { 181 r#"{ 182 "id": 5, 183 "type": "record", 184 "record": { 185 "live": false, 186 "did": "did:plc:bailey", 187 "rev": "3lq2zk5wqsh2o", 188 "collection": "sh.tangled.graph.follow", 189 "rkey": "3lq2zk5wq0300", 190 "action": "create", 191 "record": { 192 "$type": "sh.tangled.graph.follow", 193 "createdAt": "2026-05-01T00:00:00Z", 194 "subject": "did:plc:nel" 195 } 196 } 197 }"# 198} 199 200fn extract_record_slice(text: &str) -> (Nsid<DefaultStr>, Vec<u8>) { 201 let frame: ValueFrame = serde_json::from_str(text).expect("frame"); 202 let value = frame.record.record.expect("upsert body"); 203 let bytes = serde_json::to_vec(&value).expect("re-serialize Value"); 204 (frame.record.collection, bytes) 205} 206 207fn bench_decode(c: &mut Criterion) { 208 let corpus: &[(&str, &str)] = &[ 209 ("star", star_text()), 210 ("repo", repo_text()), 211 ("issue", issue_text()), 212 ("pull_comment", pull_comment_text()), 213 ("follow", follow_text()), 214 ]; 215 for (name, text) in corpus { 216 let mut group = c.benchmark_group(format!("decode/{name}")); 217 let (collection, record_bytes) = extract_record_slice(text); 218 219 group.bench_function("current_path", |b| { 220 b.iter(|| { 221 let r = current_path(black_box(text)); 222 black_box(r); 223 }); 224 }); 225 226 group.bench_function("raw_value_borrowed", |b| { 227 b.iter(|| { 228 let r = raw_value_borrowed(black_box(text)); 229 black_box(r); 230 }); 231 }); 232 233 group.bench_function("raw_value_owned", |b| { 234 b.iter(|| { 235 let r = raw_value_owned(black_box(text)); 236 black_box(r); 237 }); 238 }); 239 240 group.bench_function("floor_record_only", |b| { 241 let bytes = record_bytes.as_slice(); 242 b.iter(|| { 243 let r = floor_record_only(black_box(&collection), black_box(bytes)); 244 black_box(r); 245 }); 246 }); 247 248 group.finish(); 249 } 250} 251 252criterion_group!(benches, bench_decode); 253criterion_main!(benches);