mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Keep minimal available fd to accelerate fd allocation
Use fd.next to store the iteration start position, which can be used to accelerate allocating new FDs. And adding the corresponding gtest benchmark to measure performance. @tanjianfeng COPYBARA_INTEGRATE_REVIEW=https://github.com/google/gvisor/pull/758 from DarcySail:master 96685ec7886dfe1a64988406831d3bc002b438cc PiperOrigin-RevId: 276351250
This commit is contained in:
@@ -81,6 +81,9 @@ type FDTable struct {
|
||||
// mu protects below.
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
|
||||
// next is start position to find fd.
|
||||
next int32
|
||||
|
||||
// used contains the number of non-nil entries. It must be accessed
|
||||
// atomically. It may be read atomically without holding mu (but not
|
||||
// written).
|
||||
@@ -226,6 +229,11 @@ func (f *FDTable) NewFDs(ctx context.Context, fd int32, files []*fs.File, flags
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
||||
// From f.next to find available fd.
|
||||
if fd < f.next {
|
||||
fd = f.next
|
||||
}
|
||||
|
||||
// Install all entries.
|
||||
for i := fd; i < end && len(fds) < len(files); i++ {
|
||||
if d, _, _ := f.get(i); d == nil {
|
||||
@@ -242,6 +250,11 @@ func (f *FDTable) NewFDs(ctx context.Context, fd int32, files []*fs.File, flags
|
||||
return nil, syscall.EMFILE
|
||||
}
|
||||
|
||||
if fd == f.next {
|
||||
// Update next search start position.
|
||||
f.next = fds[len(fds)-1] + 1
|
||||
}
|
||||
|
||||
return fds, nil
|
||||
}
|
||||
|
||||
@@ -361,6 +374,11 @@ func (f *FDTable) Remove(fd int32) *fs.File {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
||||
// Update current available position.
|
||||
if fd < f.next {
|
||||
f.next = fd
|
||||
}
|
||||
|
||||
orig, _, _ := f.get(fd)
|
||||
if orig != nil {
|
||||
orig.IncRef() // Reference for caller.
|
||||
@@ -377,6 +395,10 @@ func (f *FDTable) RemoveIf(cond func(*fs.File, FDFlags) bool) {
|
||||
f.forEach(func(fd int32, file *fs.File, flags FDFlags) {
|
||||
if cond(file, flags) {
|
||||
f.set(fd, nil, FDFlags{}) // Clear from table.
|
||||
// Update current available position.
|
||||
if fd < f.next {
|
||||
f.next = fd
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -70,6 +70,42 @@ func TestFDTableMany(t *testing.T) {
|
||||
if err := fdTable.NewFDAt(ctx, 1, file, FDFlags{}); err != nil {
|
||||
t.Fatalf("fdTable.NewFDAt(1, r, FDFlags{}): got %v, wanted nil", err)
|
||||
}
|
||||
|
||||
i := int32(2)
|
||||
fdTable.Remove(i)
|
||||
if fds, err := fdTable.NewFDs(ctx, 0, []*fs.File{file}, FDFlags{}); err != nil || fds[0] != i {
|
||||
t.Fatalf("Allocated %v FDs but wanted to allocate %v: %v", i, maxFD, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestFDTableOverLimit(t *testing.T) {
|
||||
runTest(t, func(ctx context.Context, fdTable *FDTable, file *fs.File, _ *limits.LimitSet) {
|
||||
if _, err := fdTable.NewFDs(ctx, maxFD, []*fs.File{file}, FDFlags{}); err == nil {
|
||||
t.Fatalf("fdTable.NewFDs(maxFD, f): got nil, wanted error")
|
||||
}
|
||||
|
||||
if _, err := fdTable.NewFDs(ctx, maxFD-2, []*fs.File{file, file, file}, FDFlags{}); err == nil {
|
||||
t.Fatalf("fdTable.NewFDs(maxFD-2, {f,f,f}): got nil, wanted error")
|
||||
}
|
||||
|
||||
if fds, err := fdTable.NewFDs(ctx, maxFD-3, []*fs.File{file, file, file}, FDFlags{}); err != nil {
|
||||
t.Fatalf("fdTable.NewFDs(maxFD-3, {f,f,f}): got %v, wanted nil", err)
|
||||
} else {
|
||||
for _, fd := range fds {
|
||||
fdTable.Remove(fd)
|
||||
}
|
||||
}
|
||||
|
||||
if fds, err := fdTable.NewFDs(ctx, maxFD-1, []*fs.File{file}, FDFlags{}); err != nil || fds[0] != maxFD-1 {
|
||||
t.Fatalf("fdTable.NewFDAt(1, r, FDFlags{}): got %v, wanted nil", err)
|
||||
}
|
||||
|
||||
if fds, err := fdTable.NewFDs(ctx, 0, []*fs.File{file}, FDFlags{}); err != nil {
|
||||
t.Fatalf("Adding an FD to a resized map: got %v, want nil", err)
|
||||
} else if len(fds) != 1 || fds[0] != 0 {
|
||||
t.Fatalf("Added an FD to a resized map: got %v, want {1}", fds)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user