Skip to content

Commit a83d56a

Browse files
ckreibicharr2036
authored andcommitted
Avoid initialization of every calloc'd int in fd_map
libkqueue allocates the the number of available file descriptors for the fd_map array in linux/platform.c to. That limit is vast in Docker, for complicated reasons: 1073741816 The library allocates arrays of that size in several places, but in only one does it then also _initialize_ every member of the array (to -1). Since calloc/mmap are optimized to allocate lazily, this means that only that instance winds up immediately actually using ~4GB in memory. The initialization of the int array uses -1 to indicate that a field isn't in use. The patch changes this to use 0 as unused, simply bumping the stored fds by one upon insert and decrementing by one on access, via helpers.
1 parent fbe0c77 commit a83d56a

1 file changed

Lines changed: 25 additions & 7 deletions

File tree

src/linux/platform.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,28 @@ static int nb_max_fd;
7373
static void
7474
linux_kqueue_free(struct kqueue *kq);
7575

76+
/*
77+
* Helper method for dealing with the fd_map to avoid calling calloc()
78+
* on the entire set of fds at once. fd_map uses 0 to indicate that
79+
* an fd is unused instead of -1, so this function adapts the stored
80+
* file descriptors to match.
81+
*/
82+
static void
83+
fd_map_set(int from, int to)
84+
{
85+
fd_map[from] = to + 1;
86+
}
87+
88+
/*
89+
* Helper method for dealing with the fd_map to avoid calling calloc()
90+
* on the entire set of fds at once. See the comment on fd_map_set().
91+
*/
92+
static int
93+
fd_map_get(int fd)
94+
{
95+
return fd_map[fd] - 1;
96+
}
97+
7698
static void
7799
monitoring_thread_cleanup(UNUSED void *arg)
78100
{
@@ -178,7 +200,7 @@ monitoring_thread_kqueue_cleanup(int signal_fd)
178200
* Signal is received for read side of pipe
179201
* Get FD for write side as it's the kqueue identifier
180202
*/
181-
fd = fd_map[signal_fd];
203+
fd = fd_map_get(signal_fd);
182204
if (fd < 0) {
183205
/* Should not happen */
184206
dbg_printf("fd=%i - not a known FD", fd);
@@ -235,8 +257,6 @@ monitoring_thread_loop(UNUSED void *arg)
235257
int res = 0;
236258
siginfo_t info;
237259

238-
int i;
239-
240260
sigset_t monitoring_sig_set;
241261

242262
/* Set the thread's name to something descriptive so it shows up in gdb,
@@ -263,8 +283,6 @@ monitoring_thread_loop(UNUSED void *arg)
263283
error:
264284
return NULL;
265285
}
266-
for (i = 0; i < nb_max_fd; i++)
267-
fd_map[i] = -1;
268286

269287
fd_use_cnt = calloc(nb_max_fd, sizeof(unsigned int));
270288
if (fd_use_cnt == NULL){
@@ -298,7 +316,7 @@ monitoring_thread_loop(UNUSED void *arg)
298316
*/
299317
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
300318
tracing_mutex_lock(&kq_mtx);
301-
dbg_printf("fd=%i - freeing kqueue due to fd closure (signal) for sfd=%i ", fd_map[info.si_fd], info.si_fd);
319+
dbg_printf("fd=%i - freeing kqueue due to fd closure (signal) for sfd=%i ", fd_map_get(info.si_fd), info.si_fd);
302320

303321
/*
304322
* Release resources used by this kqueue
@@ -535,7 +553,7 @@ linux_kqueue_init(struct kqueue *kq)
535553
}
536554

537555
/* Update pipe FD map */
538-
fd_map[kq->pipefd[0]] = kq->kq_id;
556+
fd_map_set(kq->pipefd[0], kq->kq_id);
539557

540558
/* Mark this id as in use */
541559
fd_use_cnt[kq->kq_id]++;

0 commit comments

Comments
 (0)