mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
epoll: use ilist:generic_list instead of ilist:ilist
ilist:generic_list works faster than ilist:ilist. Here is a beanchmark test to measure performance of epoll_wait, when readyList isn't empty. It shows about 30% better performance with these changes. Benchmark Time(ns) CPU(ns) Iterations Before: BM_EpollAllEvents 46725 46899 14286 After: BM_EpollAllEvents 33167 33300 18919 PiperOrigin-RevId: 240185278 Change-Id: I3e33f9b214db13ab840b91613400525de5b58d18
This commit is contained in:
@@ -1,17 +1,30 @@
|
||||
package(licenses = ["notice"])
|
||||
|
||||
load("//tools/go_generics:defs.bzl", "go_template_instance")
|
||||
load("//tools/go_stateify:defs.bzl", "go_library", "go_test")
|
||||
|
||||
go_template_instance(
|
||||
name = "epoll_list",
|
||||
out = "epoll_list.go",
|
||||
package = "epoll",
|
||||
prefix = "pollEntry",
|
||||
template = "//pkg/ilist:generic_list",
|
||||
types = {
|
||||
"Element": "*pollEntry",
|
||||
"Linker": "*pollEntry",
|
||||
},
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "epoll",
|
||||
srcs = [
|
||||
"epoll.go",
|
||||
"epoll_list.go",
|
||||
"epoll_state.go",
|
||||
],
|
||||
importpath = "gvisor.googlesource.com/gvisor/pkg/sentry/kernel/epoll",
|
||||
visibility = ["//pkg/sentry:internal"],
|
||||
deps = [
|
||||
"//pkg/ilist",
|
||||
"//pkg/refs",
|
||||
"//pkg/sentry/context",
|
||||
"//pkg/sentry/fs",
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"gvisor.googlesource.com/gvisor/pkg/ilist"
|
||||
"gvisor.googlesource.com/gvisor/pkg/refs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/context"
|
||||
"gvisor.googlesource.com/gvisor/pkg/sentry/fs"
|
||||
@@ -70,7 +69,7 @@ type FileIdentifier struct {
|
||||
//
|
||||
// +stateify savable
|
||||
type pollEntry struct {
|
||||
ilist.Entry
|
||||
pollEntryEntry
|
||||
file *refs.WeakRef `state:"manual"`
|
||||
id FileIdentifier `state:"wait"`
|
||||
userData [2]int32
|
||||
@@ -84,7 +83,7 @@ type pollEntry struct {
|
||||
// struct, while state framework currently does not support such
|
||||
// in-struct pointers. Instead, EventPoll will properly set this field
|
||||
// in its loading logic.
|
||||
curList *ilist.List `state:"nosave"`
|
||||
curList *pollEntryList `state:"nosave"`
|
||||
}
|
||||
|
||||
// WeakRefGone implements refs.WeakRefUser.WeakRefGone.
|
||||
@@ -133,9 +132,9 @@ type EventPoll struct {
|
||||
// disabledList -- when the entry is disabled. This happens when
|
||||
// a one-shot entry gets delivered via readEvents().
|
||||
listsMu sync.Mutex `state:"nosave"`
|
||||
readyList ilist.List
|
||||
waitingList ilist.List
|
||||
disabledList ilist.List
|
||||
readyList pollEntryList
|
||||
waitingList pollEntryList
|
||||
disabledList pollEntryList
|
||||
}
|
||||
|
||||
// cycleMu is used to serialize all the cycle checks. This is only used when
|
||||
@@ -189,7 +188,7 @@ func (e *EventPoll) eventsAvailable() bool {
|
||||
e.listsMu.Lock()
|
||||
|
||||
for it := e.readyList.Front(); it != nil; {
|
||||
entry := it.(*pollEntry)
|
||||
entry := it
|
||||
it = it.Next()
|
||||
|
||||
// If the entry is ready, we know 'e' has at least one entry
|
||||
@@ -225,14 +224,14 @@ func (e *EventPoll) Readiness(mask waiter.EventMask) waiter.EventMask {
|
||||
|
||||
// ReadEvents returns up to max available events.
|
||||
func (e *EventPoll) ReadEvents(max int) []Event {
|
||||
var local ilist.List
|
||||
var local pollEntryList
|
||||
var ret []Event
|
||||
|
||||
e.listsMu.Lock()
|
||||
|
||||
// Go through all entries we believe may be ready.
|
||||
for it := e.readyList.Front(); it != nil && len(ret) < max; {
|
||||
entry := it.(*pollEntry)
|
||||
entry := it
|
||||
it = it.Next()
|
||||
|
||||
// Check the entry's readiness. It it's not really ready, we
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
package epoll
|
||||
|
||||
import (
|
||||
"gvisor.googlesource.com/gvisor/pkg/ilist"
|
||||
"gvisor.googlesource.com/gvisor/pkg/refs"
|
||||
"gvisor.googlesource.com/gvisor/pkg/waiter"
|
||||
)
|
||||
@@ -33,18 +32,17 @@ func (e *EventPoll) afterLoad() {
|
||||
e.listsMu.Lock()
|
||||
defer e.listsMu.Unlock()
|
||||
|
||||
for _, ls := range []*ilist.List{&e.waitingList, &e.readyList, &e.disabledList} {
|
||||
for _, ls := range []*pollEntryList{&e.waitingList, &e.readyList, &e.disabledList} {
|
||||
for it := ls.Front(); it != nil; it = it.Next() {
|
||||
it.(*pollEntry).curList = ls
|
||||
it.curList = ls
|
||||
}
|
||||
}
|
||||
|
||||
for it := e.waitingList.Front(); it != nil; it = it.Next() {
|
||||
p := it.(*pollEntry)
|
||||
if p.id.File.Readiness(p.mask) != 0 {
|
||||
e.waitingList.Remove(p)
|
||||
e.readyList.PushBack(p)
|
||||
p.curList = &e.readyList
|
||||
if it.id.File.Readiness(it.mask) != 0 {
|
||||
e.waitingList.Remove(it)
|
||||
e.readyList.PushBack(it)
|
||||
it.curList = &e.readyList
|
||||
e.Notify(waiter.EventIn)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user