aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2019-03-25 14:34:45 +0100
committerLukas Larsson <[email protected]>2019-03-25 16:34:11 +0100
commit7b6c36d65fabd9ba43beb2fa56cc1a17249aac64 (patch)
treebc7a39d4f5d7886cb67bfc1df5a3a69a896dfb8b
parent6907100826bf1956a8dbeb16ba2e736199913d0a (diff)
downloadotp-7b6c36d65fabd9ba43beb2fa56cc1a17249aac64.tar.gz
otp-7b6c36d65fabd9ba43beb2fa56cc1a17249aac64.tar.bz2
otp-7b6c36d65fabd9ba43beb2fa56cc1a17249aac64.zip
erts: Include external msg in need of GC
When many external messages suddenly appear in the mailbox the young gen size is adjusted accordingly but it was immediately shrunk as the data was not counted towards the shrink size. This commit includes the ext dist size in the shrink calculation which means that the decode of the external messages will not trigger as many GCs which means much better performance.
-rw-r--r--erts/emulator/beam/erl_gc.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 9317850d96..67a73e4d57 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -577,7 +577,7 @@ force_reschedule:
}
static ERTS_FORCE_INLINE Uint
-young_gen_usage(Process *p)
+young_gen_usage(Process *p, Uint *ext_msg_usage)
{
Uint hsz;
Eterm *aheap;
@@ -604,7 +604,10 @@ young_gen_usage(Process *p)
if (ERTS_SIG_IS_MSG(mp)
&& mp->data.attached
&& mp->data.attached != ERTS_MSG_COMBINED_HFRAG) {
- hsz += erts_msg_attached_data_size(mp);
+ Uint sz = erts_msg_attached_data_size(mp);
+ if (ERTS_SIG_IS_EXTERNAL_MSG(mp))
+ *ext_msg_usage += sz;
+ hsz += sz;
}
});
}
@@ -676,6 +679,7 @@ garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
{
Uint reclaimed_now = 0;
Uint ygen_usage;
+ Uint ext_msg_usage = 0;
Eterm gc_trace_end_tag;
int reds;
ErtsMonotonicTime start_time;
@@ -698,7 +702,7 @@ garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
return delay_garbage_collection(p, live_hf_end, need, fcalls);
}
- ygen_usage = max_young_gen_usage ? max_young_gen_usage : young_gen_usage(p);
+ ygen_usage = max_young_gen_usage ? max_young_gen_usage : young_gen_usage(p, &ext_msg_usage);
if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
check_for_possibly_long_gc(p, ygen_usage);
@@ -739,7 +743,7 @@ garbage_collect(Process* p, ErlHeapFragment *live_hf_end,
trace_gc(p, am_gc_minor_start, need, THE_NON_VALUE);
}
DTRACE2(gc_minor_start, pidbuf, need);
- reds = minor_collection(p, live_hf_end, need, objv, nobj,
+ reds = minor_collection(p, live_hf_end, need + ext_msg_usage, objv, nobj,
ygen_usage, &reclaimed_now);
DTRACE2(gc_minor_end, pidbuf, reclaimed_now);
if (reds == -1) {
@@ -764,7 +768,7 @@ do_major_collection:
trace_gc(p, am_gc_major_start, need, THE_NON_VALUE);
}
DTRACE2(gc_major_start, pidbuf, need);
- reds = major_collection(p, live_hf_end, need, objv, nobj,
+ reds = major_collection(p, live_hf_end, need + ext_msg_usage, objv, nobj,
ygen_usage, &reclaimed_now);
if (ERTS_SCHEDULER_IS_DIRTY(esdp))
p->flags &= ~(F_DIRTY_MAJOR_GC|F_DIRTY_MINOR_GC);
@@ -1101,6 +1105,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
Eterm* old_htop;
Uint n;
Uint ygen_usage = 0;
+ Uint ext_msg_usage = 0;
struct erl_off_heap_header** prev = NULL;
Sint64 reds;
int hibernated = !!(p->flags & F_HIBERNATED);
@@ -1118,7 +1123,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
p->flags &= ~F_DIRTY_CLA;
else {
Uint size = byte_lit_size/sizeof(Uint);
- ygen_usage = young_gen_usage(p);
+ ygen_usage = young_gen_usage(p, &ext_msg_usage);
if (hibernated)
size = size*2 + 3*ygen_usage;
else
@@ -1130,7 +1135,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals,
}
}
- reds = (Sint64) garbage_collect(p, ERTS_INVALID_HFRAG_PTR, 0,
+ reds = (Sint64) garbage_collect(p, ERTS_INVALID_HFRAG_PTR, ext_msg_usage,
p->arg_reg, p->arity, fcalls,
ygen_usage);
if (ERTS_PROC_IS_EXITING(p)) {
@@ -1348,6 +1353,9 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end,
Eterm *mature = p->abandoned_heap ? p->abandoned_heap : p->heap;
Uint mature_size = p->high_water - mature;
Uint size_before = ygen_usage;
+#ifdef DEBUG
+ Uint debug_tmp = 0;
+#endif
/*
* Check if we have gone past the max heap size limit
@@ -1484,7 +1492,7 @@ minor_collection(Process* p, ErlHeapFragment *live_hf_end,
process from there */
ASSERT(!MAX_HEAP_SIZE_GET(p) ||
!(MAX_HEAP_SIZE_FLAGS_GET(p) & MAX_HEAP_SIZE_KILL) ||
- MAX_HEAP_SIZE_GET(p) > (young_gen_usage(p) +
+ MAX_HEAP_SIZE_GET(p) > (young_gen_usage(p, &debug_tmp) +
(OLD_HEND(p) - OLD_HEAP(p)) +
(HEAP_END(p) - HEAP_TOP(p))));