diff options
| author | Ophestra <cat@gensokyo.uk> | 2026-05-11 19:44:28 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2026-05-12 00:19:42 +0900 |
| commit | 6e113b88364ade12b26c9f01c43608841b9378df (patch) | |
| tree | 28386b65784d7b50f976e3c3f2634dc007f1661f /internal/pkg/ir.go | |
| parent | ce9f4b5f713b2ff2a03adefe83175d75d16ef24f (diff) | |
internal/pkg: content-based dependency substitution
This change introduces a new fast path for FloodArtifact. It is taken when a curing artifact has identical-by-content controlled relevant inputs and are otherwise identical to an already-cured artifact.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/pkg/ir.go')
| -rw-r--r-- | internal/pkg/ir.go | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/internal/pkg/ir.go b/internal/pkg/ir.go index c93abc9e..72a2c90c 100644 --- a/internal/pkg/ir.go +++ b/internal/pkg/ir.go @@ -76,6 +76,9 @@ type IContext struct { // Written to by various methods, should be zeroed after [Artifact.Params] // returns and must not be exposed directly. w io.Writer + // Optional [Artifact] to cureRes cache, replaces [IRKindIdent] with + // checksum values if non-nil. + inputs map[Artifact]cureRes } // irZero is a zero IR word. @@ -163,7 +166,15 @@ func (i *IContext) WriteIdent(a Artifact) { defer i.ic.putIdentBuf(buf) IRKindIdent.encodeHeader(0).put(buf[:]) - *(*ID)(buf[wordSize:]) = i.ic.Ident(a).Value() + if i.inputs != nil { + res, ok := i.inputs[a] + if !ok { + panic(InvalidLookupError(i.ic.Ident(a).Value())) + } + *(*ID)(buf[wordSize:]) = res.checksum.Value() + } else { + *(*ID)(buf[wordSize:]) = i.ic.Ident(a).Value() + } i.mustWrite(buf[:]) } @@ -207,19 +218,44 @@ func (i *IContext) WriteString(s string) { // Encode writes a deterministic, efficient representation of a to w and returns // the first non-nil error encountered while writing to w. func (ic *irCache) Encode(w io.Writer, a Artifact) (err error) { + return ic.encode(w, a, nil) +} + +// encode implements Encode but replaces identifiers with their cured checksums +// for a non-nil ident. Caller must acquire Cache.identMu. +func (ic *irCache) encode( + w io.Writer, + a Artifact, + inputs map[Artifact]cureRes, +) (err error) { deps := a.Dependencies() idents := make([]*extIdent, len(deps)) - for i, d := range deps { - dbuf, did := ic.unsafeIdent(d, true) - if dbuf == nil { - dbuf = ic.getIdentBuf() + if inputs == nil { + for i, d := range deps { + dbuf, did := ic.unsafeIdent(d, true) + if dbuf == nil { + dbuf = ic.getIdentBuf() + binary.LittleEndian.PutUint64(dbuf[:], uint64(d.Kind())) + *(*ID)(dbuf[wordSize:]) = did.Value() + } else { + ic.storeIdent(d, dbuf) + } + defer ic.putIdentBuf(dbuf) + idents[i] = dbuf + } + } else { + for i, d := range deps { + res, ok := inputs[d] + if !ok { + return InvalidLookupError(ic.Ident(d).Value()) + } + + dbuf := ic.getIdentBuf() binary.LittleEndian.PutUint64(dbuf[:], uint64(d.Kind())) - *(*ID)(dbuf[wordSize:]) = did.Value() - } else { - ic.storeIdent(d, dbuf) + *(*ID)(dbuf[wordSize:]) = res.checksum.Value() + defer ic.putIdentBuf(dbuf) + idents[i] = dbuf } - defer ic.putIdentBuf(dbuf) - idents[i] = dbuf } slices.SortFunc(idents, func(a, b *extIdent) int { return bytes.Compare(a[:], b[:]) @@ -244,7 +280,7 @@ func (ic *irCache) Encode(w io.Writer, a Artifact) (err error) { } func() { - i := IContext{ic, w} + i := IContext{ic, w, inputs} defer panicToError(&err) defer func() { i.ic, i.w = nil, nil }() |
