Skip to content

Commit 24852b5

Browse files
committed
deps: reduce cpu profiler overhead
* Block SIGPROF when in the epoll_pwait() system call so the event loop doesn't keep waking up on signal delivery. The clock_gettime() system call that libuv does after EINTR is very expensive on virtualized systems. * Replace sched_yield() with nanosleep() in V8's tick event processor thread. The former only yields the CPU when there is another process scheduled on the same CPU. * Fix a bug in the epoll_pwait() system call wrapper in libuv, see libuv/libuv#4. Refs strongloop/strong-agent#3 and strongloop-internal/scrum-cs#37.
1 parent 3a08b7c commit 24852b5

File tree

3 files changed

+14
-19
lines changed

3 files changed

+14
-19
lines changed

deps/uv/src/unix/linux-core.c

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
130130
struct uv__epoll_event e;
131131
ngx_queue_t* q;
132132
uv__io_t* w;
133+
sigset_t set;
133134
uint64_t base;
134135
uint64_t diff;
135136
int nevents;
@@ -138,7 +139,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
138139
int fd;
139140
int op;
140141
int i;
141-
static int no_epoll_wait;
142142

143143
if (loop->nfds == 0) {
144144
assert(ngx_queue_empty(&loop->watcher_queue));
@@ -184,23 +184,15 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
184184
base = loop->time;
185185
count = 48; /* Benchmarks suggest this gives the best throughput. */
186186

187+
sigemptyset(&set);
188+
sigaddset(&set, SIGPROF);
189+
187190
for (;;) {
188-
if (!no_epoll_wait) {
189-
nfds = uv__epoll_wait(loop->backend_fd,
190-
events,
191-
ARRAY_SIZE(events),
192-
timeout);
193-
if (nfds == -1 && errno == ENOSYS) {
194-
no_epoll_wait = 1;
195-
continue;
196-
}
197-
} else {
198-
nfds = uv__epoll_pwait(loop->backend_fd,
199-
events,
200-
ARRAY_SIZE(events),
201-
timeout,
202-
NULL);
203-
}
191+
nfds = uv__epoll_pwait(loop->backend_fd,
192+
events,
193+
ARRAY_SIZE(events),
194+
timeout,
195+
&set);
204196

205197
/* Update loop->time unconditionally. It's tempting to skip the update when
206198
* timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the

deps/uv/src/unix/linux-syscalls.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "linux-syscalls.h"
2323
#include <unistd.h>
24+
#include <signal.h>
2425
#include <sys/syscall.h>
2526
#include <sys/types.h>
2627
#include <errno.h>
@@ -298,7 +299,7 @@ int uv__epoll_pwait(int epfd,
298299
nevents,
299300
timeout,
300301
sigmask,
301-
sizeof(*sigmask));
302+
_NSIG / sizeof(long));
302303
#else
303304
return errno = ENOSYS, -1;
304305
#endif

deps/v8/src/platform-linux.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <sys/syscall.h>
3838
#include <sys/types.h>
3939
#include <stdlib.h>
40+
#include <time.h>
4041

4142
// Ubuntu Dapper requires memory pages to be marked as
4243
// executable. Otherwise, OS raises an exception when executing code
@@ -813,7 +814,8 @@ void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
813814

814815

815816
void Thread::YieldCPU() {
816-
sched_yield();
817+
const timespec delay = { 0, 1 };
818+
nanosleep(&delay, NULL);
817819
}
818820

819821

0 commit comments

Comments
 (0)