Skip to content

Commit 4b5faab

Browse files
committed
Fix the poor performance in network writing
The poor performance is hit when there is only one active port with a big packet (> 64k bytes) to write. The network driver will split the packet into 32k chunks, and only send the first chunk before returning RD_PEND. When N_wait checks for signals from this port, it sees no signal (write is not done yet), and thus the wait time is doubled, and OS_Wait is called. In OS_Wait, default Poll_Default is called, which goes through all pending requests for the device. Because the packet is so big, after a second "write", the packet is still not sent completely, and the status remains the same: DR_PEND, which causes Poll_Default mistakenly thinks the device is inactive, and then OS_Wait starts waiting with the doubled wait time. The wait time could get doubled further until its max if the packet is quite big. The fix is in two folds: 1. Introduce a new flag RRF_ACTIVE, to mark the request as active in case that partial data is written 2. Modify Poll_Default funcntion to check RRF_ACTIVE in addition to the current DR_DONE/DR_ERROR. So when the data is partial written, Poll_Default will return "TRUE", which causes OS_Wait to return immediately, no matter how long the "wait time" is.
1 parent 1320682 commit 4b5faab

File tree

3 files changed

+10
-4
lines changed

3 files changed

+10
-4
lines changed

src/include/reb-device.h

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ enum {
9393
RRF_PENDING, // Request is attached to pending list
9494
RRF_ALLOC, // Request is allocated, not a temp on stack
9595
RRF_WIDE, // Wide char IO
96+
RRF_ACTIVE, // Port is active, even no new events yet
9697
};
9798

9899
// REBOL Device Errors:

src/os/dev-net.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ static REBOOL Nonblocking_Mode(SOCKET sock)
460460
Signal_Device(sock, EVT_WROTE);
461461
return DR_DONE;
462462
}
463+
SET_FLAG(sock->flags, RRF_ACTIVE); /* notify OS_WAIT of activity */
463464
return DR_PEND;
464465
}
465466
// if (result < 0) ...
@@ -612,7 +613,6 @@ static REBOOL Nonblocking_Mode(SOCKET sock)
612613
return DR_PEND;
613614
}
614615

615-
616616
/***********************************************************************
617617
**
618618
** Command Dispatch Table (RDC_ enum order)

src/os/host-device.c

+8-3
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,10 @@ static int Poll_Default(REBDEV *dev)
102102
for (req = *prior; req; req = *prior) {
103103

104104
// Call command again:
105-
if (req->command < RDC_MAX)
105+
if (req->command < RDC_MAX) {
106+
CLR_FLAG(req->flags, RRF_ACTIVE);
106107
result = dev->commands[req->command](req);
107-
else {
108+
} else {
108109
result = -1; // invalid command, remove it
109110
req->error = ((REBCNT)-1);
110111
}
@@ -115,8 +116,12 @@ static int Poll_Default(REBDEV *dev)
115116
req->next = 0;
116117
CLR_FLAG(req->flags, RRF_PENDING);
117118
change = TRUE;
119+
} else {
120+
prior = &req->next;
121+
if (GET_FLAG(req->flags, RRF_ACTIVE)) {
122+
change = TRUE;
123+
}
118124
}
119-
else prior = &req->next;
120125
}
121126

122127
return change;

0 commit comments

Comments
 (0)