aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/erl_nif.c
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2016-02-18 13:52:54 +0100
committerLukas Larsson <[email protected]>2016-04-07 09:54:14 +0200
commit57551877d85ad7659201235e27498be42809fefb (patch)
treed510785967a851f39150331f81da2b3b33b4b87f /erts/emulator/beam/erl_nif.c
parent3f190b62031783ad4fc9bb1fb91703a1b1b40ad7 (diff)
downloadotp-57551877d85ad7659201235e27498be42809fefb.tar.gz
otp-57551877d85ad7659201235e27498be42809fefb.tar.bz2
otp-57551877d85ad7659201235e27498be42809fefb.zip
erts: Add enif_send with NULL as msg env
This is an optimization for reducing the number of heap fragments allocated when sending a message where the majority of the message payload is on the sending process' heap.
Diffstat (limited to 'erts/emulator/beam/erl_nif.c')
-rw-r--r--erts/emulator/beam/erl_nif.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index d3030070b7..1012ced44b 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -312,7 +312,6 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
Process* rp;
Process* c_p;
ErtsMessage *mp;
- ErlHeapFragment* frags;
Eterm receiver = to_pid->pid;
int flush_me = 0;
int scheduler = erts_get_scheduler_id() != 0;
@@ -340,25 +339,32 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
ASSERT(env == NULL || receiver != c_p->common.id);
return 0;
}
- flush_env(msg_env);
- frags = menv->env.heap_frag;
- ASSERT(frags == MBUF(&menv->phony_proc));
- if (frags != NULL) {
- /* Move all offheap's from phony proc to the first fragment.
- Quick and dirty... */
- ASSERT(!is_offheap(&frags->off_heap));
- frags->off_heap = MSO(&menv->phony_proc);
- clear_offheap(&MSO(&menv->phony_proc));
- menv->env.heap_frag = NULL;
- MBUF(&menv->phony_proc) = NULL;
+ if (menv) {
+ flush_env(msg_env);
+ mp = erts_alloc_message(0, NULL);
+ mp->data.heap_frag = menv->env.heap_frag;
+ ASSERT(mp->data.heap_frag == MBUF(&menv->phony_proc));
+ if (mp->data.heap_frag != NULL) {
+ /* Move all offheap's from phony proc to the first fragment.
+ Quick and dirty... */
+ ASSERT(!is_offheap(&mp->data.heap_frag->off_heap));
+ mp->data.heap_frag->off_heap = MSO(&menv->phony_proc);
+ clear_offheap(&MSO(&menv->phony_proc));
+ menv->env.heap_frag = NULL;
+ MBUF(&menv->phony_proc) = NULL;
+ }
+ ASSERT(!is_offheap(&MSO(&menv->phony_proc)));
+ } else {
+ Uint sz = size_object(msg);
+ Eterm *hp;
+ mp = erts_alloc_message(sz, &hp);
+ msg = copy_struct(msg, sz, &hp, &mp->hfrag.off_heap);
+ ASSERT(hp == mp->hfrag.mem+mp->hfrag.used_size);
}
- ASSERT(!is_offheap(&MSO(&menv->phony_proc)));
if (flush_me) {
flush_env(env); /* Needed for ERTS_HOLE_CHECK */
}
- mp = erts_alloc_message(0, NULL);
- mp->data.heap_frag = frags;
erts_queue_message(rp, &rp_locks, mp, msg, am_undefined);
if (c_p == rp)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;