Improved performance of distributed read endpoint (#42810)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42808 This is another hot path optimization recommended by Claude Code. I QA'd it with a local osquery perf run. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. ## Testing - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Enhanced performance of the distributed read endpoint by optimizing lock contention management during jitter table access operations. This change reduces latency and improves system responsiveness when handling distributed read requests, particularly benefiting high-concurrency scenarios. The optimization maintains all existing functionality while providing better performance characteristics for read-heavy workloads. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -849,15 +849,22 @@ func (svc *Service) hostRequiresConditionalAccessMicrosoftIngestion(ctx context.
|
||||
}
|
||||
|
||||
func (svc *Service) shouldUpdate(lastUpdated time.Time, interval time.Duration, hostID uint) bool {
|
||||
svc.jitterMu.Lock()
|
||||
defer svc.jitterMu.Unlock()
|
||||
svc.jitterMu.RLock()
|
||||
jh := svc.jitterH[interval]
|
||||
svc.jitterMu.RUnlock()
|
||||
|
||||
if svc.jitterH[interval] == nil {
|
||||
svc.jitterH[interval] = newJitterHashTable(int(int64(svc.config.Osquery.MaxJitterPercent) * int64(interval.Minutes()) / 100.0))
|
||||
svc.logger.DebugContext(context.TODO(), "jitter table created", "bucketCount", svc.jitterH[interval].bucketCount)
|
||||
if jh == nil {
|
||||
svc.jitterMu.Lock()
|
||||
// Double-check after acquiring write lock.
|
||||
if svc.jitterH[interval] == nil {
|
||||
svc.jitterH[interval] = newJitterHashTable(int(int64(svc.config.Osquery.MaxJitterPercent) * int64(interval.Minutes()) / 100.0))
|
||||
svc.logger.DebugContext(context.TODO(), "jitter table created", "bucketCount", svc.jitterH[interval].bucketCount)
|
||||
}
|
||||
jh = svc.jitterH[interval]
|
||||
svc.jitterMu.Unlock()
|
||||
}
|
||||
|
||||
jitter := svc.jitterH[interval].jitterForHost(hostID)
|
||||
jitter := jh.jitterForHost(hostID)
|
||||
cutoff := svc.clock.Now().Add(-(interval + jitter))
|
||||
return lastUpdated.Before(cutoff)
|
||||
}
|
||||
|
||||
@@ -1253,7 +1253,7 @@ func TestHostDetailQueries(t *testing.T) {
|
||||
logger: slog.New(slog.DiscardHandler),
|
||||
config: config.TestConfig(),
|
||||
ds: ds,
|
||||
jitterMu: new(sync.Mutex),
|
||||
jitterMu: new(sync.RWMutex),
|
||||
jitterH: make(map[time.Duration]*jitterHashTable),
|
||||
}
|
||||
|
||||
@@ -2296,7 +2296,7 @@ func TestMDMQueries(t *testing.T) {
|
||||
logger: slog.New(slog.DiscardHandler),
|
||||
config: config.TestConfig(),
|
||||
ds: ds,
|
||||
jitterMu: new(sync.Mutex),
|
||||
jitterMu: new(sync.RWMutex),
|
||||
jitterH: make(map[time.Duration]*jitterHashTable),
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ type Service struct {
|
||||
|
||||
authz *authz.Authorizer
|
||||
|
||||
jitterMu *sync.Mutex
|
||||
jitterMu *sync.RWMutex
|
||||
jitterH map[time.Duration]*jitterHashTable
|
||||
|
||||
geoIP fleet.GeoIP
|
||||
@@ -172,7 +172,7 @@ func NewService(
|
||||
failingPolicySet: failingPolicySet,
|
||||
authz: authorizer,
|
||||
jitterH: make(map[time.Duration]*jitterHashTable),
|
||||
jitterMu: new(sync.Mutex),
|
||||
jitterMu: new(sync.RWMutex),
|
||||
geoIP: geoIP,
|
||||
enrollHostLimiter: enrollHostLimiter,
|
||||
depStorage: depStorage,
|
||||
|
||||
Reference in New Issue
Block a user