mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +00:00
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:
committed by
Andreas Rumpf
parent
23c1ee982e
commit
0229dfd199
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user