allow configuring inline shard size value (#19336)

This commit is contained in:
Harshavardhana 2024-03-26 15:06:19 -07:00 committed by GitHub
parent 7ff4164d65
commit 0a56dbde2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 63 additions and 9 deletions

View File

@ -31,6 +31,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/dustin/go-humanize"
"github.com/klauspost/readahead" "github.com/klauspost/readahead"
"github.com/minio/madmin-go/v3" "github.com/minio/madmin-go/v3"
"github.com/minio/minio-go/v7/pkg/tags" "github.com/minio/minio-go/v7/pkg/tags"
@ -1396,20 +1397,25 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st
defer er.deleteAll(context.Background(), minioMetaTmpBucket, tempObj) defer er.deleteAll(context.Background(), minioMetaTmpBucket, tempObj)
shardFileSize := erasure.ShardFileSize(data.Size()) shardFileSize := erasure.ShardFileSize(data.Size())
inlineBlock := globalStorageClass.InlineBlock()
if inlineBlock <= 0 {
inlineBlock = 128 * humanize.KiByte
}
writers := make([]io.Writer, len(onlineDisks)) writers := make([]io.Writer, len(onlineDisks))
var inlineBuffers []*bytes.Buffer var inlineBuffers []*bytes.Buffer
if shardFileSize >= 0 { if shardFileSize >= 0 {
if !opts.Versioned && shardFileSize < smallFileThreshold { if !opts.Versioned && shardFileSize < inlineBlock {
inlineBuffers = make([]*bytes.Buffer, len(onlineDisks)) inlineBuffers = make([]*bytes.Buffer, len(onlineDisks))
} else if shardFileSize < smallFileThreshold/8 { } else if shardFileSize < inlineBlock/8 {
inlineBuffers = make([]*bytes.Buffer, len(onlineDisks)) inlineBuffers = make([]*bytes.Buffer, len(onlineDisks))
} }
} else { } else {
// If compressed, use actual size to determine. // If compressed, use actual size to determine.
if sz := erasure.ShardFileSize(data.ActualSize()); sz > 0 { if sz := erasure.ShardFileSize(data.ActualSize()); sz > 0 {
if !opts.Versioned && sz < smallFileThreshold { if !opts.Versioned && sz < inlineBlock {
inlineBuffers = make([]*bytes.Buffer, len(onlineDisks)) inlineBuffers = make([]*bytes.Buffer, len(onlineDisks))
} else if sz < smallFileThreshold/8 { } else if sz < inlineBlock/8 {
inlineBuffers = make([]*bytes.Buffer, len(onlineDisks)) inlineBuffers = make([]*bytes.Buffer, len(onlineDisks))
} }
} }

View File

@ -39,8 +39,8 @@ var (
Type: "string", Type: "string",
}, },
config.HelpKV{ config.HelpKV{
Key: ClassOptimize, Key: Optimize,
Description: `optimize parity calculation for standard storage class, set 'capacity' for capacity optimized (no additional parity)` + defaultHelpPostfix(ClassOptimize), Description: `optimize parity calculation for standard storage class, set 'capacity' for capacity optimized (no additional parity)` + defaultHelpPostfix(Optimize),
Optional: true, Optional: true,
Type: "string", Type: "string",
}, },

View File

@ -18,13 +18,16 @@
package storageclass package storageclass
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"github.com/dustin/go-humanize"
"github.com/minio/minio/internal/config" "github.com/minio/minio/internal/config"
"github.com/minio/minio/internal/logger"
"github.com/minio/pkg/v2/env" "github.com/minio/pkg/v2/env"
) )
@ -40,7 +43,8 @@ const (
const ( const (
ClassStandard = "standard" ClassStandard = "standard"
ClassRRS = "rrs" ClassRRS = "rrs"
ClassOptimize = "optimize" Optimize = "optimize"
InlineBlock = "inline_block"
// Reduced redundancy storage class environment variable // Reduced redundancy storage class environment variable
RRSEnv = "MINIO_STORAGE_CLASS_RRS" RRSEnv = "MINIO_STORAGE_CLASS_RRS"
@ -48,6 +52,14 @@ const (
StandardEnv = "MINIO_STORAGE_CLASS_STANDARD" StandardEnv = "MINIO_STORAGE_CLASS_STANDARD"
// Optimize storage class environment variable // Optimize storage class environment variable
OptimizeEnv = "MINIO_STORAGE_CLASS_OPTIMIZE" OptimizeEnv = "MINIO_STORAGE_CLASS_OPTIMIZE"
// Inline block indicates the size of the shard
// that is considered for inlining, remember this
// shard value is the value per drive shard it
// will vary based on the parity that is configured
// for the STANDARD storage_class.
// inlining means data and metadata are written
// together in a single file i.e xl.meta
InlineBlockEnv = "MINIO_STORAGE_CLASS_INLINE_BLOCK"
// Supported storage class scheme is EC // Supported storage class scheme is EC
schemePrefix = "EC" schemePrefix = "EC"
@ -71,9 +83,14 @@ var (
Value: "EC:1", Value: "EC:1",
}, },
config.KV{ config.KV{
Key: ClassOptimize, Key: Optimize,
Value: "availability", Value: "availability",
}, },
config.KV{
Key: InlineBlock,
Value: "",
HiddenIfEmpty: true,
},
} }
) )
@ -90,6 +107,8 @@ type Config struct {
Standard StorageClass `json:"standard"` Standard StorageClass `json:"standard"`
RRS StorageClass `json:"rrs"` RRS StorageClass `json:"rrs"`
Optimize string `json:"optimize"` Optimize string `json:"optimize"`
inlineBlock int64
initialized bool initialized bool
} }
@ -253,6 +272,19 @@ func (sCfg *Config) GetParityForSC(sc string) (parity int) {
} }
} }
// InlineBlock indicates the size of the block which will be used to inline
// an erasure shard and written along with xl.meta on the drive, on a versioned
// bucket this value is automatically chosen to 1/8th of the this value, make
// sure to put this into consideration when choosing this value.
func (sCfg *Config) InlineBlock() int64 {
ConfigLock.RLock()
defer ConfigLock.RUnlock()
if !sCfg.initialized {
return 128 * humanize.KiByte
}
return sCfg.inlineBlock
}
// CapacityOptimized - returns true if the storage-class is capacity optimized // CapacityOptimized - returns true if the storage-class is capacity optimized
// meaning we will not use additional parities when drives are offline. // meaning we will not use additional parities when drives are offline.
// //
@ -355,7 +387,23 @@ func LookupConfig(kvs config.KVS, setDriveCount int) (cfg Config, err error) {
return Config{}, err return Config{}, err
} }
cfg.Optimize = env.Get(OptimizeEnv, kvs.Get(Optimize))
inlineBlockStr := env.Get(InlineBlockEnv, kvs.Get(InlineBlock))
if inlineBlockStr != "" {
inlineBlock, err := humanize.ParseBytes(inlineBlockStr)
if err != nil {
return cfg, err
}
if inlineBlock > 128*humanize.KiByte {
logger.LogOnceIf(context.Background(), fmt.Errorf("inline block value bigger than recommended max of 128KiB -> %s, performance may degrade for PUT please benchmark the changes", inlineBlockStr), inlineBlockStr)
}
cfg.inlineBlock = int64(inlineBlock)
} else {
cfg.inlineBlock = 128 * humanize.KiByte
}
cfg.initialized = true cfg.initialized = true
cfg.Optimize = env.Get(OptimizeEnv, kvs.Get(ClassOptimize))
return cfg, nil return cfg, nil
} }