aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/external.c
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2018-09-18 15:27:01 +0200
committerLukas Larsson <[email protected]>2019-02-21 16:38:04 +0100
commit0184c2e0438ac42c44d14e92b13e2807e0a670b3 (patch)
treeed3189b7efad20435fd8443279e75e623af36b52 /erts/emulator/beam/external.c
parent45c57256d06b14bae7a4f19978a375e360b609cf (diff)
downloadotp-0184c2e0438ac42c44d14e92b13e2807e0a670b3.tar.gz
otp-0184c2e0438ac42c44d14e92b13e2807e0a670b3.tar.bz2
otp-0184c2e0438ac42c44d14e92b13e2807e0a670b3.zip
erts: Remove a copy of distribution data payload
Before this change the inet driver was in list mode and thus the data from it had to be copied when received by the dist entry. This change puts the tcp port in binary mode and makes the any refc binary created by it be used all the way to the process where it is decoded. Thus eliminating one copy of the entire message payload.
Diffstat (limited to 'erts/emulator/beam/external.c')
-rw-r--r--erts/emulator/beam/external.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 9a66e491f3..4b8040b356 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -640,14 +640,15 @@ erts_make_dist_ext_copy(ErtsDistExternal *edep, Uint xsize)
{
size_t align_sz;
size_t dist_ext_sz;
- size_t ext_sz;
+ size_t ext_sz = 0;
byte *ep;
ErtsDistExternal *new_edep;
dist_ext_sz = ERTS_DIST_EXT_SIZE(edep);
ASSERT(edep->ext_endp && edep->extp);
ASSERT(edep->ext_endp >= edep->extp);
- ext_sz = edep->ext_endp - edep->extp;
+ if (edep->binp == NULL)
+ ext_sz = edep->ext_endp - edep->extp;
align_sz = ERTS_EXTRA_DATA_ALIGN_SZ(dist_ext_sz + ext_sz);
@@ -656,20 +657,36 @@ erts_make_dist_ext_copy(ErtsDistExternal *edep, Uint xsize)
ep = (byte *) new_edep;
sys_memcpy((void *) ep, (void *) edep, dist_ext_sz);
- ep += dist_ext_sz;
if (new_edep->dep)
erts_ref_dist_entry(new_edep->dep);
- new_edep->extp = ep;
- new_edep->ext_endp = ep + ext_sz;
new_edep->heap_size = -1;
- sys_memcpy((void *) ep, (void *) edep->extp, ext_sz);
+
+ if (ext_sz) {
+ ep += dist_ext_sz;
+ new_edep->extp = ep;
+ new_edep->ext_endp = ep + ext_sz;
+ sys_memcpy((void *) ep, (void *) edep->extp, ext_sz);
+ } else {
+ erts_refc_inc(&new_edep->binp->intern.refc, 2);
+ }
return new_edep;
}
+void
+erts_free_dist_ext_copy(ErtsDistExternal *edep)
+{
+ if (edep->dep)
+ erts_deref_dist_entry(edep->dep);
+ if (edep->binp)
+ erts_bin_release(edep->binp);
+ erts_free(ERTS_ALC_T_EXT_TERM_DATA, edep);
+}
+
int
erts_prepare_dist_ext(ErtsDistExternal *edep,
byte *ext,
Uint size,
+ Binary *binp,
DistEntry *dep,
Uint32 conn_id,
ErtsAtomCache *cache)
@@ -685,6 +702,7 @@ erts_prepare_dist_ext(ErtsDistExternal *edep,
ASSERT(dep->flags & DFLAG_UTF8_ATOMS);
+
if ((dep->state != ERTS_DE_STATE_CONNECTED &&
dep->state != ERTS_DE_STATE_PENDING)
|| dep->connection_id != conn_id) {
@@ -697,7 +715,11 @@ erts_prepare_dist_ext(ErtsDistExternal *edep,
ext++;
size--;
}
+
+ edep->heap_size = -1;
edep->ext_endp = ext + size;
+ edep->binp = binp;
+
ep = ext;
if (size < 2)