Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backpressure/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ type Operator interface {
// AllowRequest используется интерсепторами запросов для подавления части запросов во время пиковых нагрузок.
AllowRequest() bool
// GetStats возвращает статистику подсистемы backpressure
GetStats() *stats.Backpressure
GetStats() *stats.BackpressureStats
}
2 changes: 1 addition & 1 deletion backpressure/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type OperatorMock struct {
mock.Mock
}

func (m *OperatorMock) GetStats() *stats.Backpressure {
func (m *OperatorMock) GetStats() *stats.BackpressureStats {
// TODO implement me
panic("implement me")
}
Expand Down
4 changes: 2 additions & 2 deletions backpressure/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ type operatorImpl struct {
logger logr.Logger
}

func (b *operatorImpl) GetStats() *stats.Backpressure {
result := &stats.Backpressure{
func (b *operatorImpl) GetStats() *stats.BackpressureStats {
result := &stats.BackpressureStats{
Throttling: b.throttler.getStats(),
}

Expand Down
4 changes: 2 additions & 2 deletions backpressure/throttler.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ func (t *throttler) setThreshold(value uint32) error {
return nil
}

func (t *throttler) getStats() *stats.Throttling {
return &stats.Throttling{
func (t *throttler) getStats() *stats.ThrottlingStats {
return &stats.ThrottlingStats{
Total: uint64(t.requestsTotal.Count()),
Passed: uint64(t.requestsPassed.Count()),
Throttled: uint64(t.requestsThrottled.Count()),
Expand Down
2 changes: 1 addition & 1 deletion controller/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ import (

// Controller - обобщённый интерфейс регулятора.
type Controller interface {
GetStats() (*stats.Controller, error)
GetStats() (*stats.ControllerStats, error)
Quit()
}
22 changes: 11 additions & 11 deletions controller/nextgc/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ type controllerImpl struct {
}

type getStatsRequest struct {
result chan *stats.Controller
result chan *stats.ControllerStats
}

func (r *getStatsRequest) respondWith(resp *stats.Controller) {
func (r *getStatsRequest) respondWith(resp *stats.ControllerStats) {
r.result <- resp
}

func (c *controllerImpl) GetStats() (*stats.Controller, error) {
req := &getStatsRequest{result: make(chan *stats.Controller, 1)}
func (c *controllerImpl) GetStats() (*stats.ControllerStats, error) {
req := &getStatsRequest{result: make(chan *stats.ControllerStats, 1)}

select {
case c.getStatsChan <- req:
Expand Down Expand Up @@ -112,7 +112,7 @@ func (c *controllerImpl) loop() {
}
}

func (c *controllerImpl) updateState(serviceStats *stats.Service) error {
func (c *controllerImpl) updateState(serviceStats *stats.ServiceStats) error {
// извлекаем оперативную информацию о спец. потребителях памяти, если она предоставляется клиентом
if c.consumptionReporter != nil {
var err error
Expand All @@ -134,7 +134,7 @@ func (c *controllerImpl) updateState(serviceStats *stats.Service) error {
return nil
}

func (c *controllerImpl) updateUtilization(serviceStats *stats.Service) {
func (c *controllerImpl) updateUtilization(serviceStats *stats.ServiceStats) {
// Чтобы понять, сколько памяти можно аллоцировать на нужды Go,
// требуется вычесть из общего лимита на RSS память, в явном виде потраченную в CGO.
// Иными словами, если аллокации в CGO будут расти, то аллокации в Go должны ужиматься.
Expand Down Expand Up @@ -224,21 +224,21 @@ func (c *controllerImpl) applyControlValue() error {
return nil
}

func (c *controllerImpl) aggregateStats() *stats.Controller {
res := &stats.Controller{
MemoryBudget: &stats.MemoryBudget{
func (c *controllerImpl) aggregateStats() *stats.ControllerStats {
res := &stats.ControllerStats{
MemoryBudget: &stats.MemoryBudgetStats{
RSSLimit: c.cfg.RSSLimit.Value,
GoAllocLimit: c.goAllocLimit,
Utilization: c.utilization,
},
NextGC: &stats.ControllerNextGC{
NextGC: &stats.ControllerNextGCStats{
P: c.pValue,
Output: c.sumValue,
},
}

if c.consumptionReport != nil {
res.MemoryBudget.SpecialConsumers = &stats.SpecialConsumers{}
res.MemoryBudget.SpecialConsumers = &stats.SpecialConsumersStats{}
res.MemoryBudget.SpecialConsumers.Go = c.consumptionReport.Go
res.MemoryBudget.SpecialConsumers.Cgo = c.consumptionReport.Cgo
}
Expand Down
8 changes: 4 additions & 4 deletions controller/nextgc/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,17 @@ func TestController(t *testing.T) {
}

// Первый вариант статистики описывает ситуацию, когда память близка к исчерпанию
memoryBudgetExhausted := &stats.Service{
memoryBudgetExhausted := &stats.ServiceStats{
NextGC: 950 * bytefmt.MEGABYTE, // память потрачена на 95%
}

// Во втором варианте бюджет памяти возвращается в норму
memoryBudgetNormal := &stats.Service{
memoryBudgetNormal := &stats.ServiceStats{
NextGC: 300 * bytefmt.MEGABYTE, // память потрачена на 50%
}

subscriptionMock := &stats.ServiceSubscriptionMock{
Chan: make(chan *stats.Service),
Chan: make(chan *stats.ServiceStats),
}

// канал закрывается, когда backpressure.Operator получит все необходимые команды
Expand All @@ -63,7 +63,7 @@ func TestController(t *testing.T) {
for {
select {
case <-ticker.C:
serviceStats, ok := serviceStatsContainer.Load().(*stats.Service)
serviceStats, ok := serviceStatsContainer.Load().(*stats.ServiceStats)
if ok {
subscriptionMock.Chan <- serviceStats
}
Expand Down
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ require (
)

require (
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/objx v0.2.0 // indirect
github.com/urfave/cli/v2 v2.8.1 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect
golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d // indirect
google.golang.org/protobuf v1.26.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
Expand Down
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand All @@ -16,8 +18,11 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
Expand Down Expand Up @@ -71,6 +76,8 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5X
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
Expand All @@ -80,10 +87,14 @@ github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMT
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tsuna/endian v0.0.0-20151020052604-29b3a4178852 h1:/HMzghBx/U8ZTQ+CCKRAsjeNNV12OCG3PfJcthNMBU0=
github.com/tsuna/endian v0.0.0-20151020052604-29b3a4178852/go.mod h1:7SvkOZYNBtjd5XUi2fuPMvAZS8rlCMaU69hj/3joIsE=
github.com/urfave/cli/v2 v2.8.1 h1:CGuYNZF9IKZY/rfBe3lJpccSoIY1ytfvmgQT90cNOl4=
github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY=
github.com/valyala/fastrand v1.0.0 h1:LUKT9aKer2dVQNUi3waewTbKV+7H17kvWFNKs2ObdkI=
github.com/valyala/fastrand v1.0.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
github.com/villenny/fastrand64-go v0.0.0-20201008161821-3d8fa521c558 h1:oNwFCUPi4ns2fMuaBtzMdQImdt25neDPJPBTNprmdF8=
github.com/villenny/fastrand64-go v0.0.0-20201008161821-3d8fa521c558/go.mod h1:0KogUQQf0cFYfgnOpYJqw1RnSb4S1oJwUb1CEpGJLJ4=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yalue/native_endian v0.0.0-20180607135909-51013b03be4f h1:nsQCScpQ8RRf+wIooqfyyEUINV2cAPuo2uVtHSBbA4M=
github.com/yalue/native_endian v0.0.0-20180607135909-51013b03be4f/go.mod h1:1cm5YQZdnDQBZVtFG2Ip8sFVN0eYZ8OFkCT2kIVl9mw=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down Expand Up @@ -141,6 +152,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
Expand Down
2 changes: 1 addition & 1 deletion interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

// Service - верхнеуровневый интерфейс системы управления бюджетом оперативной памяти.
type Service interface {
GetStats() (*stats.Memlimiter, error)
GetStats() (*stats.MemlimiterStats, error)
// MakeUnaryServerInterceptor возвращает интерсептор для унарных запросов
MakeUnaryServerInterceptor() grpc.UnaryServerInterceptor
// MakeStreamServerInterceptor возвращает интерсептор для стримовых запросов
Expand Down
4 changes: 2 additions & 2 deletions memlimiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ type serviceImpl struct {
logger logr.Logger
}

func (s *serviceImpl) GetStats() (*stats.Memlimiter, error) {
func (s *serviceImpl) GetStats() (*stats.MemlimiterStats, error) {
controllerStats, err := s.controller.GetStats()
if err != nil {
return nil, errors.Wrap(err, "controller get stats")
}

backpressureStats := s.backpressureOperator.GetStats()

return &stats.Memlimiter{
return &stats.MemlimiterStats{
Controller: controllerStats,
Backpressure: backpressureStats,
}, nil
Expand Down
26 changes: 13 additions & 13 deletions stats/memlimiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,39 @@ import (
"fmt"
)

type Memlimiter struct {
Controller *Controller
Backpressure *Backpressure
type MemlimiterStats struct {
Controller *ControllerStats
Backpressure *BackpressureStats
}

type Controller struct {
MemoryBudget *MemoryBudget
NextGC *ControllerNextGC
type ControllerStats struct {
MemoryBudget *MemoryBudgetStats
NextGC *ControllerNextGCStats
}

type MemoryBudget struct {
type MemoryBudgetStats struct {
RSSLimit uint64
GoAllocLimit uint64
Utilization float64
SpecialConsumers *SpecialConsumers
SpecialConsumers *SpecialConsumersStats
}

type SpecialConsumers struct {
type SpecialConsumersStats struct {
Go map[string]uint64
Cgo map[string]uint64
}

type ControllerNextGC struct {
type ControllerNextGCStats struct {
P float64
Output float64
}

type Backpressure struct {
Throttling *Throttling
type BackpressureStats struct {
Throttling *ThrottlingStats
ControlParameters *ControlParameters
}

type Throttling struct {
type ThrottlingStats struct {
Total uint64
Passed uint64
Throttled uint64
Expand Down
4 changes: 2 additions & 2 deletions stats/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (
var _ Subscription = (*ServiceSubscriptionMock)(nil)

type ServiceSubscriptionMock struct {
Chan chan *Service
Chan chan *ServiceStats
mock.Mock
}

func (m *ServiceSubscriptionMock) Updates() <-chan *Service {
func (m *ServiceSubscriptionMock) Updates() <-chan *ServiceStats {
return m.Chan
}

Expand Down
8 changes: 1 addition & 7 deletions stats/service.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
package stats

type Service struct {
type ServiceStats struct {
NextGC uint64
Custom interface{}
}

// Subscription - интерфейс подписки на оперативную статистику
type Subscription interface {
Updates() <-chan *Service
Quit()
}
67 changes: 67 additions & 0 deletions stats/subscription.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package stats

import (
"runtime"
"time"

"github.com/newcloudtechnologies/memlimiter/utils/breaker"
)

// Subscription - интерфейс подписки на оперативную статистику
type Subscription interface {
Updates() <-chan *ServiceStats
Quit()
}

type subscriptionDefault struct {
outChan chan *ServiceStats
period time.Duration
breaker *breaker.Breaker
}

func (s *subscriptionDefault) Updates() <-chan *ServiceStats { return s.outChan }

func (s *subscriptionDefault) Quit() {
s.breaker.ShutdownAndWait()
}

func (s *subscriptionDefault) makeServiceStats() *ServiceStats {
ms := &runtime.MemStats{}
runtime.ReadMemStats(ms)

return &ServiceStats{
NextGC: ms.NextGC,
// don't forget to put real stats of your service in your own implementation
Custom: nil,
}
}

func NewSubscriptionDefault(period time.Duration) Subscription {
ss := &subscriptionDefault{
outChan: make(chan *ServiceStats),
period: period,
breaker: breaker.NewBreakerWithInitValue(1),
}

go func() {
ticker := time.NewTicker(period)
defer ticker.Stop()

defer ss.breaker.Dec()

for {
select {
case <-ticker.C:
select {
case ss.outChan <- ss.makeServiceStats():
case <-ss.breaker.Done():
return
}
case <-ss.breaker.Done():
return
}
}
}()

return ss
}
Loading