Add LimitMode and Resources.CPU.IsThrottling to process state

This commit is contained in:
Ingo Oppermann
2023-07-17 21:45:19 +02:00
parent 5b075ed54b
commit 8a8ff6d4f4
8 changed files with 66 additions and 26 deletions

View File

@@ -6147,6 +6147,9 @@ const docTemplate = `{
"last_logline": { "last_logline": {
"type": "string" "type": "string"
}, },
"limit_mode": {
"type": "string"
},
"memory_bytes": { "memory_bytes": {
"description": "deprecated, use Resources.CPU.Current", "description": "deprecated, use Resources.CPU.Current",
"type": "integer", "type": "integer",
@@ -6199,6 +6202,9 @@ const docTemplate = `{
}, },
"ncpu": { "ncpu": {
"type": "number" "type": "number"
},
"throttling": {
"type": "boolean"
} }
} }
}, },

View File

@@ -6139,6 +6139,9 @@
"last_logline": { "last_logline": {
"type": "string" "type": "string"
}, },
"limit_mode": {
"type": "string"
},
"memory_bytes": { "memory_bytes": {
"description": "deprecated, use Resources.CPU.Current", "description": "deprecated, use Resources.CPU.Current",
"type": "integer", "type": "integer",
@@ -6191,6 +6194,9 @@
}, },
"ncpu": { "ncpu": {
"type": "number" "type": "number"
},
"throttling": {
"type": "boolean"
} }
} }
}, },

View File

@@ -1220,6 +1220,8 @@ definitions:
type: string type: string
last_logline: last_logline:
type: string type: string
limit_mode:
type: string
memory_bytes: memory_bytes:
description: deprecated, use Resources.CPU.Current description: deprecated, use Resources.CPU.Current
format: uint64 format: uint64
@@ -1256,6 +1258,8 @@ definitions:
type: number type: number
ncpu: ncpu:
type: number type: number
throttling:
type: boolean
type: object type: object
api.ProcessUsageMemory: api.ProcessUsageMemory:
properties: properties:

View File

