anthropics / anthropics/buffa

default_value_ref allocates a DynamicMessage and clones the pool Arc on every get() of an unset message field

オープン
#435 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Rust
スター
883
フォーク
88
平均マージ
3日 19時間
マージ済み PR(30日)
42

説明

`default_value_ref` in `buffa-descriptor/src/reflect/dynamic.rs` answers `get()` on an unset singular *message* field by building a value on every call:

```rust
FieldKind::Singular(SingularKind::Message(midx)) => ValueRef::Message(ReflectCow::Owned(
alloc::boxed::Box::new(DynamicMessage::new(Arc::clone(pool), midx)),
)),
```

so each read of an unset message-typed field costs a heap allocation, an `Arc` clone of the pool (an atomic RMW on a line shared across threads — see the companion issue on the pool's count line), and the matching drop, where the list and map arms of the same function hand out `'static` empties for free. A reflective reader that probes optional sub-messages (`has`-then-`get` patterns, or readers that treat unset as the empty message per proto3 semantics) pays this per field per message per request.

Options that keep `get()`'s signature:

- Cache one empty `DynamicMessage` per `MessageIndex` in the pool (built lazily, e.g. a `OnceLock>` slot per message, or a side `Vec` filled at pool build) and return `ValueRef::Message(ReflectCow::Borrowed(&empty))`. The empty message's own `pool` field is the one wrinkle — an empty message never dereferences it for field storage, so it could hold a `Weak` or the pool could store the empties without a back-reference; whichever fits the existing invariants.
- Or return a dedicated `ValueRef::EmptyMessage(MessageIndex)`-style variant and let `ReflectMessage` consumers treat it as the default instance, avoiding the self-referential question altogether at the cost of a new variant.

The first keeps every caller working unchanged.

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。