epoll selector starts with reasonable fd set size (1024) and increases in powers of two when needed. This prevents the selector to allocate large amounts of memory at startup on systems with a high RLIMIT_NOFILE setting (#10194)
This commit is contained in:
parent
23c1ee982e
commit
0229dfd199
2 changed files with 22 additions and 3 deletions
|
|
@ -53,6 +53,7 @@ when hasThreadSupport:
|
|||
SelectorImpl[T] = object
|
||||
epollFD: cint
|
||||
maxFD: int
|
||||
numFD: int
|
||||
fds: ptr SharedArray[SelectorKey[T]]
|
||||
count: int
|
||||
Selector*[T] = ptr SelectorImpl[T]
|
||||
|
|
@ -61,6 +62,7 @@ else:
|
|||
SelectorImpl[T] = object
|
||||
epollFD: cint
|
||||
maxFD: int
|
||||
numFD: int
|
||||
fds: seq[SelectorKey[T]]
|
||||
count: int
|
||||
Selector*[T] = ref SelectorImpl[T]
|
||||
|
|
@ -76,6 +78,8 @@ proc newSelector*[T](): Selector[T] =
|
|||
raiseOsError(osLastError())
|
||||
var maxFD = int(a.rlim_max)
|
||||
doAssert(maxFD > 0)
|
||||
# Start with a reasonable size, checkFd() will grow this on demand
|
||||
const numFD = 1024
|
||||
|
||||
var epollFD = epoll_create(MAX_EPOLL_EVENTS)
|
||||
if epollFD < 0:
|
||||
|
|
@ -85,14 +89,16 @@ proc newSelector*[T](): Selector[T] =
|
|||
result = cast[Selector[T]](allocShared0(sizeof(SelectorImpl[T])))
|
||||
result.epollFD = epollFD
|
||||
result.maxFD = maxFD
|
||||
result.fds = allocSharedArray[SelectorKey[T]](maxFD)
|
||||
result.numFD = numFD
|
||||
result.fds = allocSharedArray[SelectorKey[T]](numFD)
|
||||
else:
|
||||
result = Selector[T]()
|
||||
result.epollFD = epollFD
|
||||
result.maxFD = maxFD
|
||||
result.fds = newSeq[SelectorKey[T]](maxFD)
|
||||
result.numFD = numFD
|
||||
result.fds = newSeq[SelectorKey[T]](numFD)
|
||||
|
||||
for i in 0 ..< maxFD:
|
||||
for i in 0 ..< numFD:
|
||||
result.fds[i].ident = InvalidIdent
|
||||
|
||||
proc close*[T](s: Selector[T]) =
|
||||
|
|
@ -127,6 +133,16 @@ template checkFd(s, f) =
|
|||
# FD if there is too many. -- DP
|
||||
if f >= s.maxFD:
|
||||
raiseIOSelectorsError("Maximum number of descriptors is exhausted!")
|
||||
if f >= s.numFD:
|
||||
var numFD = s.numFD
|
||||
while numFD <= f: numFD *= 2
|
||||
when hasThreadSupport:
|
||||
s.fds = reallocSharedArray(s.fds, numFD)
|
||||
else:
|
||||
s.fds.setLen(numFD)
|
||||
for i in s.numFD ..< numFD:
|
||||
s.fds[i].ident = InvalidIdent
|
||||
s.numFD = numFD
|
||||
|
||||
proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle,
|
||||
events: set[Event], data: T) =
|
||||
|
|
|
|||
|
|
@ -239,6 +239,9 @@ else:
|
|||
proc allocSharedArray[T](nsize: int): ptr SharedArray[T] =
|
||||
result = cast[ptr SharedArray[T]](allocShared0(sizeof(T) * nsize))
|
||||
|
||||
proc reallocSharedArray[T](sa: ptr SharedArray[T], nsize: int): ptr SharedArray[T] =
|
||||
result = cast[ptr SharedArray[T]](reallocShared(sa, sizeof(T) * nsize))
|
||||
|
||||
proc deallocSharedArray[T](sa: ptr SharedArray[T]) =
|
||||
deallocShared(cast[pointer](sa))
|
||||
type
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue