aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2018-06-20 17:54:24 +0200
committerLukas Larsson <[email protected]>2018-07-16 17:45:09 +0200
commit83445d0de88a1ad15066e6c415b2c2d9aa93d6a1 (patch)
treee10f44d82831ca127e07cb6eb82695c7f62f90e9
parent2e51ef8d76ba0d0b700a673262292f7e63ba9c58 (diff)
downloadotp-83445d0de88a1ad15066e6c415b2c2d9aa93d6a1.tar.gz
otp-83445d0de88a1ad15066e6c415b2c2d9aa93d6a1.tar.bz2
otp-83445d0de88a1ad15066e6c415b2c2d9aa93d6a1.zip
erts: Free udp buffer when getting EAGAIN
Only SCPT should keep the recv buffer when going into select. If UDP does it, it will result in many more memory allocations than there should be which can be very detrimental to performance.
-rw-r--r--erts/emulator/drivers/common/inet_drv.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 5e9afdc5ca..833befefd1 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -1785,6 +1785,7 @@ static void release_buffer(ErlDrvBinary* buf)
#ifdef HAVE_UDP
static ErlDrvBinary* realloc_buffer(ErlDrvBinary* buf, ErlDrvSizeT newsz)
{
+ DEBUGF(("realloc_buffer: %ld -> %ld\r\n", (buf==NULL) ? 0 : buf->orig_size, newsz));
return driver_realloc_binary(buf, newsz);
}
#endif
@@ -12042,15 +12043,11 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
sys_memzero((char *) &other, sizeof(other));
/* udesc->i_buf is only kept between SCTP fragments */
- if (udesc->i_buf == NULL) {
- udesc->i_bufsz = desc->bufsz + len;
- if ((udesc->i_buf = alloc_buffer(udesc->i_bufsz)) == NULL)
- return packet_error(udesc, ENOMEM);
- /* pointer to message start */
- udesc->i_ptr = udesc->i_buf->orig_bytes + len;
- } else {
- ErlDrvBinary* tmp;
+#ifdef HAVE_SCTP
+ if (udesc->i_buf != NULL) {
+ ErlDrvBinary* tmp;
int bufsz;
+ ASSERT(IS_SCTP(desc));
bufsz = desc->bufsz + (udesc->i_ptr - udesc->i_buf->orig_bytes);
if ((tmp = realloc_buffer(udesc->i_buf, bufsz)) == NULL) {
release_buffer(udesc->i_buf);
@@ -12062,6 +12059,15 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
udesc->i_buf = tmp;
udesc->i_bufsz = bufsz;
}
+ } else
+#endif
+ {
+ ASSERT(udesc->i_buf == NULL);
+ udesc->i_bufsz = desc->bufsz + len;
+ if ((udesc->i_buf = alloc_buffer(udesc->i_bufsz)) == NULL)
+ return packet_error(udesc, ENOMEM);
+ /* pointer to message start */
+ udesc->i_ptr = udesc->i_buf->orig_bytes + len;
}
/* Note: On Windows NT, recvfrom() fails if the socket is connected. */
@@ -12120,6 +12126,14 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
) {
sock_select(desc,FD_READ,1);
}
+#ifdef HAVE_SCTP
+ if (!short_recv) {
+#endif
+ release_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
+#ifdef HAVE_SCTP
+ }
+#endif
return count; /* strange, not ready */
}