aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2015-06-10 20:59:05 +0200
committerSverker Eriksson <[email protected]>2015-06-15 15:24:16 +0200
commitf5138184479bd16c0ee0a5e583479378451401c8 (patch)
tree85d32701fb3dde71fa74bbbb5c6b0087d7f399be
parent7c1ed37b4aa173181c4d45a2108f5eef4c36c41e (diff)
downloadotp-f5138184479bd16c0ee0a5e583479378451401c8.tar.gz
otp-f5138184479bd16c0ee0a5e583479378451401c8.tar.bz2
otp-f5138184479bd16c0ee0a5e583479378451401c8.zip
erts: Add erts_factory_trim_and_close
-rw-r--r--erts/emulator/beam/erl_message.c25
-rw-r--r--erts/emulator/beam/erl_message.h1
-rw-r--r--erts/emulator/beam/io.c6
3 files changed, 23 insertions, 9 deletions
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 13e084ce10..f806d2c498 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -93,9 +93,6 @@ erts_resize_message_buffer(ErlHeapFragment *bp, Uint size,
#endif
ErlHeapFragment* nbp;
- /* ToDo: Make use of 'used_size' to avoid realloc
- when shrinking just a few words */
-
#ifdef DEBUG
{
Uint off_sz = size < bp->used_size ? size : bp->used_size;
@@ -110,8 +107,10 @@ erts_resize_message_buffer(ErlHeapFragment *bp, Uint size,
}
#endif
- if (size == bp->used_size)
+ if (size >= (bp->used_size - bp->used_size / 16)) {
+ bp->used_size = size;
return bp;
+ }
#ifdef HARD_DEBUG
dbg_brefs = erts_alloc(ERTS_ALC_T_UNDEF, sizeof(Eterm *)*brefs_size);
@@ -1288,6 +1287,24 @@ void erts_factory_close(ErtsHeapFactory* factory)
factory->mode = FACTORY_CLOSED;
}
+void erts_factory_trim_and_close(ErtsHeapFactory* factory,
+ Eterm *brefs, Uint brefs_size)
+{
+ if (factory->mode == FACTORY_HEAP_FRAGS) {
+ ErlHeapFragment* bp = factory->heap_frags;
+ if (bp->next == NULL) {
+ Uint used_sz = factory->hp - bp->mem;
+ ASSERT(used_sz <= bp->alloc_size);
+ factory->heap_frags = erts_resize_message_buffer(bp, used_sz,
+ brefs, brefs_size);
+ factory->mode = FACTORY_CLOSED;
+ return;
+ }
+ /*else we don't trim multi fragmented messages for now */
+ }
+ erts_factory_close(factory);
+}
+
void erts_factory_undo(ErtsHeapFactory* factory)
{
ErlHeapFragment* bp;
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index 39946f2a14..705ba5e506 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -79,6 +79,7 @@ void erts_factory_dummy_init(ErtsHeapFactory*);
Eterm* erts_produce_heap(ErtsHeapFactory*, Uint need, Uint xtra);
Eterm* erts_reserve_heap(ErtsHeapFactory*, Uint need);
void erts_factory_close(ErtsHeapFactory*);
+void erts_factory_trim_and_close(ErtsHeapFactory*,Eterm *brefs, Uint brefs_size);
void erts_factory_undo(ErtsHeapFactory*);
#ifdef CHECK_FOR_HOLES
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index fb030d61f9..23f208c2eb 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1407,12 +1407,8 @@ queue_port_sched_op_reply(Process *rp,
hp += REF_THING_SIZE;
msg = TUPLE2(hp, ref, msg);
- hp += 3;
- /* SVERK: We used to call erts_resize_message_buffer here
- * to maybe realloc message.
- */
- erts_factory_close(factory);
+ erts_factory_trim_and_close(factory, &msg, 1);
erts_queue_message(rp, rp_locksp, factory->heap_frags, msg, NIL);
}