package cgo import ( "math" "runtime" "time" "github.com/milvus-io/milvus/pkg/metrics" "github.com/milvus-io/milvus/pkg/util/hardware" "github.com/milvus-io/milvus/pkg/util/paramtable" ) var caller *cgoCaller func initCaller(nodeID string) { chSize := int64(math.Ceil(float64(hardware.GetCPUNum()) * paramtable.Get().QueryNodeCfg.CGOPoolSizeRatio.GetAsFloat())) if chSize <= 0 { chSize = 1 } caller = &cgoCaller{ ch: make(chan struct{}, chSize), nodeID: nodeID, } } // getCGOCaller returns the cgoCaller instance. func getCGOCaller() *cgoCaller { return caller } // cgoCaller is a limiter to restrict the number of concurrent cgo calls. type cgoCaller struct { ch chan struct{} nodeID string } // call calls the work function with a lock to restrict the number of concurrent cgo calls. // it collect some metrics too. func (c *cgoCaller) call(name string, work func()) { start := time.Now() c.ch <- struct{}{} queueTime := time.Since(start) metrics.CGOQueueDuration.WithLabelValues(c.nodeID).Observe(queueTime.Seconds()) runtime.LockOSThread() defer func() { runtime.UnlockOSThread() <-c.ch metrics.RunningCgoCallTotal.WithLabelValues(c.nodeID).Dec() total := time.Since(start) - queueTime metrics.CGODuration.WithLabelValues(c.nodeID, name).Observe(total.Seconds()) }() metrics.RunningCgoCallTotal.WithLabelValues(c.nodeID).Inc() work() }