Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: weicao/otp
...
head fork: weicao/otp
Checking mergeability… Don't worry, you can still create the pull request.
  • 1 commit
  • 4 files changed
  • 0 commit comments
  • 1 contributor
Commits on Jul 12, 2012
@weicao Bind port to owner process's scheduler if owner is bound to a scheduler
In network servers like http or proxy, ports which do tcp IO tasks and the
handler process which processes IO packages should be bound to the same
scheduler to reduce the cost of thread switches and synchronization.

This patch is based on pollset_per_scheduler patch, after giving each scheduler
a standalone pollset so that schedulers can poll IO events concurrently,
and binding IO tasks and the handler to the same scheduler, significant performance
improvement can be observed for tcp servers: in our environment, http server
(with keepalive) QPS is increased from 95k to 130k, proxy QPS is increase
from 45k to 105k.
67e98fb
View
4 erts/emulator/beam/erl_port_task.c
@@ -934,7 +934,11 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
ASSERT(pp->sched.taskq->first);
#ifdef ERTS_SMP
+ if(ERTS_PORT_SFLG_BOUND & pp->status) {
+ xrunq = NULL;
+ } else {
xrunq = erts_check_emigration_need(runq, ERTS_PORT_PRIO_LEVEL);
+ }
if (!xrunq) {
#endif
enqueue_port(runq, pp);
View
11 erts/emulator/beam/erl_process.c
@@ -3093,7 +3093,9 @@ immigrate(ErtsRunQueue *c_rq, ErtsMigrationPath *mp)
rq = check_immigration_need(c_rq, mp, prio);
if (rq) {
erts_smp_runq_lock(rq);
- if (prio == ERTS_PORT_PRIO_LEVEL) {
+ if (prio == ERTS_PORT_PRIO_LEVEL &&
+ rq->ports.start &&
+ !(ERTS_PORT_SFLG_BOUND & rq->ports.start->status)) {
Port *prt;
prt = erts_dequeue_port(rq);
if (prt) {
@@ -3275,6 +3277,10 @@ evacuate_run_queue(ErtsRunQueue *rq,
while (prt) {
ErtsRunQueue *prt_rq;
prt = erts_dequeue_port(rq);
+ if(ERTS_PORT_SFLG_BOUND & prt->status) {
+ // simply clear SFLG_BOUND flag after evacuate
+ prt->status &= ~ERTS_PORT_SFLG_BOUND;
+ }
#ifdef ERTS_POLLSET_PER_SCHEDULER
erts_transfer_outstanding_io_tasks(prt, rq, to_rq);
#endif
@@ -3427,7 +3433,8 @@ try_steal_task_from_victim(ErtsRunQueue *rq, int *rq_lockedp, ErtsRunQueue *vrq,
/*
* Check for a runnable port to steal...
*/
- if (vrq->ports.start) {
+ if (vrq->ports.start &&
+ !(ERTS_PORT_SFLG_BOUND & vrq->ports.start->status)) {
ErtsRunQueue *prt_rq;
Port *prt = erts_dequeue_port(vrq);
#ifdef ERTS_POLLSET_PER_SCHEDULER
View
2  erts/emulator/beam/global.h
@@ -731,6 +731,8 @@ do { \
#define ERTS_PORT_SFLG_INVALID ((Uint32) (1 << 14))
/* Last port to terminate halts the emulator */
#define ERTS_PORT_SFLG_HALT ((Uint32) (1 << 15))
+/* Bound port to scheduler */
+#define ERTS_PORT_SFLG_BOUND ((Uint32) (1 << 16))
#ifdef DEBUG
/* Only debug: make sure all flags aren't cleared unintentionally */
#define ERTS_PORT_SFLG_PORT_DEBUG ((Uint32) (1 << 31))
View
18 erts/emulator/beam/io.c
@@ -426,6 +426,24 @@ setup_port(Port* prt, Eterm pid, erts_driver_t *driver,
{
ErtsRunQueue *runq = erts_get_runq_current(NULL);
char *new_name, *old_name;
+
+#ifdef ERTS_SMP
+ Process *rp = NULL;
+ ErtsProcLocks rp_locks = 0;
+
+ rp = erts_pid2proc(NULL, 0, pid, rp_locks);
+ if(rp) {
+ erts_aint32_t state = erts_smp_atomic32_read_nob(&rp->state);
+ if(state & ERTS_PSFLG_BOUND) {
+ ErtsRunQueue *rq = (ErtsRunQueue *) erts_smp_atomic_read_nob(&rp->run_queue);
+ if(rq) {
+ runq = rq;
+ xstatus |= ERTS_PORT_SFLG_BOUND;
+ }
+ }
+ }
+#endif
+
#ifdef DEBUG
/* Make sure the debug flags survives until port is freed */
xstatus |= ERTS_PORT_SFLG_PORT_DEBUG;

No commit comments for this range

Something went wrong with that request. Please try again.