diff options
author | Sverker Eriksson <[email protected]> | 2015-06-01 19:43:13 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2015-06-15 15:22:12 +0200 |
commit | 7c1ed37b4aa173181c4d45a2108f5eef4c36c41e (patch) | |
tree | 39591f16aaff0f9dd18c9a0424b6ef9e88a1f417 | |
parent | 02d0ce034598297565f2b35ecc3d1af121787f33 (diff) | |
download | otp-7c1ed37b4aa173181c4d45a2108f5eef4c36c41e.tar.gz otp-7c1ed37b4aa173181c4d45a2108f5eef4c36c41e.tar.bz2 otp-7c1ed37b4aa173181c4d45a2108f5eef4c36c41e.zip |
erts: Optimize driver_deliver_term
Try write directly to process heap (as before)
if the term is guaranteed not to contain any
big maps that may break the initial size estimation.
-rw-r--r-- | erts/emulator/beam/io.c | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 07a82b42d2..fb030d61f9 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -5108,12 +5108,16 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len) ErlDrvTermData* ptr; ErlDrvTermData* ptr_end; DECLARE_ESTACK(stack); - Eterm mess = NIL; /* keeps compiler happy */ + Eterm mess; Process* rp = NULL; ErtsHeapFactory factory; ErtsProcLocks rp_locks = 0; struct b2t_states__ b2t; - int scheduler = 1; /* Silence erroneous warning... */ + int scheduler; + int is_heap_need_limited = 1; + + ERTS_UNDEF(mess,NIL); + ERTS_UNDEF(scheduler,1); factory.mode = FACTORY_CLOSED; init_b2t_states(&b2t); @@ -5286,6 +5290,9 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len) need += hsz; ptr += 2; depth++; + if (size > MAP_SMALL_MAP_LIMIT*3) { /* may contain big map */ + is_heap_need_limited = 0; + } break; } case ERL_DRV_MAP: { /* int */ @@ -5293,6 +5300,7 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len) if ((int) ptr[0] < 0) ERTS_DDT_FAIL; if (ptr[0] > MAP_SMALL_MAP_LIMIT) { need += HASHMAP_ESTIMATED_HEAP_SIZE(ptr[0]); + is_heap_need_limited = 0; } else { need += MAP_HEADER_FLATMAP_SZ + 1 + 2*ptr[0]; } @@ -5331,14 +5339,17 @@ driver_deliver_term(Eterm to, ErlDrvTermData* data, int len) goto done; } - - /* We could try to copy directly to destination heap - * if we knew there is no big maps. - - erts_alloc_message_heap(need, &bp, &ohp, rp, &rp_locks); - */ - erts_factory_message_init(&factory, NULL, NULL, - new_message_buffer(need)); + /* Try copy directly to destination heap if we know there are no big maps */ + if (is_heap_need_limited) { + ErlOffHeap *ohp; + ErlHeapFragment* bp; + Eterm* hp = erts_alloc_message_heap(need, &bp, &ohp, rp, &rp_locks); + erts_factory_message_init(&factory, rp, hp, bp); + } + else { + erts_factory_message_init(&factory, NULL, NULL, + new_message_buffer(need)); + } /* * Interpret the instructions and build the term. |