mirror of
https://github.com/datarhei/core.git
synced 2025-10-07 08:51:04 +08:00
Add option to disable CPU throttling
This commit is contained in:
@@ -513,6 +513,7 @@ func (a *api) start(ctx context.Context) error {
|
|||||||
Portrange: portrange,
|
Portrange: portrange,
|
||||||
Collector: a.sessions.Collector("ffmpeg"),
|
Collector: a.sessions.Collector("ffmpeg"),
|
||||||
Resource: a.resources,
|
Resource: a.resources,
|
||||||
|
Throttling: !cfg.FFmpeg.DisableThrottling,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create ffmpeg: %w", err)
|
return fmt.Errorf("unable to create ffmpeg: %w", err)
|
||||||
|
@@ -1922,6 +1922,9 @@ const docTemplateClusterAPI = `{
|
|||||||
"binary": {
|
"binary": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"disable_throttling": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"log": {
|
"log": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@@ -1915,6 +1915,9 @@
|
|||||||
"binary": {
|
"binary": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"disable_throttling": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"log": {
|
"log": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@@ -429,6 +429,8 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
binary:
|
binary:
|
||||||
type: string
|
type: string
|
||||||
|
disable_throttling:
|
||||||
|
type: boolean
|
||||||
log:
|
log:
|
||||||
properties:
|
properties:
|
||||||
max_history:
|
max_history:
|
||||||
|
@@ -283,6 +283,7 @@ func (d *Config) init() {
|
|||||||
// FFmpeg
|
// FFmpeg
|
||||||
d.vars.Register(value.NewExec(&d.FFmpeg.Binary, "ffmpeg", d.fs), "ffmpeg.binary", "CORE_FFMPEG_BINARY", nil, "Path to ffmpeg binary", true, false)
|
d.vars.Register(value.NewExec(&d.FFmpeg.Binary, "ffmpeg", d.fs), "ffmpeg.binary", "CORE_FFMPEG_BINARY", nil, "Path to ffmpeg binary", true, false)
|
||||||
d.vars.Register(value.NewInt64(&d.FFmpeg.MaxProcesses, 0), "ffmpeg.max_processes", "CORE_FFMPEG_MAXPROCESSES", nil, "Max. allowed simultaneously running ffmpeg instances, 0 for unlimited", false, false)
|
d.vars.Register(value.NewInt64(&d.FFmpeg.MaxProcesses, 0), "ffmpeg.max_processes", "CORE_FFMPEG_MAXPROCESSES", nil, "Max. allowed simultaneously running ffmpeg instances, 0 for unlimited", false, false)
|
||||||
|
d.vars.Register(value.NewBool(&d.FFmpeg.DisableThrottling, false), "ffmpeg.disable_throttling", "CORE_FFMPEG_DISABLE_THROTTLING", nil, "Disable CPU throttling", false, false)
|
||||||
d.vars.Register(value.NewStringList(&d.FFmpeg.Access.Input.Allow, []string{}, " "), "ffmpeg.access.input.allow", "CORE_FFMPEG_ACCESS_INPUT_ALLOW", nil, "List of allowed expression to match against the input addresses", false, false)
|
d.vars.Register(value.NewStringList(&d.FFmpeg.Access.Input.Allow, []string{}, " "), "ffmpeg.access.input.allow", "CORE_FFMPEG_ACCESS_INPUT_ALLOW", nil, "List of allowed expression to match against the input addresses", false, false)
|
||||||
d.vars.Register(value.NewStringList(&d.FFmpeg.Access.Input.Block, []string{}, " "), "ffmpeg.access.input.block", "CORE_FFMPEG_ACCESS_INPUT_BLOCK", nil, "List of blocked expression to match against the input addresses", false, false)
|
d.vars.Register(value.NewStringList(&d.FFmpeg.Access.Input.Block, []string{}, " "), "ffmpeg.access.input.block", "CORE_FFMPEG_ACCESS_INPUT_BLOCK", nil, "List of blocked expression to match against the input addresses", false, false)
|
||||||
d.vars.Register(value.NewStringList(&d.FFmpeg.Access.Output.Allow, []string{}, " "), "ffmpeg.access.output.allow", "CORE_FFMPEG_ACCESS_OUTPUT_ALLOW", nil, "List of allowed expression to match against the output addresses", false, false)
|
d.vars.Register(value.NewStringList(&d.FFmpeg.Access.Output.Allow, []string{}, " "), "ffmpeg.access.output.allow", "CORE_FFMPEG_ACCESS_OUTPUT_ALLOW", nil, "List of allowed expression to match against the output addresses", false, false)
|
||||||
|
@@ -127,9 +127,10 @@ type Data struct {
|
|||||||
} `json:"log"`
|
} `json:"log"`
|
||||||
} `json:"srt"`
|
} `json:"srt"`
|
||||||
FFmpeg struct {
|
FFmpeg struct {
|
||||||
Binary string `json:"binary"`
|
Binary string `json:"binary"`
|
||||||
MaxProcesses int64 `json:"max_processes" format:"int64"`
|
MaxProcesses int64 `json:"max_processes" format:"int64"`
|
||||||
Access struct {
|
DisableThrottling bool `json:"disable_throttling"`
|
||||||
|
Access struct {
|
||||||
Input struct {
|
Input struct {
|
||||||
Allow []string `json:"allow"`
|
Allow []string `json:"allow"`
|
||||||
Block []string `json:"block"`
|
Block []string `json:"block"`
|
||||||
|
@@ -6077,6 +6077,9 @@ const docTemplate = `{
|
|||||||
"binary": {
|
"binary": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"disable_throttling": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"log": {
|
"log": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -8628,6 +8631,9 @@ const docTemplate = `{
|
|||||||
"binary": {
|
"binary": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"disable_throttling": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"log": {
|
"log": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@@ -6070,6 +6070,9 @@
|
|||||||
"binary": {
|
"binary": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"disable_throttling": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"log": {
|
"log": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -8621,6 +8624,9 @@
|
|||||||
"binary": {
|
"binary": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"disable_throttling": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"log": {
|
"log": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@@ -572,6 +572,8 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
binary:
|
binary:
|
||||||
type: string
|
type: string
|
||||||
|
disable_throttling:
|
||||||
|
type: boolean
|
||||||
log:
|
log:
|
||||||
properties:
|
properties:
|
||||||
max_history:
|
max_history:
|
||||||
@@ -2363,6 +2365,8 @@ definitions:
|
|||||||
type: object
|
type: object
|
||||||
binary:
|
binary:
|
||||||
type: string
|
type: string
|
||||||
|
disable_throttling:
|
||||||
|
type: boolean
|
||||||
log:
|
log:
|
||||||
properties:
|
properties:
|
||||||
max_history:
|
max_history:
|
||||||
|
@@ -65,7 +65,8 @@ type Config struct {
|
|||||||
ValidatorOutput Validator
|
ValidatorOutput Validator
|
||||||
Portrange net.Portranger
|
Portrange net.Portranger
|
||||||
Collector session.Collector
|
Collector session.Collector
|
||||||
Resource resources.Resources
|
Resource resources.Resources // Resource observer
|
||||||
|
Throttling bool // Whether to allow CPU throttling
|
||||||
}
|
}
|
||||||
|
|
||||||
type ffmpeg struct {
|
type ffmpeg struct {
|
||||||
@@ -84,7 +85,8 @@ type ffmpeg struct {
|
|||||||
states process.States
|
states process.States
|
||||||
statesLock sync.RWMutex
|
statesLock sync.RWMutex
|
||||||
|
|
||||||
resources resources.Resources
|
resources resources.Resources
|
||||||
|
throttling bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config Config) (FFmpeg, error) {
|
func New(config Config) (FFmpeg, error) {
|
||||||
@@ -95,6 +97,7 @@ func New(config Config) (FFmpeg, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
f.resources = config.Resource
|
f.resources = config.Resource
|
||||||
|
f.throttling = config.Throttling
|
||||||
|
|
||||||
binary, err := exec.LookPath(config.Binary)
|
binary, err := exec.LookPath(config.Binary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -164,6 +167,7 @@ func (f *ffmpeg) New(config ProcessConfig) (process.Process, error) {
|
|||||||
StaleTimeout: config.StaleTimeout,
|
StaleTimeout: config.StaleTimeout,
|
||||||
Timeout: config.Timeout,
|
Timeout: config.Timeout,
|
||||||
LimitCPU: config.LimitCPU,
|
LimitCPU: config.LimitCPU,
|
||||||
|
Throttling: f.throttling,
|
||||||
LimitMemory: config.LimitMemory,
|
LimitMemory: config.LimitMemory,
|
||||||
LimitGPUUsage: config.LimitGPUUsage,
|
LimitGPUUsage: config.LimitGPUUsage,
|
||||||
LimitGPUEncoder: config.LimitGPUEncoder,
|
LimitGPUEncoder: config.LimitGPUEncoder,
|
||||||
|
@@ -86,6 +86,7 @@ type LimiterConfig struct {
|
|||||||
OnLimit LimitFunc // Function to be triggered if limits are exceeded.
|
OnLimit LimitFunc // Function to be triggered if limits are exceeded.
|
||||||
Mode LimitMode // How to limit CPU usage.
|
Mode LimitMode // How to limit CPU usage.
|
||||||
NCPU float64 // Number of available CPU
|
NCPU float64 // Number of available CPU
|
||||||
|
Throttling bool // Whether to allow CPU throttling
|
||||||
Logger log.Logger
|
Logger log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,8 +237,9 @@ type limiter struct {
|
|||||||
lastUsage Usage
|
lastUsage Usage
|
||||||
lastUsageLock sync.RWMutex
|
lastUsageLock sync.RWMutex
|
||||||
|
|
||||||
cpu metric[float64] // CPU limit
|
cpu metric[float64] // CPU limit
|
||||||
cpuThrottling bool // Whether CPU throttling is currently active (soft limiter mode)
|
cpuThrottling bool // Whether CPU throttling is currently active (soft limiter mode)
|
||||||
|
cpuEnableThrottling bool // Whether to enable CPU throttling
|
||||||
|
|
||||||
memory metric[uint64] // Memory limit (bytes)
|
memory metric[uint64] // Memory limit (bytes)
|
||||||
|
|
||||||
@@ -269,7 +271,10 @@ func NewLimiter(config LimiterConfig) (Limiter, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l.cpu.SetLimit(config.CPU / 100)
|
l.cpu.SetLimit(config.CPU / 100)
|
||||||
|
l.cpuEnableThrottling = config.Throttling
|
||||||
|
|
||||||
l.memory.SetLimit(config.Memory)
|
l.memory.SetLimit(config.Memory)
|
||||||
|
|
||||||
l.gpu.memory.SetLimit(config.GPUMemory)
|
l.gpu.memory.SetLimit(config.GPUMemory)
|
||||||
l.gpu.usage.SetLimit(config.GPUUsage / 100)
|
l.gpu.usage.SetLimit(config.GPUUsage / 100)
|
||||||
l.gpu.encoder.SetLimit(config.GPUEncoder / 100)
|
l.gpu.encoder.SetLimit(config.GPUEncoder / 100)
|
||||||
@@ -342,7 +347,7 @@ func (l *limiter) Start(process resources.Process) error {
|
|||||||
|
|
||||||
go l.ticker(ctx, time.Second)
|
go l.ticker(ctx, time.Second)
|
||||||
|
|
||||||
if l.mode == LimitModeSoft {
|
if l.mode == LimitModeSoft && l.cpuEnableThrottling {
|
||||||
go l.limitCPU(ctx, l.cpu.Limit(), time.Second)
|
go l.limitCPU(ctx, l.cpu.Limit(), time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,7 +412,7 @@ func (l *limiter) collect() {
|
|||||||
|
|
||||||
isLimitExceeded := false
|
isLimitExceeded := false
|
||||||
|
|
||||||
if l.mode == LimitModeHard {
|
if l.mode == LimitModeHard || !l.cpuEnableThrottling {
|
||||||
if l.cpu.IsExceeded(l.waitFor, l.mode) {
|
if l.cpu.IsExceeded(l.waitFor, l.mode) {
|
||||||
l.logger.Warn().Log("CPU limit exceeded")
|
l.logger.Warn().Log("CPU limit exceeded")
|
||||||
isLimitExceeded = true
|
isLimitExceeded = true
|
||||||
|
@@ -58,6 +58,7 @@ type Config struct {
|
|||||||
StaleTimeout time.Duration // Kill the process after this duration if it doesn't produce any output.
|
StaleTimeout time.Duration // Kill the process after this duration if it doesn't produce any output.
|
||||||
Timeout time.Duration // Kill the process after this duration.
|
Timeout time.Duration // Kill the process after this duration.
|
||||||
LimitCPU float64 // Kill the process if the CPU usage in percent is above this value, in percent 0-100 in hard mode, 0-100*ncpu in soft mode.
|
LimitCPU float64 // Kill the process if the CPU usage in percent is above this value, in percent 0-100 in hard mode, 0-100*ncpu in soft mode.
|
||||||
|
Throttling bool // Whether to allow CPU throttling
|
||||||
LimitMemory uint64 // Kill the process if the memory consumption in bytes is above this value.
|
LimitMemory uint64 // Kill the process if the memory consumption in bytes is above this value.
|
||||||
LimitGPUUsage float64 // Kill the process if the GPU usage in percent is above this value, in percent 0-100.
|
LimitGPUUsage float64 // Kill the process if the GPU usage in percent is above this value, in percent 0-100.
|
||||||
LimitGPUEncoder float64 // Kill the process if the GPU encoder usage in percent is above this value, in percent 0-100.
|
LimitGPUEncoder float64 // Kill the process if the GPU encoder usage in percent is above this value, in percent 0-100.
|
||||||
@@ -312,6 +313,7 @@ func New(config Config) (Process, error) {
|
|||||||
|
|
||||||
limits, err := NewLimiter(LimiterConfig{
|
limits, err := NewLimiter(LimiterConfig{
|
||||||
CPU: config.LimitCPU,
|
CPU: config.LimitCPU,
|
||||||
|
Throttling: config.Throttling,
|
||||||
NCPU: ncpu,
|
NCPU: ncpu,
|
||||||
Memory: config.LimitMemory,
|
Memory: config.LimitMemory,
|
||||||
GPUUsage: config.LimitGPUUsage,
|
GPUUsage: config.LimitGPUUsage,
|
||||||
|
Reference in New Issue
Block a user