@@ -227,6 +227,7 @@ type ProcessState struct {
Progress *Progress `json:"progress"` Progress *Progress `json:"progress"`
Memory uint64 `json:"memory_bytes" format:"uint64"` // deprecated, use Resources.CPU.Current Memory uint64 `json:"memory_bytes" format:"uint64"` // deprecated, use Resources.CPU.Current
CPU json.Number `json:"cpu_usage" swaggertype:"number" jsonschema:"type=number"` // deprecated, use Resources.Memory.Current CPU json.Number `json:"cpu_usage" swaggertype:"number" jsonschema:"type=number"` // deprecated, use Resources.Memory.Current
LimitMode string `json:"limit_mode"`
Resources ProcessUsage `json:"resources"` Resources ProcessUsage `json:"resources"`
Command []string `json:"command"` Command []string `json:"command"`
} }
@@ -245,12 +246,14 @@ func (s *ProcessState) Unmarshal(state *app.State) {
s.Progress = &Progress{} s.Progress = &Progress{}
s.Memory = state.Memory s.Memory = state.Memory
s.CPU = ToNumber(state.CPU) s.CPU = ToNumber(state.CPU)
s.LimitMode = state.LimitMode
s.Resources.CPU = ProcessUsageCPU{ s.Resources.CPU = ProcessUsageCPU{
NCPU: ToNumber(state.Resources.CPU.NCPU), NCPU: ToNumber(state.Resources.CPU.NCPU),
Current: ToNumber(state.Resources.CPU.Current), Current: ToNumber(state.Resources.CPU.Current),
Average: ToNumber(state.Resources.CPU.Average), Average: ToNumber(state.Resources.CPU.Average),
Max: ToNumber(state.Resources.CPU.Max), Max: ToNumber(state.Resources.CPU.Max),
Limit: ToNumber(state.Resources.CPU.Limit), Limit: ToNumber(state.Resources.CPU.Limit),
IsThrottling: state.Resources.CPU.IsThrottling,
} }
s.Resources.Memory = ProcessUsageMemory{ s.Resources.Memory = ProcessUsageMemory{
Current: state.Resources.Memory.Current, Current: state.Resources.Memory.Current,
@@ -264,11 +267,12 @@ func (s *ProcessState) Unmarshal(state *app.State) {
} }
type ProcessUsageCPU struct { type ProcessUsageCPU struct {
NCPU json.Number `json:"ncpu" swaggertype:"number" jsonschema:"type=number"` NCPU json.Number `json:"ncpu" swaggertype:"number" jsonschema:"type=number"`
Current json.Number `json:"cur" swaggertype:"number" jsonschema:"type=number"` Current json.Number `json:"cur" swaggertype:"number" jsonschema:"type=number"`
Average json.Number `json:"avg" swaggertype:"number" jsonschema:"type=number"` Average json.Number `json:"avg" swaggertype:"number" jsonschema:"type=number"`
Max json.Number `json:"max" swaggertype:"number" jsonschema:"type=number"` Max json.Number `json:"max" swaggertype:"number" jsonschema:"type=number"`
Limit json.Number `json:"limit" swaggertype:"number" jsonschema:"type=number"` Limit json.Number `json:"limit" swaggertype:"number" jsonschema:"type=number"`
IsThrottling bool `json:"throttling"`
} }
type ProcessUsageMemory struct { type ProcessUsageMemory struct {

View File

@@ -12,11 +12,12 @@ import (
type Usage struct { type Usage struct {
CPU struct { CPU struct {
NCPU float64 // number of logical processors NCPU float64 // number of logical processors
Current float64 // percent 0-100*ncpu Current float64 // percent 0-100*ncpu
Average float64 // percent 0-100*ncpu Average float64 // percent 0-100*ncpu
Max float64 // percent 0-100*ncpu Max float64 // percent 0-100*ncpu
Limit float64 // percent 0-100*ncpu Limit float64 // percent 0-100*ncpu
IsThrottling bool
} }
Memory struct { Memory struct {
Current uint64 // bytes Current uint64 // bytes
@@ -79,6 +80,9 @@ type Limiter interface {
// Limit enables or disables the throttling of the CPU or killing because of to much // Limit enables or disables the throttling of the CPU or killing because of to much
// memory consumption. // memory consumption.
Limit(cpu, memory bool) error Limit(cpu, memory bool) error
// Mode returns in which mode the limiter is running in.
Mode() LimitMode
} }
type limiter struct { type limiter struct {
@@ -99,7 +103,8 @@ type limiter struct {
cpuAvg float64 // Average CPU load of this process cpuAvg float64 // Average CPU load of this process
cpuAvgCounter uint64 // Counter for average calculation cpuAvgCounter uint64 // Counter for average calculation
cpuLimitSince time.Time // Time when the CPU limit has been reached (hard limiter mode) cpuLimitSince time.Time // Time when the CPU limit has been reached (hard limiter mode)
cpuLimitEnable bool // Whether CPU limiting is enabled (soft limiter mode) cpuLimitEnable bool // Whether CPU throttling is enabled (soft limiter mode)
cpuThrottling bool // Whether CPU throttling is currently active (soft limiter mode)
memory uint64 // Memory limit (bytes) memory uint64 // Memory limit (bytes)
memoryCurrent uint64 // Current memory usage memoryCurrent uint64 // Current memory usage
@@ -177,6 +182,7 @@ func (l *limiter) reset() {
l.cpuMax = 0 l.cpuMax = 0
l.cpuTop = 0 l.cpuTop = 0
l.cpuLimitEnable = false l.cpuLimitEnable = false
l.cpuThrottling = false
l.memoryCurrent = 0 l.memoryCurrent = 0
l.memoryLast = 0 l.memoryLast = 0
@@ -399,6 +405,7 @@ func (l *limiter) limitCPU(ctx context.Context, limit float64, interval time.Dur
if l.proc != nil { if l.proc != nil {
l.proc.Resume() l.proc.Resume()
} }
l.cpuThrottling = false
l.lock.Unlock() l.lock.Unlock()
l.logger.Debug().Log("CPU throttler disabled") l.logger.Debug().Log("CPU throttler disabled")
@@ -426,6 +433,7 @@ func (l *limiter) limitCPU(ctx context.Context, limit float64, interval time.Dur
if l.proc != nil { if l.proc != nil {
l.proc.Resume() l.proc.Resume()
} }
l.cpuThrottling = false
l.lock.Unlock() l.lock.Unlock()
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
continue continue
@@ -433,6 +441,7 @@ func (l *limiter) limitCPU(ctx context.Context, limit float64, interval time.Dur
} else { } else {
factorTopLimit = 100 factorTopLimit = 100
topLimit = l.cpuTop - limit topLimit = l.cpuTop - limit
l.cpuThrottling = true
} }
lim := limit lim := limit
@@ -509,6 +518,7 @@ func (l *limiter) Usage() Usage {
usage.CPU.Current = l.cpuCurrent * l.ncpu * 100 usage.CPU.Current = l.cpuCurrent * l.ncpu * 100
usage.CPU.Average = l.cpuAvg * l.ncpu * 100 usage.CPU.Average = l.cpuAvg * l.ncpu * 100
usage.CPU.Max = l.cpuMax * l.ncpu * 100 usage.CPU.Max = l.cpuMax * l.ncpu * 100
usage.CPU.IsThrottling = l.cpuThrottling
usage.Memory.Limit = l.memory usage.Memory.Limit = l.memory
usage.Memory.Current = l.memoryCurrent usage.Memory.Current = l.memoryCurrent
@@ -521,3 +531,7 @@ func (l *limiter) Usage() Usage {
func (l *limiter) Limits() (cpu float64, memory uint64) { func (l *limiter) Limits() (cpu float64, memory uint64) {
return l.cpu * 100, l.memory return l.cpu * 100, l.memory
} }
func (l *limiter) Mode() LimitMode {
return l.mode
}

View File

@@ -80,12 +80,14 @@ type Status struct {
Duration time.Duration // Duration is the time since the last change of the state Duration time.Duration // Duration is the time since the last change of the state
Time time.Time // Time is the time of the last change of the state Time time.Time // Time is the time of the last change of the state
CommandArgs []string // Currently running command arguments CommandArgs []string // Currently running command arguments
LimitMode string // The limiting mode
CPU struct { CPU struct {
NCPU float64 // Number of logical CPUs NCPU float64 // Number of logical CPUs
Current float64 // Currently consumed CPU in percent Current float64 // Currently consumed CPU in percent
Average float64 // Average consumed CPU in percent Average float64 // Average consumed CPU in percent
Max float64 // Max. consumed CPU in percent Max float64 // Max. consumed CPU in percent
Limit float64 // Usage limit in percent Limit float64 // Usage limit in percent
IsThrottling bool // Whether the CPU is currently limited
} // Used CPU in percent } // Used CPU in percent
Memory struct { Memory struct {
Current uint64 // Currently consumed memory in bytes Current uint64 // Currently consumed memory in bytes
@@ -461,6 +463,7 @@ func (p *process) Status() Status {
Reconnect: time.Duration(-1), Reconnect: time.Duration(-1),
Duration: time.Since(stateTime), Duration: time.Since(stateTime),
Time: stateTime, Time: stateTime,
LimitMode: p.limits.Mode().String(),
CPU: usage.CPU, CPU: usage.CPU,
Memory: usage.Memory, Memory: usage.Memory,
} }

View File

@@ -248,16 +248,18 @@ type State struct {
Progress Progress // Progress data of the process Progress Progress // Progress data of the process
Memory uint64 // Current memory consumption in bytes Memory uint64 // Current memory consumption in bytes
CPU float64 // Current CPU consumption in percent CPU float64 // Current CPU consumption in percent
LimitMode string // How the process is limited (hard or soft)
Resources ProcessUsage // Current resource usage, include CPU and memory consumption Resources ProcessUsage // Current resource usage, include CPU and memory consumption
Command []string // ffmpeg command line parameters Command []string // ffmpeg command line parameters
} }
type ProcessUsageCPU struct { type ProcessUsageCPU struct {
NCPU float64 // Number of logical CPUs NCPU float64 // Number of logical CPUs
Current float64 // percent 0-100*ncpu Current float64 // percent 0-100*ncpu
Average float64 // percent 0-100*ncpu Average float64 // percent 0-100*ncpu
Max float64 // percent 0-100*ncpu Max float64 // percent 0-100*ncpu
Limit float64 // percent 0-100*ncpu Limit float64 // percent 0-100*ncpu
IsThrottling bool
} }
type ProcessUsageMemory struct { type ProcessUsageMemory struct {

View File

@@ -1576,6 +1576,7 @@ func (r *restream) GetProcessState(id app.ProcessID) (*app.State, error) {
state.Time = status.Time.Unix() state.Time = status.Time.Unix()
state.Memory = status.Memory.Current state.Memory = status.Memory.Current
state.CPU = status.CPU.Current / status.CPU.NCPU state.CPU = status.CPU.Current / status.CPU.NCPU
state.LimitMode = status.LimitMode
state.Resources.CPU = status.CPU state.Resources.CPU = status.CPU
state.Resources.Memory = status.Memory state.Resources.Memory = status.Memory
state.Duration = status.Duration.Round(10 * time.Millisecond).Seconds() state.Duration = status.Duration.Round(10 * time.Millisecond).Seconds()