Skip to content

Commit fa598ea

Browse files
author
Cliff Jansen
committed
PROTON-1520: C proactor epoll performance. Defer writes until after event batch processed,
defer rearm until after write
1 parent 10df413 commit fa598ea

File tree

1 file changed

+28
-25
lines changed

1 file changed

+28
-25
lines changed

proton-c/src/proactor/epoll.c

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ struct pn_listener_t {
537537

538538

539539
static pn_event_batch_t *pconnection_process(pconnection_t *pc, uint32_t events, bool timeout, bool topup);
540+
static void write_flush(pconnection_t *pc);
540541
static void listener_begin_close(pn_listener_t* l);
541542
static void proactor_add(pcontext_t *ctx);
542543
static bool proactor_remove(pcontext_t *ctx);
@@ -800,9 +801,13 @@ static void pconnection_forced_shutdown(pconnection_t *pc) {
800801
static pn_event_t *pconnection_batch_next(pn_event_batch_t *batch) {
801802
pconnection_t *pc = batch_pconnection(batch);
802803
pn_event_t *e = pn_connection_driver_next_event(&pc->driver);
803-
if (!e && pc->hog_count < HOG_MAX) {
804-
if (pconnection_process(pc, 0, false, true)) {
805-
e = pn_connection_driver_next_event(&pc->driver);
804+
if (!e) {
805+
write_flush(pc); // May generate transport event
806+
e = pn_connection_driver_next_event(&pc->driver);
807+
if (!e && pc->hog_count < HOG_MAX) {
808+
if (pconnection_process(pc, 0, false, true)) {
809+
e = pn_connection_driver_next_event(&pc->driver);
810+
}
806811
}
807812
}
808813
return e;
@@ -903,6 +908,23 @@ static bool pconnection_write(pconnection_t *pc, pn_bytes_t wbuf) {
903908
return true;
904909
}
905910

911+
static void write_flush(pconnection_t *pc) {
912+
if (!pc->write_blocked && !pconnection_wclosed(pc)) {
913+
pn_bytes_t wbuf = pn_connection_driver_write_buffer(&pc->driver);
914+
if (wbuf.size > 0) {
915+
if (!pconnection_write(pc, wbuf)) {
916+
psocket_error(&pc->psocket, errno, pc->disconnected ? "disconnected" : "on write to");
917+
}
918+
}
919+
else {
920+
if (pn_connection_driver_write_closed(&pc->driver)) {
921+
shutdown(pc->psocket.sockfd, SHUT_WR);
922+
pc->write_blocked = true;
923+
}
924+
}
925+
}
926+
}
927+
906928
static void pconnection_connected_lh(pconnection_t *pc);
907929
static void pconnection_maybe_connect_lh(pconnection_t *pc);
908930

@@ -1001,7 +1023,6 @@ static pn_event_batch_t *pconnection_process(pconnection_t *pc, uint32_t events,
10011023
pc->current_arm = 0;
10021024
pc->new_events = 0;
10031025
}
1004-
bool unarmed = (pc->current_arm == 0);
10051026

10061027
if (pc->context.closing && pconnection_is_final(pc)) {
10071028
unlock(&pc->context.mutex);
@@ -1058,36 +1079,17 @@ static pn_event_batch_t *pconnection_process(pconnection_t *pc, uint32_t events,
10581079
tick_required = false;
10591080
}
10601081

1061-
while (!pc->write_blocked && !pconnection_wclosed(pc)) {
1062-
pn_bytes_t wbuf = pn_connection_driver_write_buffer(&pc->driver);
1063-
if (wbuf.size > 0) {
1064-
if (!pconnection_write(pc, wbuf)) {
1065-
psocket_error(&pc->psocket, errno, pc->disconnected ? "disconnected" : "on write to");
1066-
}
1067-
}
1068-
else {
1069-
if (pn_connection_driver_write_closed(&pc->driver)) {
1070-
shutdown(pc->psocket.sockfd, SHUT_WR);
1071-
pc->write_blocked = true;
1072-
}
1073-
else
1074-
break; /* nothing to write until next read/wake/timeout */
1075-
}
1076-
}
1077-
10781082
if (topup) {
10791083
// If there was anything new to topup, we have it by now.
1080-
if (unarmed && pconnection_rearm_check(pc))
1081-
pconnection_rearm(pc);
10821084
return NULL; // caller already owns the batch
10831085
}
10841086

10851087
if (pconnection_has_event(pc)) {
1086-
if (unarmed && pconnection_rearm_check(pc))
1087-
pconnection_rearm(pc);
10881088
return &pc->batch;
10891089
}
10901090

1091+
write_flush(pc);
1092+
10911093
lock(&pc->context.mutex);
10921094
if (pc->context.closing && pconnection_is_final(pc)) {
10931095
unlock(&pc->context.mutex);
@@ -1608,6 +1610,7 @@ pn_proactor_t *pn_proactor() {
16081610

16091611
void pn_proactor_free(pn_proactor_t *p) {
16101612
// No competing threads, not even a pending timer
1613+
p->shutting_down = true;
16111614
close(p->epollfd);
16121615
p->epollfd = -1;
16131616
close(p->eventfd);

0 commit comments

Comments
 (0)