Skip to content

Commit

Permalink
service: re-use buffer for return all services
Browse files Browse the repository at this point in the history
Signed-off-by: Jan-Otto Kröpke <[email protected]>
  • Loading branch information
jkroepke committed Jan 23, 2025
1 parent 608b83c commit 10da342
Showing 1 changed file with 13 additions and 10 deletions.
23 changes: 13 additions & 10 deletions internal/collector/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ type Collector struct {
// ref: https://victoriametrics.com/blog/go-sync-pool/
serviceConfigPoolBytes sync.Pool

serviceManagerHandle *mgr.Mgr
serviceManagerHandle *mgr.Mgr
queryAllServicesBuffer []byte
}

func New(config *Config) *Collector {
Expand Down Expand Up @@ -140,6 +141,8 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
},
}

c.queryAllServicesBuffer = make([]byte, 1024*100)

c.info = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, Name, "info"),
"A metric with a constant '1' value labeled with service information",
Expand Down Expand Up @@ -209,7 +212,7 @@ func (c *Collector) Close() error {
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
services, err := c.queryAllServices()
if err != nil {
return fmt.Errorf("failed to query services: %w", err)
return fmt.Errorf("failed to query all services: %w", err)
}

servicesCh := make(chan windows.ENUM_SERVICE_STATUS_PROCESS, len(services))
Expand Down Expand Up @@ -368,16 +371,16 @@ func (c *Collector) queryAllServices() ([]windows.ENUM_SERVICE_STATUS_PROCESS, e
err error
)

buf := make([]byte, 1024*100)

for {
currentBufferSize := uint32(cap(c.queryAllServicesBuffer))

err = windows.EnumServicesStatusEx(
c.serviceManagerHandle.Handle,
windows.SC_STATUS_PROCESS_INFO,
windows.SERVICE_WIN32,
windows.SERVICE_STATE_ALL,
&buf[0],
uint32(len(buf)),
&c.queryAllServicesBuffer[0],
currentBufferSize,
&bytesNeeded,
&servicesReturned,
nil,
Expand All @@ -392,18 +395,18 @@ func (c *Collector) queryAllServices() ([]windows.ENUM_SERVICE_STATUS_PROCESS, e
return nil, err
}

if bytesNeeded <= uint32(len(buf)) {
return nil, err
if bytesNeeded <= currentBufferSize {
return nil, fmt.Errorf("windows.EnumServicesStatusEx reports buffer too small (%d), but buffer is large enough (%d)", currentBufferSize, bytesNeeded)
}

buf = make([]byte, bytesNeeded)
c.queryAllServicesBuffer = make([]byte, bytesNeeded)
}

if servicesReturned == 0 {
return []windows.ENUM_SERVICE_STATUS_PROCESS{}, nil
}

services := unsafe.Slice((*windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&buf[0])), int(servicesReturned))
services := unsafe.Slice((*windows.ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(&c.queryAllServicesBuffer[0])), int(servicesReturned))

return services, nil
}
Expand Down

0 comments on commit 10da342

Please sign in to comment.