Skip to main content

UploadSummary

Struct UploadSummary 

Source
pub struct UploadSummary {
    pub protocol: ProtocolVersion,
    pub ls_refs: usize,
    pub fetch_rounds: usize,
    pub objects_sent: u32,
    pub objects_selected: usize,
    pub common: usize,
    pub objects_copied_from_pack: usize,
    pub objects_recompressed: usize,
    pub answered_from_bitmap: bool,
    pub thin_bases_offered: usize,
    pub thin_bases_vetoed: usize,
    pub closure_bases_declined: usize,
}
Expand description

What a whole upload-pack session did.

Returned rather than logged because the SSH layer wants it for metrics and the interop tests want it as evidence: “the fetch succeeded” is true of a server that negotiated properly and of one that shipped the entire repository every time, and only fetch_rounds and objects_sent tell them apart.

Fields§

§protocol: ProtocolVersion

Which protocol was spoken.

§ls_refs: usize

How many ls-refs commands were served.

§fetch_rounds: usize

How many negotiation rounds the client took, the one that carried the packfile included.

§objects_sent: u32

Objects in the packfile, if one was sent.

This is what the ENGINE emitted, not what this end chose. See objects_selected for the other half; a reader that has only this one cannot tell the two apart.

§objects_selected: usize

Objects GitServe::select chose — the exact set emit_pack was handed.

§Why both counts, and why this one is asserted rather than logged

emit_pack’s first parameter is an exact set and the engine must not close it over reachability (DECIDED 2026-08-10). It may still emit more than it was given, legitimately: an OFS_DELTA names its base by a backwards distance inside the pack, so an engine copying stored entries has to bring along any delta base that fell outside the selection or emit something unparseable. Caps::thin is the allowance to skip that, and an engine is free not to take it.

So the gap is expected and unbounded, which is precisely why it has to be reported rather than assumed small. MEASURED on the laptop 2026-08-10, the h2h-linear-sha1-2048c-1024f-16k corpus over the znippy engine, a negotiated fetch from a receiver N commits behind the tip:

  N commits behind    selected    sent    amplification
                 1          18     157            8.72x
               256        4382    7801            1.78x

Until this field existed the left-hand column reached exactly one place — a human-readable sideband progress line that git fetch -q suppresses and no meter parses — so bench/’s gunnar.vs_git_push could report a 33.6% divergence with nothing anywhere able to attribute it. That is the failure a published number can hide: one describing a path other than the one its name claims.

Zero for a session that sent no packfile. Summed over rounds in v2, for the same reason objects_sent is.

§common: usize

How many haves turned out to be common on the final round.

§objects_copied_from_pack: usize

Of objects_sent, how many left as a copy of the pack entry they were already stored as.

Reported for the same reason fetch_rounds and objects_sent are: “the clone succeeded” is true of a server that shipped the client’s own deltas back and of one that inflated and re-deflated 528 MiB to send 18× the bytes, and nothing else on this struct tells them apart. A byte count cannot either, since it moves with the corpus.

§objects_recompressed: usize

Of objects_sent, how many had to be deflated from their decompressed content: everything, on a store with no packs, and on a packed one only the loose objects and the deltas whose base did not come along.

§answered_from_bitmap: bool

Whether the packfile round’s object selection came from a .bitmap rather than from the walk.

§Why this is on the summary and not only in a log line

Because the two paths do not produce identical bytes and every measurement of this server is therefore a measurement of one of them. The bitmap path vouches for the client’s whole closure (ClientHas::Bits) where Exclusion::Edges’ walk vouches only for the frontier, so a delta base the walk expands the bitmap names — same request, same repository, fewer bytes. Nothing else a server reports says which one answered, and the failure is silent in the direction that matters: a repository with no .bitmap on disk falls through to the walk and every number taken on it is a walk number wearing the default’s name.

MEASURED 2026-08-04: the head-to-head fetch arm’s server fixture is a git clone --bare carve, git clone writes no .bitmap, and so gunnar.vs_git_fetch_divergent — the one arm gunnar loses on bytes — had never once exercised the shipping path. false here is what says so.

false for a session that sent no packfile, and for a request shape [crate::bitmap::select] declines (a filter, a shallow boundary, a deepening).

§thin_bases_offered: usize

Thin-delta bases gix offered over the session, and how many client_has refused. See crate::pack::WriteOutcome::thin_bases_offered.

§thin_bases_vetoed: usize§closure_bases_declined: usize

See crate::pack::WriteOutcome::closure_bases_declined. Non-zero only on a clone out of a multi-pack store whose selection reaches one object by two routes, which is the shape no fixture in this tree had until 2026-08-05.

Trait Implementations§

Source§

impl Clone for UploadSummary

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for UploadSummary

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for UploadSummary

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Eq for UploadSummary

Source§

impl PartialEq for UploadSummary

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for UploadSummary

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more