Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 1 commit
  • 4 files changed
  • 0 comments
  • 1 contributor
Jul 12, 2012
Wei Cao 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
4  erts/emulator/beam/erl_port_task.c
@@ -934,7 +934,11 @@ erts_port_task_execute(ErtsRunQueue *runq, Port **curr_port_pp)
934 934
 	ASSERT(pp->sched.taskq->first);
935 935
 
936 936
 #ifdef ERTS_SMP
  937
+    if(ERTS_PORT_SFLG_BOUND & pp->status) {
  938
+    xrunq = NULL;
  939
+    } else {
937 940
 	xrunq = erts_check_emigration_need(runq, ERTS_PORT_PRIO_LEVEL);
  941
+    }
938 942
 	if (!xrunq) {
939 943
 #endif
940 944
 	    enqueue_port(runq, pp);
11  erts/emulator/beam/erl_process.c
@@ -3093,7 +3093,9 @@ immigrate(ErtsRunQueue *c_rq, ErtsMigrationPath *mp)
3093 3093
 	rq = check_immigration_need(c_rq, mp, prio);
3094 3094
 	if (rq) {
3095 3095
 	    erts_smp_runq_lock(rq);
3096  
-	    if (prio == ERTS_PORT_PRIO_LEVEL) {
  3096
+	    if (prio == ERTS_PORT_PRIO_LEVEL && 
  3097
+            rq->ports.start && 
  3098
+            !(ERTS_PORT_SFLG_BOUND & rq->ports.start->status)) {
3097 3099
 		Port *prt;
3098 3100
 		prt = erts_dequeue_port(rq);
3099 3101
 		if (prt) {
@@ -3275,6 +3277,10 @@ evacuate_run_queue(ErtsRunQueue *rq,
3275 3277
 	while (prt) {
3276 3278
 	    ErtsRunQueue *prt_rq;
3277 3279
 	    prt = erts_dequeue_port(rq);
  3280
+	    if(ERTS_PORT_SFLG_BOUND & prt->status) {
  3281
+	        // simply clear SFLG_BOUND flag after evacuate
  3282
+	        prt->status &= ~ERTS_PORT_SFLG_BOUND;
  3283
+	    }
3278 3284
 #ifdef ERTS_POLLSET_PER_SCHEDULER
3279 3285
 	    erts_transfer_outstanding_io_tasks(prt, rq, to_rq);
3280 3286
 #endif
@@ -3427,7 +3433,8 @@ try_steal_task_from_victim(ErtsRunQueue *rq, int *rq_lockedp, ErtsRunQueue *vrq,
3427 3433
     /*
3428 3434
      * Check for a runnable port to steal...
3429 3435
      */
3430  
-    if (vrq->ports.start) {
  3436
+    if (vrq->ports.start && 
  3437
+        !(ERTS_PORT_SFLG_BOUND & vrq->ports.start->status)) {
3431 3438
 	ErtsRunQueue *prt_rq;
3432 3439
 	Port *prt = erts_dequeue_port(vrq);
3433 3440
 #ifdef ERTS_POLLSET_PER_SCHEDULER
2  erts/emulator/beam/global.h
@@ -731,6 +731,8 @@ do {									\
731 731
 #define ERTS_PORT_SFLG_INVALID		((Uint32) (1 << 14))
732 732
 /* Last port to terminate halts the emulator */
733 733
 #define ERTS_PORT_SFLG_HALT		((Uint32) (1 << 15))
  734
+/* Bound port to scheduler */
  735
+#define ERTS_PORT_SFLG_BOUND    ((Uint32) (1 << 16))
734 736
 #ifdef DEBUG
735 737
 /* Only debug: make sure all flags aren't cleared unintentionally */
736 738
 #define ERTS_PORT_SFLG_PORT_DEBUG	((Uint32) (1 << 31))
18  erts/emulator/beam/io.c
@@ -426,6 +426,24 @@ setup_port(Port* prt, Eterm pid, erts_driver_t *driver,
426 426
 {
427 427
     ErtsRunQueue *runq = erts_get_runq_current(NULL);
428 428
     char *new_name, *old_name;
  429
+
  430
+#ifdef ERTS_SMP
  431
+    Process *rp = NULL;
  432
+    ErtsProcLocks rp_locks = 0;
  433
+
  434
+    rp = erts_pid2proc(NULL, 0, pid, rp_locks);
  435
+    if(rp) {
  436
+        erts_aint32_t state = erts_smp_atomic32_read_nob(&rp->state);
  437
+        if(state & ERTS_PSFLG_BOUND) {
  438
+            ErtsRunQueue *rq = (ErtsRunQueue *) erts_smp_atomic_read_nob(&rp->run_queue);
  439
+            if(rq) {
  440
+                runq = rq;
  441
+                xstatus |= ERTS_PORT_SFLG_BOUND;
  442
+            }
  443
+        }
  444
+    }
  445
+#endif
  446
+
429 447
 #ifdef DEBUG
430 448
     /* Make sure the debug flags survives until port is freed */
431 449
     xstatus |= ERTS_PORT_SFLG_PORT_DEBUG;

No commit comments for this range

Something went wrong with that request. Please try again.