mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-28 20:06:14 +00:00
Further reduce lock contention in LookupVolumeIdsWithFallback
Optimized two loops that were holding RLock for extended periods: Before: - Held RLock during entire loop iteration - Included string parsing and cache lookups - Could block resetVidMap for significant time with large batches After: - Grab vidMap pointer with brief RLock - Release lock immediately - Perform all loop operations on local pointer Impact: - First loop: Cache check on initial volumeIds - Second loop: Double-check after singleflight wait Benefits: - Minimal lock hold time (just pointer copy) - resetVidMap no longer blocked by long loops - Better concurrent performance with large volume ID lists - Still thread-safe (vidMap methods have internal locks) Verified with: go test -race ./weed/wdclient/... (passes)
This commit is contained in:
@@ -128,23 +128,26 @@ func (mc *MasterClient) LookupVolumeIdsWithFallback(ctx context.Context, volumeI
|
||||
|
||||
// Check cache first and parse volume IDs once
|
||||
vidStringToUint := make(map[string]uint32, len(volumeIds))
|
||||
|
||||
// Get stable pointer to vidMap with minimal lock hold time
|
||||
mc.vidMapLock.RLock()
|
||||
vm := mc.vidMap
|
||||
mc.vidMapLock.RUnlock()
|
||||
|
||||
for _, vidString := range volumeIds {
|
||||
vid, err := strconv.ParseUint(vidString, 10, 32)
|
||||
if err != nil {
|
||||
mc.vidMapLock.RUnlock()
|
||||
return nil, fmt.Errorf("invalid volume id %s: %v", vidString, err)
|
||||
}
|
||||
vidStringToUint[vidString] = uint32(vid)
|
||||
|
||||
locations, found := mc.vidMap.GetLocations(uint32(vid))
|
||||
locations, found := vm.GetLocations(uint32(vid))
|
||||
if found && len(locations) > 0 {
|
||||
result[vidString] = locations
|
||||
} else {
|
||||
needsLookup = append(needsLookup, vidString)
|
||||
}
|
||||
}
|
||||
mc.vidMapLock.RUnlock()
|
||||
|
||||
if len(needsLookup) == 0 {
|
||||
return result, nil
|
||||
@@ -160,16 +163,19 @@ func (mc *MasterClient) LookupVolumeIdsWithFallback(ctx context.Context, volumeI
|
||||
stillNeedLookup := make([]string, 0, len(needsLookup))
|
||||
batchResult := make(map[string][]Location)
|
||||
|
||||
// Get stable pointer with minimal lock hold time
|
||||
mc.vidMapLock.RLock()
|
||||
vm := mc.vidMap
|
||||
mc.vidMapLock.RUnlock()
|
||||
|
||||
for _, vidString := range needsLookup {
|
||||
vid := vidStringToUint[vidString] // Use pre-parsed value
|
||||
if locations, found := mc.vidMap.GetLocations(vid); found && len(locations) > 0 {
|
||||
if locations, found := vm.GetLocations(vid); found && len(locations) > 0 {
|
||||
batchResult[vidString] = locations
|
||||
} else {
|
||||
stillNeedLookup = append(stillNeedLookup, vidString)
|
||||
}
|
||||
}
|
||||
mc.vidMapLock.RUnlock()
|
||||
|
||||
if len(stillNeedLookup) == 0 {
|
||||
return batchResult, nil
|
||||
|
||||
Reference in New Issue
Block a user