mirror of
https://github.com/kopia/kopia.git
synced 2026-05-19 04:04:56 -04:00
feat(ui): support for deprecation of certain algorithms (#2122)
Some compression algorithms are not recommended because they allocate disproportionate amounts of memory. They are still possible to use, just marked as NOT RECOMMENDED in the UI.
This commit is contained in:
@@ -26,6 +26,7 @@ type commandBenchmarkCompression struct {
|
|||||||
verifyStable bool
|
verifyStable bool
|
||||||
optionPrint bool
|
optionPrint bool
|
||||||
parallel int
|
parallel int
|
||||||
|
deprecated bool
|
||||||
|
|
||||||
out textOutput
|
out textOutput
|
||||||
}
|
}
|
||||||
@@ -39,6 +40,7 @@ func (c *commandBenchmarkCompression) setup(svc appServices, parent commandParen
|
|||||||
cmd.Flag("parallel", "Number of parallel goroutines").Default("1").IntVar(&c.parallel)
|
cmd.Flag("parallel", "Number of parallel goroutines").Default("1").IntVar(&c.parallel)
|
||||||
cmd.Flag("verify-stable", "Verify that compression is stable").BoolVar(&c.verifyStable)
|
cmd.Flag("verify-stable", "Verify that compression is stable").BoolVar(&c.verifyStable)
|
||||||
cmd.Flag("print-options", "Print out options usable for repository creation").BoolVar(&c.optionPrint)
|
cmd.Flag("print-options", "Print out options usable for repository creation").BoolVar(&c.optionPrint)
|
||||||
|
cmd.Flag("deprecated", "Included deprecated compression algorithms").BoolVar(&c.deprecated)
|
||||||
cmd.Action(svc.noRepositoryAction(c.run))
|
cmd.Action(svc.noRepositoryAction(c.run))
|
||||||
c.out.setup(svc)
|
c.out.setup(svc)
|
||||||
}
|
}
|
||||||
@@ -107,6 +109,10 @@ func (c *commandBenchmarkCompression) run(ctx context.Context) error {
|
|||||||
log(ctx).Infof("Repeating %v times per compression method (total %v). Override with --repeat=N.", repeatCount, units.BytesStringBase2(int64(repeatCount*len(data))))
|
log(ctx).Infof("Repeating %v times per compression method (total %v). Override with --repeat=N.", repeatCount, units.BytesStringBase2(int64(repeatCount*len(data))))
|
||||||
|
|
||||||
for name, comp := range compression.ByName {
|
for name, comp := range compression.ByName {
|
||||||
|
if compression.IsDeprecated[name] && !c.deprecated {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
log(ctx).Infof("Benchmarking compressor '%v'...", name)
|
log(ctx).Infof("Benchmarking compressor '%v'...", name)
|
||||||
|
|
||||||
cnt := repeatCount
|
cnt := repeatCount
|
||||||
@@ -197,13 +203,19 @@ func (c *commandBenchmarkCompression) printResults(results []compressionBechmark
|
|||||||
c.out.printStdout("------------------------------------------------------------------------------------------------\n")
|
c.out.printStdout("------------------------------------------------------------------------------------------------\n")
|
||||||
|
|
||||||
for ndx, r := range results {
|
for ndx, r := range results {
|
||||||
c.out.printStdout("%3d. %-26v %-12v %-12v %-8v %v",
|
maybeDeprecated := ""
|
||||||
|
if compression.IsDeprecated[r.compression] {
|
||||||
|
maybeDeprecated = " (deprecated)"
|
||||||
|
}
|
||||||
|
|
||||||
|
c.out.printStdout("%3d. %-26v %-12v %-12v %-8v %v%v",
|
||||||
ndx,
|
ndx,
|
||||||
r.compression,
|
r.compression,
|
||||||
units.BytesStringBase2(r.compressedSize),
|
units.BytesStringBase2(r.compressedSize),
|
||||||
units.BytesStringBase2(int64(r.throughput))+"/s",
|
units.BytesStringBase2(int64(r.throughput))+"/s",
|
||||||
r.allocations,
|
r.allocations,
|
||||||
units.BytesStringBase2(r.allocBytes),
|
units.BytesStringBase2(r.allocBytes),
|
||||||
|
maybeDeprecated,
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.optionPrint {
|
if c.optionPrint {
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -83,7 +83,7 @@ require (
|
|||||||
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
|
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/kopia/htmluibuild v0.0.0-20220702012237-9d334f452b6b
|
github.com/kopia/htmluibuild v0.0.0-20220703174648-d70429a8dad7
|
||||||
github.com/kr/fs v0.1.0 // indirect
|
github.com/kr/fs v0.1.0 // indirect
|
||||||
github.com/mattn/go-ieproxy v0.0.1 // indirect
|
github.com/mattn/go-ieproxy v0.0.1 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -349,6 +349,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
|||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kopia/htmluibuild v0.0.0-20220702012237-9d334f452b6b h1:ox9MBvtiRvcnVjYQd5XYmk9IhRGMo7lK/pbJA1Ud2EY=
|
github.com/kopia/htmluibuild v0.0.0-20220702012237-9d334f452b6b h1:ox9MBvtiRvcnVjYQd5XYmk9IhRGMo7lK/pbJA1Ud2EY=
|
||||||
github.com/kopia/htmluibuild v0.0.0-20220702012237-9d334f452b6b/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw=
|
github.com/kopia/htmluibuild v0.0.0-20220702012237-9d334f452b6b/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw=
|
||||||
|
github.com/kopia/htmluibuild v0.0.0-20220703174648-d70429a8dad7 h1:OdKsyukYW8aww2naIL2HECJbcuicvJrOb884tI+2FWM=
|
||||||
|
github.com/kopia/htmluibuild v0.0.0-20220703174648-d70429a8dad7/go.mod h1:eWer4rx9P8lJo2eKc+Q7AZ1dE1x1hJNdkbDFPzMu1Hw=
|
||||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
|||||||
@@ -251,25 +251,59 @@ func handleRepoSetDescription(ctx context.Context, rc requestContext) (interface
|
|||||||
|
|
||||||
func handleRepoSupportedAlgorithms(ctx context.Context, rc requestContext) (interface{}, *apiError) {
|
func handleRepoSupportedAlgorithms(ctx context.Context, rc requestContext) (interface{}, *apiError) {
|
||||||
res := &serverapi.SupportedAlgorithmsResponse{
|
res := &serverapi.SupportedAlgorithmsResponse{
|
||||||
DefaultHashAlgorithm: hashing.DefaultAlgorithm,
|
DefaultHashAlgorithm: hashing.DefaultAlgorithm,
|
||||||
HashAlgorithms: hashing.SupportedAlgorithms(),
|
SupportedHashAlgorithms: toAlgorithmInfo(hashing.SupportedAlgorithms(), neverDeprecated),
|
||||||
|
|
||||||
DefaultEncryptionAlgorithm: encryption.DefaultAlgorithm,
|
DefaultEncryptionAlgorithm: encryption.DefaultAlgorithm,
|
||||||
EncryptionAlgorithms: encryption.SupportedAlgorithms(false),
|
SupportedEncryptionAlgorithms: toAlgorithmInfo(encryption.SupportedAlgorithms(false), neverDeprecated),
|
||||||
|
|
||||||
DefaultSplitterAlgorithm: splitter.DefaultAlgorithm,
|
DefaultSplitterAlgorithm: splitter.DefaultAlgorithm,
|
||||||
SplitterAlgorithms: splitter.SupportedAlgorithms(),
|
SupportedSplitterAlgorithms: toAlgorithmInfo(splitter.SupportedAlgorithms(), neverDeprecated),
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range compression.ByName {
|
for k := range compression.ByName {
|
||||||
res.CompressionAlgorithms = append(res.CompressionAlgorithms, string(k))
|
res.SupportedCompressionAlgorithms = append(res.SupportedCompressionAlgorithms, serverapi.AlgorithmInfo{
|
||||||
|
ID: string(k),
|
||||||
|
Deprecated: compression.IsDeprecated[k],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Strings(res.CompressionAlgorithms)
|
sortAlgorithms(res.SupportedHashAlgorithms)
|
||||||
|
sortAlgorithms(res.SupportedEncryptionAlgorithms)
|
||||||
|
sortAlgorithms(res.SupportedCompressionAlgorithms)
|
||||||
|
sortAlgorithms(res.SupportedSplitterAlgorithms)
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func neverDeprecated(n string) bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func toAlgorithmInfo(names []string, isDeprecated func(id string) bool) []serverapi.AlgorithmInfo {
|
||||||
|
var result []serverapi.AlgorithmInfo
|
||||||
|
|
||||||
|
for _, n := range names {
|
||||||
|
result = append(result, serverapi.AlgorithmInfo{
|
||||||
|
ID: n,
|
||||||
|
Deprecated: isDeprecated(n),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortAlgorithms(a []serverapi.AlgorithmInfo) {
|
||||||
|
sort.Slice(a, func(i, j int) bool {
|
||||||
|
if l, r := a[i].Deprecated, a[j].Deprecated; l != r {
|
||||||
|
// non-deprecated first
|
||||||
|
return !l
|
||||||
|
}
|
||||||
|
|
||||||
|
return a[i].ID < a[j].ID
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func handleRepoGetThrottle(ctx context.Context, rc requestContext) (interface{}, *apiError) {
|
func handleRepoGetThrottle(ctx context.Context, rc requestContext) (interface{}, *apiError) {
|
||||||
dr, ok := rc.rep.(repo.DirectRepository)
|
dr, ok := rc.rep.(repo.DirectRepository)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
@@ -128,15 +128,22 @@ type ConnectRepositoryRequest struct {
|
|||||||
SyncWaitTimeSeconds int `json:"syncWaitTime"` // if non-zero, force particular wait time, negative == forever
|
SyncWaitTimeSeconds int `json:"syncWaitTime"` // if non-zero, force particular wait time, negative == forever
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AlgorithmInfo is an information about a single algorithm.
|
||||||
|
type AlgorithmInfo struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Deprecated bool `json:"deprecated"`
|
||||||
|
}
|
||||||
|
|
||||||
// SupportedAlgorithmsResponse returns the list of supported algorithms for repository creation.
|
// SupportedAlgorithmsResponse returns the list of supported algorithms for repository creation.
|
||||||
type SupportedAlgorithmsResponse struct {
|
type SupportedAlgorithmsResponse struct {
|
||||||
DefaultHashAlgorithm string `json:"defaultHash"`
|
DefaultHashAlgorithm string `json:"defaultHash"`
|
||||||
DefaultEncryptionAlgorithm string `json:"defaultEncryption"`
|
DefaultEncryptionAlgorithm string `json:"defaultEncryption"`
|
||||||
DefaultSplitterAlgorithm string `json:"defaultSplitter"`
|
DefaultSplitterAlgorithm string `json:"defaultSplitter"`
|
||||||
HashAlgorithms []string `json:"hash"`
|
|
||||||
EncryptionAlgorithms []string `json:"encryption"`
|
SupportedHashAlgorithms []AlgorithmInfo `json:"hash"`
|
||||||
SplitterAlgorithms []string `json:"splitter"`
|
SupportedEncryptionAlgorithms []AlgorithmInfo `json:"encryption"`
|
||||||
CompressionAlgorithms []string `json:"compression"`
|
SupportedSplitterAlgorithms []AlgorithmInfo `json:"splitter"`
|
||||||
|
SupportedCompressionAlgorithms []AlgorithmInfo `json:"compression"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSnapshotSourceRequest contains request to create snapshot source and optionally create first snapshot.
|
// CreateSnapshotSourceRequest contains request to create snapshot source and optionally create first snapshot.
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ type Compressor interface {
|
|||||||
ByHeaderID = map[HeaderID]Compressor{}
|
ByHeaderID = map[HeaderID]Compressor{}
|
||||||
ByName = map[Name]Compressor{}
|
ByName = map[Name]Compressor{}
|
||||||
HeaderIDToName = map[HeaderID]Name{}
|
HeaderIDToName = map[HeaderID]Name{}
|
||||||
|
IsDeprecated = map[Name]bool{}
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterCompressor registers the provided compressor implementation.
|
// RegisterCompressor registers the provided compressor implementation.
|
||||||
@@ -45,6 +46,13 @@ func RegisterCompressor(name Name, c Compressor) {
|
|||||||
HeaderIDToName[c.HeaderID()] = name
|
HeaderIDToName[c.HeaderID()] = name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterDeprecatedCompressor registers the provided compressor implementation.
|
||||||
|
func RegisterDeprecatedCompressor(name Name, c Compressor) {
|
||||||
|
RegisterCompressor(name, c)
|
||||||
|
|
||||||
|
IsDeprecated[name] = true
|
||||||
|
}
|
||||||
|
|
||||||
func compressionHeader(id HeaderID) []byte {
|
func compressionHeader(id HeaderID) []byte {
|
||||||
b := make([]byte, compressionHeaderSize)
|
b := make([]byte, compressionHeaderSize)
|
||||||
binary.BigEndian.PutUint32(b, uint32(id))
|
binary.BigEndian.PutUint32(b, uint32(id))
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RegisterCompressor("lz4", newLZ4Compressor(headerLZ4Default))
|
RegisterDeprecatedCompressor("lz4", newLZ4Compressor(headerLZ4Default))
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLZ4Compressor(id HeaderID) Compressor {
|
func newLZ4Compressor(id HeaderID) Compressor {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func init() {
|
|||||||
RegisterCompressor("zstd", newZstdCompressor(HeaderZstdDefault, zstd.SpeedDefault))
|
RegisterCompressor("zstd", newZstdCompressor(HeaderZstdDefault, zstd.SpeedDefault))
|
||||||
RegisterCompressor("zstd-fastest", newZstdCompressor(HeaderZstdFastest, zstd.SpeedFastest))
|
RegisterCompressor("zstd-fastest", newZstdCompressor(HeaderZstdFastest, zstd.SpeedFastest))
|
||||||
RegisterCompressor("zstd-better-compression", newZstdCompressor(HeaderZstdBetterCompression, zstd.SpeedBetterCompression))
|
RegisterCompressor("zstd-better-compression", newZstdCompressor(HeaderZstdBetterCompression, zstd.SpeedBetterCompression))
|
||||||
RegisterCompressor("zstd-best-compression", newZstdCompressor(HeaderZstdBestCompression, zstd.SpeedBestCompression))
|
RegisterDeprecatedCompressor("zstd-best-compression", newZstdCompressor(HeaderZstdBestCompression, zstd.SpeedBestCompression))
|
||||||
}
|
}
|
||||||
|
|
||||||
func newZstdCompressor(id HeaderID, level zstd.EncoderLevel) Compressor {
|
func newZstdCompressor(id HeaderID, level zstd.EncoderLevel) Compressor {
|
||||||
|
|||||||
Reference in New Issue
Block a user