aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2015-06-01 19:43:13 +0200
committerSverker Eriksson <[email protected]>2015-06-15 15:22:12 +0200
commit7c1ed37b4aa173181c4d45a2108f5eef4c36c41e (patch)
tree39591f16aaff0f9dd18c9a0424b6ef9e88a1f417
parent02d0ce034598297565f2b35ecc3d1af121787f33 (diff)
downloadotp-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.c31
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.