Skip to content

Commit f0efb8a

Browse files
committed
DRA scheduler: populate set of allocated devices only once
The devices which are allocated before starting the allocation always remain allocated. They can be stored once in a set, then each Filter call for the different nodes can reuse that set instead of allocating it anew for each node. goos: linux goarch: amd64 pkg: k8s.io/kubernetes/test/integration/scheduler_perf cpu: Intel(R) Core(TM) i9-7980XE CPU @ 2.60GHz │ before │ after │ │ SchedulingThroughput/Average │ SchedulingThroughput/Average vs base │ PerfScheduling/SchedulingWithResourceClaimTemplateStructured/5000pods_500nodes-36 36.89 ± 2% 54.70 ± 6% +48.26% (p=0.002 n=6) PerfScheduling/SteadyStateClusterResourceClaimTemplateStructured/empty_100nodes-36 105.7 ± 5% 106.4 ± 4% ~ (p=0.970 n=6) PerfScheduling/SteadyStateClusterResourceClaimTemplateStructured/empty_500nodes-36 117.8 ± 3% 120.0 ± 4% ~ (p=0.134 n=6) PerfScheduling/SteadyStateClusterResourceClaimTemplateStructured/half_100nodes-36 119.5 ± 4% 112.5 ± 4% -5.86% (p=0.009 n=6) PerfScheduling/SteadyStateClusterResourceClaimTemplateStructured/half_500nodes-36 63.22 ± 2% 87.13 ± 4% +37.82% (p=0.002 n=6) PerfScheduling/SteadyStateClusterResourceClaimTemplateStructured/full_100nodes-36 109.5 ± 2% 113.4 ± 2% +3.65% (p=0.006 n=6) PerfScheduling/SteadyStateClusterResourceClaimTemplateStructured/full_500nodes-36 27.56 ± 5% 65.55 ± 3% +137.84% (p=0.002 n=6) geomean 72.44 90.81 +25.37%
1 parent f070dd7 commit f0efb8a

File tree

1 file changed

+15
-22
lines changed
  • staging/src/k8s.io/dynamic-resource-allocation/structured

1 file changed

+15
-22
lines changed

staging/src/k8s.io/dynamic-resource-allocation/structured/allocator.go

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import (
4343
type Allocator struct {
4444
adminAccessEnabled bool
4545
claimsToAllocate []*resourceapi.ResourceClaim
46-
allocatedDevices []DeviceID
46+
allocatedDevices sets.Set[DeviceID]
4747
classLister resourcelisters.DeviceClassLister
4848
slices []*resourceapi.ResourceSlice
4949
celCache *CELCache
@@ -66,11 +66,12 @@ func NewAllocator(ctx context.Context,
6666
return &Allocator{
6767
adminAccessEnabled: adminAccessEnabled,
6868
claimsToAllocate: claimsToAllocate,
69-
allocatedDevices: allocatedDevices,
70-
classLister: classLister,
71-
slices: slices,
72-
celCache: celCache,
73-
celMutex: keymutex.NewHashed(0),
69+
// This won't change, so build this set only once.
70+
allocatedDevices: sets.New(allocatedDevices...),
71+
classLister: classLister,
72+
slices: slices,
73+
celCache: celCache,
74+
celMutex: keymutex.NewHashed(0),
7475
}, nil
7576
}
7677

@@ -295,18 +296,10 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node) (finalResult []
295296
// the Allocate call and can be compared in Go.
296297
alloc.deviceMatchesRequest = make(map[matchKey]bool)
297298

298-
// Some of the existing devices are probably already allocated by
299-
// claims...
300-
numAllocated := len(alloc.allocatedDevices)
299+
// We can estimate the size based on what we need to allocate.
300+
alloc.allocatingDevices = make(map[DeviceID]bool, numDevicesTotal)
301301

302-
// Pre-allocating the map avoids growing it later. We can estimate
303-
// the size based on what is already allocated and what we need to
304-
// allocate.
305-
alloc.allocated = make(map[DeviceID]bool, numAllocated+numDevicesTotal)
306-
for _, deviceID := range alloc.allocatedDevices {
307-
alloc.allocated[deviceID] = true
308-
}
309-
alloc.logger.V(6).Info("Gathered information about allocated devices", "numAllocated", numAllocated)
302+
alloc.logger.V(6).Info("Gathered information about devices", "numAllocated", len(alloc.allocatedDevices), "toBeAllocated", numDevicesTotal)
310303

311304
// In practice, there aren't going to be many different CEL
312305
// expressions. Most likely, there is going to be handful of different
@@ -393,7 +386,7 @@ type allocator struct {
393386
deviceMatchesRequest map[matchKey]bool
394387
constraints [][]constraint // one list of constraints per claim
395388
requestData map[requestIndices]requestData // one entry per request
396-
allocated map[DeviceID]bool
389+
allocatingDevices map[DeviceID]bool
397390
result []internalAllocationResult
398391
}
399392

@@ -620,7 +613,7 @@ func (alloc *allocator) allocateOne(r deviceIndices) (bool, error) {
620613
deviceID := DeviceID{Driver: pool.Driver, Pool: pool.Pool, Device: slice.Spec.Devices[deviceIndex].Name}
621614

622615
// Checking for "in use" is cheap and thus gets done first.
623-
if !ptr.Deref(request.AdminAccess, false) && alloc.allocated[deviceID] {
616+
if !ptr.Deref(request.AdminAccess, false) && (alloc.allocatedDevices.Has(deviceID) || alloc.allocatingDevices[deviceID]) {
624617
alloc.logger.V(7).Info("Device in use", "device", deviceID)
625618
continue
626619
}
@@ -775,7 +768,7 @@ func (alloc *allocator) allocateDevice(r deviceIndices, device deviceWithID, mus
775768
claim := alloc.claimsToAllocate[r.claimIndex]
776769
request := &claim.Spec.Devices.Requests[r.requestIndex]
777770
adminAccess := ptr.Deref(request.AdminAccess, false)
778-
if !adminAccess && alloc.allocated[device.id] {
771+
if !adminAccess && (alloc.allocatedDevices.Has(device.id) || alloc.allocatingDevices[device.id]) {
779772
alloc.logger.V(7).Info("Device in use", "device", device.id)
780773
return false, nil, nil
781774
}
@@ -802,7 +795,7 @@ func (alloc *allocator) allocateDevice(r deviceIndices, device deviceWithID, mus
802795
// and record the result.
803796
alloc.logger.V(7).Info("Device allocated", "device", device.id)
804797
if !adminAccess {
805-
alloc.allocated[device.id] = true
798+
alloc.allocatingDevices[device.id] = true
806799
}
807800
result := internalDeviceResult{
808801
request: request.Name,
@@ -820,7 +813,7 @@ func (alloc *allocator) allocateDevice(r deviceIndices, device deviceWithID, mus
820813
constraint.remove(request.Name, device.basic, device.id)
821814
}
822815
if !adminAccess {
823-
alloc.allocated[device.id] = false
816+
alloc.allocatingDevices[device.id] = false
824817
}
825818
// Truncate, but keep the underlying slice.
826819
alloc.result[r.claimIndex].devices = alloc.result[r.claimIndex].devices[:previousNumResults]

0 commit comments

Comments
 (0)