Commit 93be57b9 authored by Michael de Hoog's avatar Michael de Hoog

Rename TargetSizeCompressor to RatioCompressor, and add some comments

parent 4ccdbf0a
...@@ -106,7 +106,7 @@ func (cc *ChannelConfig) NewCompressor() (derive.Compressor, error) { ...@@ -106,7 +106,7 @@ func (cc *ChannelConfig) NewCompressor() (derive.Compressor, error) {
cc.TargetNumFrames, cc.TargetNumFrames,
) )
default: default:
return NewTargetSizeCompressor( return NewRatioCompressor(
cc.TargetFrameSize, cc.TargetFrameSize,
cc.TargetNumFrames, cc.TargetNumFrames,
cc.ApproxComprRatio, cc.ApproxComprRatio,
......
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup/derive" "github.com/ethereum-optimism/optimism/op-node/rollup/derive"
) )
type TargetSizeCompressor struct { type RatioCompressor struct {
// The frame size to target when creating channel frames. Note that if the // The frame size to target when creating channel frames. Note that if the
// realized compression ratio is worse than the approximate, more frames may // realized compression ratio is worse than the approximate, more frames may
// actually be created. This also depends on how close TargetFrameSize is to // actually be created. This also depends on how close TargetFrameSize is to
...@@ -27,8 +27,13 @@ type TargetSizeCompressor struct { ...@@ -27,8 +27,13 @@ type TargetSizeCompressor struct {
compress *zlib.Writer compress *zlib.Writer
} }
func NewTargetSizeCompressor(targetFrameSize uint64, targetNumFrames int, approxCompRatio float64) (derive.Compressor, error) { // NewRatioCompressor creates a new derive.Compressor implementation that uses the target
c := &TargetSizeCompressor{ // size and a compression ratio parameter to determine how much data can be written to
// the compressor before it's considered full. The full calculation is as follows:
//
// full = uncompressedLength * approxCompRatio >= targetFrameSize * targetNumFrames
func NewRatioCompressor(targetFrameSize uint64, targetNumFrames int, approxCompRatio float64) (derive.Compressor, error) {
c := &RatioCompressor{
TargetFrameSize: targetFrameSize, TargetFrameSize: targetFrameSize,
TargetNumFrames: targetNumFrames, TargetNumFrames: targetNumFrames,
ApproxComprRatio: approxCompRatio, ApproxComprRatio: approxCompRatio,
...@@ -43,7 +48,7 @@ func NewTargetSizeCompressor(targetFrameSize uint64, targetNumFrames int, approx ...@@ -43,7 +48,7 @@ func NewTargetSizeCompressor(targetFrameSize uint64, targetNumFrames int, approx
return c, nil return c, nil
} }
func (t *TargetSizeCompressor) Write(p []byte) (int, error) { func (t *RatioCompressor) Write(p []byte) (int, error) {
if err := t.FullErr(); err != nil { if err := t.FullErr(); err != nil {
return 0, err return 0, err
} }
...@@ -51,29 +56,29 @@ func (t *TargetSizeCompressor) Write(p []byte) (int, error) { ...@@ -51,29 +56,29 @@ func (t *TargetSizeCompressor) Write(p []byte) (int, error) {
return t.compress.Write(p) return t.compress.Write(p)
} }
func (t *TargetSizeCompressor) Close() error { func (t *RatioCompressor) Close() error {
return t.compress.Close() return t.compress.Close()
} }
func (t *TargetSizeCompressor) Read(p []byte) (int, error) { func (t *RatioCompressor) Read(p []byte) (int, error) {
return t.buf.Read(p) return t.buf.Read(p)
} }
func (t *TargetSizeCompressor) Reset() { func (t *RatioCompressor) Reset() {
t.buf.Reset() t.buf.Reset()
t.compress.Reset(&t.buf) t.compress.Reset(&t.buf)
t.inputBytes = 0 t.inputBytes = 0
} }
func (t *TargetSizeCompressor) Len() int { func (t *RatioCompressor) Len() int {
return t.buf.Len() return t.buf.Len()
} }
func (t *TargetSizeCompressor) Flush() error { func (t *RatioCompressor) Flush() error {
return t.compress.Flush() return t.compress.Flush()
} }
func (t *TargetSizeCompressor) FullErr() error { func (t *RatioCompressor) FullErr() error {
if t.inputTargetReached() { if t.inputTargetReached() {
return derive.CompressorFullErr return derive.CompressorFullErr
} }
...@@ -82,12 +87,12 @@ func (t *TargetSizeCompressor) FullErr() error { ...@@ -82,12 +87,12 @@ func (t *TargetSizeCompressor) FullErr() error {
// InputThreshold calculates the input data threshold in bytes from the given // InputThreshold calculates the input data threshold in bytes from the given
// parameters. // parameters.
func (t *TargetSizeCompressor) InputThreshold() uint64 { func (t *RatioCompressor) InputThreshold() uint64 {
return uint64(float64(t.TargetNumFrames) * float64(t.TargetFrameSize) / t.ApproxComprRatio) return uint64(float64(t.TargetNumFrames) * float64(t.TargetFrameSize) / t.ApproxComprRatio)
} }
// inputTargetReached says whether the target amount of input data has been // inputTargetReached says whether the target amount of input data has been
// reached in this channel builder. No more blocks can be added afterwards. // reached in this channel builder. No more blocks can be added afterwards.
func (t *TargetSizeCompressor) inputTargetReached() bool { func (t *RatioCompressor) inputTargetReached() bool {
return uint64(t.inputBytes) >= t.InputThreshold() return uint64(t.inputBytes) >= t.InputThreshold()
} }
...@@ -123,11 +123,11 @@ func TestInputThreshold(t *testing.T) { ...@@ -123,11 +123,11 @@ func TestInputThreshold(t *testing.T) {
TargetFrameSize: tt.input.TargetFrameSize, TargetFrameSize: tt.input.TargetFrameSize,
TargetNumFrames: tt.input.TargetNumFrames, TargetNumFrames: tt.input.TargetNumFrames,
ApproxComprRatio: tt.input.ApproxComprRatio, ApproxComprRatio: tt.input.ApproxComprRatio,
CompressorKind: flags.CompressorTarget, CompressorKind: flags.RatioCompressorKind,
} }
comp, err := config.NewCompressor() comp, err := config.NewCompressor()
require.NoError(t, err) require.NoError(t, err)
got := comp.(*batcher.TargetSizeCompressor).InputThreshold() got := comp.(*batcher.RatioCompressor).InputThreshold()
tt.assertion(got) tt.assertion(got)
} }
} }
...@@ -26,6 +26,13 @@ type ShadowCompressor struct { ...@@ -26,6 +26,13 @@ type ShadowCompressor struct {
fullErr error fullErr error
} }
// NewShadowCompressor creates a new derive.Compressor implementation that contains two
// compression buffers: one used for size estimation, and one used for the final
// compressed output. The first is flushed on every write, the second isn't, which means
// the final compressed data is always slightly smaller than the target. There is one
// exception to this rule: the first write to the buffer is not checked against the
// target, which allows individual blocks larger than the target to be included (and will
// be split across multiple channel frames).
func NewShadowCompressor(targetFrameSize uint64, targetNumFrames int) (derive.Compressor, error) { func NewShadowCompressor(targetFrameSize uint64, targetNumFrames int) (derive.Compressor, error) {
c := &ShadowCompressor{ c := &ShadowCompressor{
TargetFrameSize: targetFrameSize, TargetFrameSize: targetFrameSize,
......
...@@ -92,7 +92,7 @@ var ( ...@@ -92,7 +92,7 @@ var (
flags.EnumString[CompressorKind](CompressorKinds), flags.EnumString[CompressorKind](CompressorKinds),
EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "COMPRESSOR"), EnvVar: opservice.PrefixEnvVar(EnvVarPrefix, "COMPRESSOR"),
Value: func() *CompressorKind { Value: func() *CompressorKind {
out := CompressorTarget out := RatioCompressorKind
return &out return &out
}(), }(),
} }
...@@ -152,13 +152,17 @@ func CheckRequired(ctx *cli.Context) error { ...@@ -152,13 +152,17 @@ func CheckRequired(ctx *cli.Context) error {
type CompressorKind string type CompressorKind string
const ( const (
CompressorTarget CompressorKind = "target" // The RatioCompressorKind kind selects the batcher.RatioCompressor (see
CompressorShadow CompressorKind = "shadow" // batcher.NewRatioCompressor for a description).
RatioCompressorKind CompressorKind = "ratio"
// The ShadowCompressorKind kind selects the batcher.ShadowCompressor (see
// batcher.NewShadowCompressor for a description).
ShadowCompressorKind CompressorKind = "shadow"
) )
var CompressorKinds = []CompressorKind{ var CompressorKinds = []CompressorKind{
CompressorTarget, RatioCompressorKind,
CompressorShadow, ShadowCompressorKind,
} }
func (kind CompressorKind) String() string { func (kind CompressorKind) String() string {
......
...@@ -134,7 +134,7 @@ func (s *L2Batcher) Buffer(t Testing) error { ...@@ -134,7 +134,7 @@ func (s *L2Batcher) Buffer(t Testing) error {
if s.l2BatcherCfg.GarbageCfg != nil { if s.l2BatcherCfg.GarbageCfg != nil {
ch, err = NewGarbageChannelOut(s.l2BatcherCfg.GarbageCfg) ch, err = NewGarbageChannelOut(s.l2BatcherCfg.GarbageCfg)
} else { } else {
c, e := batcher.NewTargetSizeCompressor(s.l2BatcherCfg.MaxL1TxSize, 1, 1) c, e := batcher.NewRatioCompressor(s.l2BatcherCfg.MaxL1TxSize, 1, 1)
require.NoError(t, e, "failed to create compressor") require.NoError(t, e, "failed to create compressor")
ch, err = derive.NewChannelOut(c) ch, err = derive.NewChannelOut(c)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment