From 6fd44e63eadc4d167a0db9178ff200e51c3231c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Thu, 10 Dec 2009 19:59:24 +0100 Subject: Improve binary garbage collection The garbage collector in r13b03 is too aggressive in some cases. This commit raises the level of default initial allowed binary garbage (virtual heap for binaries) before collecting from 233 words to 46368 words (181 kB on 32-bit). A new option, min_bin_vheap_size, has been added to spawn_opt, system_flag and process_flag can be used to change the default values. The option can also be used with system_info and process_info to inspect the values. For symmetry the option min_heap_size has been added to the above functions where it was previously missing. Add testcases for min_bin_vheap_size and min_heap_size for functions process_flag/2, process_info/2, system_info/2 and spawn_opt/2. --- erts/emulator/beam/atom.names | 1 + erts/emulator/beam/bif.c | 62 +++++++++++++++++++++++++++++--- erts/emulator/beam/erl_bif_info.c | 74 +++++++++++++++++++++++++++++++-------- erts/emulator/beam/erl_gc.c | 46 +++++++++++++++++------- erts/emulator/beam/erl_init.c | 7 ++-- erts/emulator/beam/erl_process.c | 27 +++++++------- erts/emulator/beam/erl_process.h | 6 ++-- erts/emulator/beam/erl_vm.h | 4 ++- 8 files changed, 179 insertions(+), 48 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index 3ce26c4a7a..57c8b08223 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -303,6 +303,7 @@ atom messages atom meta atom meta_match_spec atom min_heap_size +atom min_bin_vheap_size atom minor_version atom Minus='-' atom module diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 74b231d56d..a6668d5665 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -807,11 +807,12 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1) /* * Store default values for options. */ - so.flags = SPO_USE_ARGS; - so.min_heap_size = H_MIN_SIZE; - so.priority = PRIORITY_NORMAL; - so.max_gen_gcs = (Uint16) erts_smp_atomic_read(&erts_max_gen_gcs); - so.scheduler = 0; + so.flags = SPO_USE_ARGS; + so.min_heap_size = H_MIN_SIZE; + so.min_vheap_size = BIN_VH_MIN_SIZE; + so.priority = PRIORITY_NORMAL; + so.max_gen_gcs = (Uint16) erts_smp_atomic_read(&erts_max_gen_gcs); + so.scheduler = 0; /* * Walk through the option list. @@ -850,6 +851,15 @@ BIF_RETTYPE spawn_opt_1(BIF_ALIST_1) } else { so.min_heap_size = erts_next_heap_size(min_heap_size, 0); } + } else if (arg == am_min_bin_vheap_size && is_small(val)) { + Sint min_vheap_size = signed_val(val); + if (min_vheap_size < 0) { + goto error; + } else if (min_vheap_size < BIN_VH_MIN_SIZE) { + so.min_vheap_size = BIN_VH_MIN_SIZE; + } else { + so.min_vheap_size = erts_next_heap_size(min_vheap_size, 0); + } } else if (arg == am_fullsweep_after && is_small(val)) { Sint max_gen_gcs = signed_val(val); if (max_gen_gcs < 0) { @@ -1485,6 +1495,23 @@ BIF_RETTYPE process_flag_2(BIF_ALIST_2) } BIF_RET(old_value); } + else if (BIF_ARG_1 == am_min_bin_vheap_size) { + Sint i; + if (!is_small(BIF_ARG_2)) { + goto error; + } + i = signed_val(BIF_ARG_2); + if (i < 0) { + goto error; + } + old_value = make_small(BIF_P->min_vheap_size); + if (i < BIN_VH_MIN_SIZE) { + BIF_P->min_vheap_size = BIN_VH_MIN_SIZE; + } else { + BIF_P->min_vheap_size = erts_next_heap_size(i, 0); + } + BIF_RET(old_value); + } else if (BIF_ARG_1 == am_sensitive) { Uint is_sensitive; if (BIF_ARG_2 == am_true) { @@ -3736,10 +3763,35 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2) BIF_RET(make_small(oval)); } else if (BIF_ARG_1 == am_min_heap_size) { int oval = H_MIN_SIZE; + if (!is_small(BIF_ARG_2) || (n = signed_val(BIF_ARG_2)) < 0) { goto error; } + + erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); + erts_smp_block_system(0); + H_MIN_SIZE = erts_next_heap_size(n, 0); + + erts_smp_release_system(); + erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); + + BIF_RET(make_small(oval)); + } else if (BIF_ARG_1 == am_min_bin_vheap_size) { + int oval = BIN_VH_MIN_SIZE; + + if (!is_small(BIF_ARG_2) || (n = signed_val(BIF_ARG_2)) < 0) { + goto error; + } + + erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); + erts_smp_block_system(0); + + BIN_VH_MIN_SIZE = erts_next_heap_size(n, 0); + + erts_smp_release_system(); + erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); + BIF_RET(make_small(oval)); } else if (BIF_ARG_1 == am_display_items) { int oval = display_items; diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index b2f81b6861..5ff1f794df 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -543,6 +543,8 @@ static Eterm pi_args[] = { am_last_calls, am_total_heap_size, am_suspending, + am_min_heap_size, + am_min_bin_vheap_size, #ifdef HYBRID am_message_binary #endif @@ -589,8 +591,10 @@ pi_arg2ix(Eterm arg) case am_last_calls: return 24; case am_total_heap_size: return 25; case am_suspending: return 26; + case am_min_heap_size: return 27; + case am_min_bin_vheap_size: return 28; #ifdef HYBRID - case am_message_binary: return 27; + case am_message_binary: return 29; #endif default: return -1; } @@ -1355,6 +1359,30 @@ process_info_aux(Process *BIF_P, break; } + case am_fullsweep_after: { + Uint hsz = 3; + (void) erts_bld_uint(NULL, &hsz, MAX_GEN_GCS(rp)); + hp = HAlloc(BIF_P, hsz); + res = erts_bld_uint(&hp, NULL, MAX_GEN_GCS(rp)); + break; + } + + case am_min_heap_size: { + Uint hsz = 3; + (void) erts_bld_uint(NULL, &hsz, MIN_HEAP_SIZE(rp)); + hp = HAlloc(BIF_P, hsz); + res = erts_bld_uint(&hp, NULL, MIN_HEAP_SIZE(rp)); + break; + } + + case am_min_bin_vheap_size: { + Uint hsz = 3; + (void) erts_bld_uint(NULL, &hsz, MIN_VHEAP_SIZE(rp)); + hp = HAlloc(BIF_P, hsz); + res = erts_bld_uint(&hp, NULL, MIN_VHEAP_SIZE(rp)); + break; + } + case am_total_heap_size: { ErlMessage *mp; Uint total_heap_size; @@ -1433,15 +1461,17 @@ process_info_aux(Process *BIF_P, DECL_AM(minor_gcs); Eterm t; - hp = HAlloc(BIF_P, 3+2+3+2+3); - t = TUPLE2(hp, AM_minor_gcs, make_small(GEN_GCS(rp))); - hp += 3; - res = CONS(hp, t, NIL); - hp += 2; - t = TUPLE2(hp, am_fullsweep_after, make_small(MAX_GEN_GCS(rp))); - hp += 3; - res = CONS(hp, t, res); - hp += 2; + hp = HAlloc(BIF_P, 3+2 + 3+2 + 3+2 + 3+2 + 3); /* last "3" is for outside tuple */ + + t = TUPLE2(hp, AM_minor_gcs, make_small(GEN_GCS(rp))); hp += 3; + res = CONS(hp, t, NIL); hp += 2; + t = TUPLE2(hp, am_fullsweep_after, make_small(MAX_GEN_GCS(rp))); hp += 3; + res = CONS(hp, t, res); hp += 2; + + t = TUPLE2(hp, am_min_heap_size, make_small(MIN_HEAP_SIZE(rp))); hp += 3; + res = CONS(hp, t, res); hp += 2; + t = TUPLE2(hp, am_min_bin_vheap_size, make_small(MIN_VHEAP_SIZE(rp))); hp += 3; + res = CONS(hp, t, res); hp += 2; break; } @@ -1897,16 +1927,32 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1) BIF_RET(res); } else if (BIF_ARG_1 == am_garbage_collection){ Uint val = (Uint) erts_smp_atomic_read(&erts_max_gen_gcs); - hp = HAlloc(BIF_P, 3+2); - res = TUPLE2(hp, am_fullsweep_after, make_small(val)); - hp += 3; - res = CONS(hp, res, NIL); + Eterm tup; + hp = HAlloc(BIF_P, 3+2 + 3+2 + 3+2); + + tup = TUPLE2(hp, am_fullsweep_after, make_small(val)); hp += 3; + res = CONS(hp, tup, NIL); hp += 2; + + tup = TUPLE2(hp, am_min_heap_size, make_small(H_MIN_SIZE)); hp += 3; + res = CONS(hp, tup, res); hp += 2; + + tup = TUPLE2(hp, am_min_bin_vheap_size, make_small(BIN_VH_MIN_SIZE)); hp += 3; + res = CONS(hp, tup, res); hp += 2; + BIF_RET(res); } else if (BIF_ARG_1 == am_fullsweep_after){ Uint val = (Uint) erts_smp_atomic_read(&erts_max_gen_gcs); hp = HAlloc(BIF_P, 3); res = TUPLE2(hp, am_fullsweep_after, make_small(val)); BIF_RET(res); + } else if (BIF_ARG_1 == am_min_heap_size) { + hp = HAlloc(BIF_P, 3); + res = TUPLE2(hp, am_min_heap_size,make_small(H_MIN_SIZE)); + BIF_RET(res); + } else if (BIF_ARG_1 == am_min_bin_vheap_size) { + hp = HAlloc(BIF_P, 3); + res = TUPLE2(hp, am_min_bin_vheap_size,make_small(BIN_VH_MIN_SIZE)); + BIF_RET(res); } else if (BIF_ARG_1 == am_process_count) { BIF_RET(make_small(erts_process_count())); } else if (BIF_ARG_1 == am_process_limit) { diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 363f956b58..e9bf37a173 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -2031,23 +2031,45 @@ shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj) } static Uint -next_vheap_size(Uint vheap, Uint vheap_sz) { - if (vheap < H_MIN_SIZE) { - return H_MIN_SIZE; - } +do_next_vheap_size(Uint vheap, Uint vheap_sz) { + + /* grow + * + * vheap_sz ====================== + * + * vheap 75% + grow + * ---------------------- + * + * vheap 25 - 75% same + * ---------------------- + * + * vheap ~ - 25% shrink + * + * ---------------------- + */ - /* grow */ - if (vheap > vheap_sz) { - return erts_next_heap_size(2*vheap, 0); + if (vheap > (Uint) (vheap_sz*3/4)) { + + while(vheap > (Uint) (vheap_sz*3/4)) { + vheap_sz = vheap_sz*2; + } + + return erts_next_heap_size(vheap_sz, 0); } - /* shrink */ - if ( vheap < vheap_sz/2) { - return (Uint)vheap_sz*3/4; + + if (vheap < (Uint) (vheap_sz/4)) { + return erts_next_heap_size((Uint) (vheap_sz / 2), 0); } return vheap_sz; + } +static Uint +next_vheap_size(Process* p, Uint vheap, Uint vheap_sz) { + vheap_sz = do_next_vheap_size(vheap, vheap_sz); + return vheap_sz < p->min_vheap_size ? p->min_vheap_size : vheap_sz; +} static void sweep_proc_externals(Process *p, int fullsweep) @@ -2250,8 +2272,8 @@ sweep_proc_bins(Process *p, int fullsweep) FLAGS(p) |= F_NEED_FULLSWEEP; } - BIN_VHEAP_SZ(p) = next_vheap_size(bin_vheap, BIN_VHEAP_SZ(p)); - BIN_OLD_VHEAP_SZ(p) = next_vheap_size(BIN_OLD_VHEAP(p), BIN_OLD_VHEAP_SZ(p)); + BIN_VHEAP_SZ(p) = next_vheap_size(p, bin_vheap, BIN_VHEAP_SZ(p)); + BIN_OLD_VHEAP_SZ(p) = next_vheap_size(p, BIN_OLD_VHEAP(p), BIN_OLD_VHEAP_SZ(p)); MSO(p).overhead = bin_vheap; /* diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 8afd349b85..5d2d119b14 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -84,9 +84,10 @@ int erts_use_sender_punish; * Configurable parameters. */ -Uint display_items; /* no of items to display in traces etc */ +Uint display_items; /* no of items to display in traces etc */ Uint display_loads; /* print info about loaded modules */ int H_MIN_SIZE; /* The minimum heap grain */ +int BIN_VH_MIN_SIZE; /* The minimum binary virtual*/ Uint32 erts_debug_flags; /* Debug flags. */ #ifdef ERTS_OPCODE_COUNTER_SUPPORT @@ -252,7 +253,8 @@ erl_init(void) no_schedulers, no_schedulers_online); - H_MIN_SIZE = erts_next_heap_size(H_MIN_SIZE, 0); + H_MIN_SIZE = erts_next_heap_size(H_MIN_SIZE, 0); + BIN_VH_MIN_SIZE = erts_next_heap_size(BIN_VH_MIN_SIZE, 0); erts_init_trace(); erts_init_binary(); @@ -604,6 +606,7 @@ early_init(int *argc, char **argv) /* erts_async_max_threads = 0; erts_async_thread_suggested_stack_size = ERTS_ASYNC_THREAD_MIN_STACK_SIZE; H_MIN_SIZE = H_DEFAULT_SIZE; + BIN_VH_MIN_SIZE = VH_DEFAULT_SIZE; erts_initialized = 0; diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index a4afe0574f..ed907f05de 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -6272,7 +6272,7 @@ Process *schedule(Process *p, int calls) erts_check_my_tracer_proc(p); #endif - if ((FLAGS(p) & F_FORCE_GC) || (MSO(p).overhead >= BIN_VHEAP_SZ(p))) { + if ((FLAGS(p) & F_FORCE_GC) || (MSO(p).overhead > BIN_VHEAP_SZ(p))) { reds -= erts_garbage_collect(p, 0, p->arg_reg, p->arity); if (reds < 0) { reds = 1; @@ -6683,13 +6683,15 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). * noone except us has access to the process. */ if (so->flags & SPO_USE_ARGS) { - p->min_heap_size = so->min_heap_size; - p->prio = so->priority; - p->max_gen_gcs = so->max_gen_gcs; + p->min_heap_size = so->min_heap_size; + p->min_vheap_size = so->min_vheap_size; + p->prio = so->priority; + p->max_gen_gcs = so->max_gen_gcs; } else { - p->min_heap_size = H_MIN_SIZE; - p->prio = PRIORITY_NORMAL; - p->max_gen_gcs = (Uint16) erts_smp_atomic_read(&erts_max_gen_gcs); + p->min_heap_size = H_MIN_SIZE; + p->min_vheap_size = BIN_VH_MIN_SIZE; + p->prio = PRIORITY_NORMAL; + p->max_gen_gcs = (Uint16) erts_smp_atomic_read(&erts_max_gen_gcs); } p->skipped = 0; ASSERT(p->min_heap_size == erts_next_heap_size(p->min_heap_size, 0)); @@ -6736,9 +6738,9 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->heap_sz = sz; p->catches = 0; - p->bin_vheap_sz = H_MIN_SIZE; - p->bin_old_vheap_sz = H_MIN_SIZE; - p->bin_old_vheap = 0; + p->bin_vheap_sz = p->min_vheap_size; + p->bin_old_vheap_sz = p->min_vheap_size; + p->bin_old_vheap = 0; /* No need to initialize p->fcalls. */ @@ -6969,6 +6971,7 @@ void erts_init_empty_process(Process *p) p->gen_gcs = 0; p->max_gen_gcs = 0; p->min_heap_size = 0; + p->min_vheap_size = 0; p->status = P_RUNABLE; p->gcstatus = P_RUNABLE; p->rstatus = P_RUNABLE; @@ -6985,8 +6988,8 @@ void erts_init_empty_process(Process *p) p->ftrace = NIL; p->fcalls = 0; - p->bin_vheap_sz=H_MIN_SIZE; - p->bin_old_vheap_sz=H_MIN_SIZE; + p->bin_vheap_sz = BIN_VH_MIN_SIZE; + p->bin_old_vheap_sz = BIN_VH_MIN_SIZE; p->bin_old_vheap = 0; #ifdef ERTS_SMP p->u.ptimer = NULL; diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 1f841b2113..f58b6932b3 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -477,6 +477,7 @@ struct ErtsPendingSuspend_ { # define MSO(p) (p)->off_heap # define MIN_HEAP_SIZE(p) (p)->min_heap_size +# define MIN_VHEAP_SIZE(p) (p)->min_vheap_size # define BIN_VHEAP_SZ(p) (p)->bin_vheap_sz # define BIN_OLD_VHEAP_SZ(p) (p)->bin_old_vheap_sz # define BIN_OLD_VHEAP(p) (p)->bin_old_vheap @@ -495,6 +496,7 @@ struct process { Eterm* hend; /* Heap end */ Uint heap_sz; /* Size of heap in words */ Uint min_heap_size; /* Minimum size of heap (in words). */ + Uint min_vheap_size; /* Minimum size of virtual heap (in words). */ #if !defined(NO_FPE_SIGNALS) volatile unsigned long fp_exception; @@ -730,8 +732,8 @@ typedef struct { * The following items are only initialized if the SPO_USE_ARGS flag is set. */ Uint min_heap_size; /* Minimum heap size (must be a valued returned - * from next_heap_size()). - */ + * from next_heap_size()). */ + Uint min_vheap_size; /* Minimum virtual heap size */ int priority; /* Priority for process. */ Uint16 max_gen_gcs; /* Maximum number of gen GCs before fullsweep. */ int scheduler; diff --git a/erts/emulator/beam/erl_vm.h b/erts/emulator/beam/erl_vm.h index d8d6246cfd..5b0d3c2bfa 100644 --- a/erts/emulator/beam/erl_vm.h +++ b/erts/emulator/beam/erl_vm.h @@ -57,7 +57,8 @@ #define INPUT_REDUCTIONS (2 * CONTEXT_REDS) -#define H_DEFAULT_SIZE 233 /* default (heap + stack) min size */ +#define H_DEFAULT_SIZE 233 /* default (heap + stack) min size */ +#define VH_DEFAULT_SIZE 32768 /* default virtual (bin) heap min size (words) */ #ifdef HYBRID # define SH_DEFAULT_SIZE 2629425 /* default message area min size */ @@ -178,6 +179,7 @@ extern int num_instructions; /* Number of instruction in opc[]. */ #define MAX_PORT_LINK 8 /* Maximum number of links to a port */ extern int H_MIN_SIZE; /* minimum (heap + stack) */ +extern int BIN_VH_MIN_SIZE; /* minimum virtual (bin) heap */ #define ORIG_CREATION 0 -- cgit v1.2.3 From 647a2b4dac949d50e01bfd541561f1e1ec1c890c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 15 Dec 2009 15:06:05 +0100 Subject: Add min heap size start options to beam and erl The erl (and beam) start arguments are extended with the following options: * +hms Size, sets the default minimum heap size for processes. * +hmbs Size, sets the default minimum binary virtual heap size for processes. The previous +h Size argument can still be used for backward compatibility purposes. --- erts/emulator/beam/erl_init.c | 115 +++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 45 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 5d2d119b14..0677037bc5 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -515,67 +515,69 @@ void erts_usage(void) /* erts_fprintf(stderr, "-# number set the number of items to be used in traces etc\n"); */ - erts_fprintf(stderr, "-a size suggested stack size in kilo words for threads\n"); - erts_fprintf(stderr, " in the async-thread pool, valid range is [%d-%d]\n", + erts_fprintf(stderr, "-a size suggested stack size in kilo words for threads\n"); + erts_fprintf(stderr, " in the async-thread pool, valid range is [%d-%d]\n", ERTS_ASYNC_THREAD_MIN_STACK_SIZE, ERTS_ASYNC_THREAD_MAX_STACK_SIZE); - erts_fprintf(stderr, "-A number set number of threads in async thread pool,\n"); - erts_fprintf(stderr, " valid range is [0-%d]\n", + erts_fprintf(stderr, "-A number set number of threads in async thread pool,\n"); + erts_fprintf(stderr, " valid range is [0-%d]\n", ERTS_MAX_NO_OF_ASYNC_THREADS); - erts_fprintf(stderr, "-B[c|d|i] c to have Ctrl-c interrupt the Erlang shell,\n"); - erts_fprintf(stderr, " d (or no extra option) to disable the break\n"); - erts_fprintf(stderr, " handler, i to ignore break signals\n"); + erts_fprintf(stderr, "-B[c|d|i] c to have Ctrl-c interrupt the Erlang shell,\n"); + erts_fprintf(stderr, " d (or no extra option) to disable the break\n"); + erts_fprintf(stderr, " handler, i to ignore break signals\n"); /* erts_fprintf(stderr, "-b func set the boot function (default boot)\n"); */ - erts_fprintf(stderr, "-c disable continuous date/time correction with\n"); - erts_fprintf(stderr, " respect to uptime\n"); + erts_fprintf(stderr, "-c disable continuous date/time correction with\n"); + erts_fprintf(stderr, " respect to uptime\n"); - erts_fprintf(stderr, "-d don't write a crash dump for internally detected errors\n"); - erts_fprintf(stderr, " (halt(String) will still produce a crash dump)\n"); + erts_fprintf(stderr, "-d don't write a crash dump for internally detected errors\n"); + erts_fprintf(stderr, " (halt(String) will still produce a crash dump)\n"); - erts_fprintf(stderr, "-h number set minimum heap size in words (default %d)\n", + erts_fprintf(stderr, "-hms size set minimum heap size in words (default %d)\n", H_DEFAULT_SIZE); + erts_fprintf(stderr, "-hmbs size set minimum binary virtual heap size in words (default %d)\n", + VH_DEFAULT_SIZE); /* erts_fprintf(stderr, "-i module set the boot module (default init)\n"); */ - erts_fprintf(stderr, "-K boolean enable or disable kernel poll\n"); + erts_fprintf(stderr, "-K boolean enable or disable kernel poll\n"); - erts_fprintf(stderr, "-l turn on auto load tracing\n"); + erts_fprintf(stderr, "-l turn on auto load tracing\n"); - erts_fprintf(stderr, "-M memory allocator switches,\n"); - erts_fprintf(stderr, " see the erts_alloc(3) documentation for more info.\n"); + erts_fprintf(stderr, "-M memory allocator switches,\n"); + erts_fprintf(stderr, " see the erts_alloc(3) documentation for more info.\n"); - erts_fprintf(stderr, "-P number set maximum number of processes on this node,\n"); - erts_fprintf(stderr, " valid range is [%d-%d]\n", + erts_fprintf(stderr, "-P number set maximum number of processes on this node,\n"); + erts_fprintf(stderr, " valid range is [%d-%d]\n", ERTS_MIN_PROCESSES, ERTS_MAX_PROCESSES); - erts_fprintf(stderr, "-R number set compatibility release number,\n"); - erts_fprintf(stderr, " valid range [%d-%d]\n", + erts_fprintf(stderr, "-R number set compatibility release number,\n"); + erts_fprintf(stderr, " valid range [%d-%d]\n", ERTS_MIN_COMPAT_REL, this_rel_num()); - erts_fprintf(stderr, "-r force ets memory block to be moved on realloc\n"); - erts_fprintf(stderr, "-sbt type set scheduler bind type, valid types are:\n"); - erts_fprintf(stderr, " u|ns|ts|ps|s|nnts|nnps|tnnps|db\n"); - erts_fprintf(stderr, "-sct cput set cpu topology,\n"); - erts_fprintf(stderr, " see the erl(1) documentation for more info.\n"); - erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n"); - erts_fprintf(stderr, " valid range is [%d-%d]\n", + erts_fprintf(stderr, "-r force ets memory block to be moved on realloc\n"); + erts_fprintf(stderr, "-sbt type set scheduler bind type, valid types are:\n"); + erts_fprintf(stderr, " u|ns|ts|ps|s|nnts|nnps|tnnps|db\n"); + erts_fprintf(stderr, "-sct cput set cpu topology,\n"); + erts_fprintf(stderr, " see the erl(1) documentation for more info.\n"); + erts_fprintf(stderr, "-sss size suggested stack size in kilo words for scheduler threads,\n"); + erts_fprintf(stderr, " valid range is [%d-%d]\n", ERTS_SCHED_THREAD_MIN_STACK_SIZE, ERTS_SCHED_THREAD_MAX_STACK_SIZE); - erts_fprintf(stderr, "-S n1:n2 set number of schedulers (n1), and number of\n"); - erts_fprintf(stderr, " schedulers online (n2), valid range for both\n"); - erts_fprintf(stderr, " numbers are [1-%d]\n", + erts_fprintf(stderr, "-S n1:n2 set number of schedulers (n1), and number of\n"); + erts_fprintf(stderr, " schedulers online (n2), valid range for both\n"); + erts_fprintf(stderr, " numbers are [1-%d]\n", ERTS_MAX_NO_OF_SCHEDULERS); - erts_fprintf(stderr, "-T number set modified timing level,\n"); - erts_fprintf(stderr, " valid range is [0-%d]\n", + erts_fprintf(stderr, "-T number set modified timing level,\n"); + erts_fprintf(stderr, " valid range is [0-%d]\n", ERTS_MODIFIED_TIMING_LEVELS-1); - erts_fprintf(stderr, "-V print Erlang version\n"); + erts_fprintf(stderr, "-V print Erlang version\n"); - erts_fprintf(stderr, "-v turn on chatty mode (GCs will be reported etc)\n"); + erts_fprintf(stderr, "-v turn on chatty mode (GCs will be reported etc)\n"); - erts_fprintf(stderr, "-W set error logger warnings mapping,\n"); - erts_fprintf(stderr, " see error_logger documentation for details\n"); + erts_fprintf(stderr, "-W set error logger warnings mapping,\n"); + erts_fprintf(stderr, " see error_logger documentation for details\n"); erts_fprintf(stderr, "\n"); erts_fprintf(stderr, "Note that if the emulator is started with erlexec (typically\n"); @@ -925,17 +927,40 @@ erl_start(int argc, char **argv) fprintf(stderr, "The undocumented +H option has been removed (R10B-6).\n\n"); break; - case 'h': - /* set default heap size */ - arg = get_arg(argv[i]+2, argv[i+1], &i); - if ((H_MIN_SIZE = atoi(arg)) <= 0) { - erts_fprintf(stderr, "bad heap size %s\n", arg); - erts_usage(); + case 'h': { + char *sub_param = argv[i]+2; + /* set default heap size + * + * h|ms - min_heap_size + * h|mbs - min_bin_vheap_size + * + */ + if (has_prefix("mbs", sub_param)) { + arg = get_arg(sub_param+3, argv[i+1], &i); + if ((BIN_VH_MIN_SIZE = atoi(arg)) <= 0) { + erts_fprintf(stderr, "bad heap size %s\n", arg); + erts_usage(); + } + VERBOSE(DEBUG_SYSTEM, ("using minimum binary virtual heap size %d\n", BIN_VH_MIN_SIZE)); + + } else if (has_prefix("ms", sub_param)) { + arg = get_arg(sub_param+2, argv[i+1], &i); + if ((H_MIN_SIZE = atoi(arg)) <= 0) { + erts_fprintf(stderr, "bad heap size %s\n", arg); + erts_usage(); + } + VERBOSE(DEBUG_SYSTEM, ("using minimum heap size %d\n", H_MIN_SIZE)); + } else { + /* backward compatibility */ + arg = get_arg(argv[i]+2, argv[i+1], &i); + if ((H_MIN_SIZE = atoi(arg)) <= 0) { + erts_fprintf(stderr, "bad heap size %s\n", arg); + erts_usage(); + } + VERBOSE(DEBUG_SYSTEM, ("using minimum heap size %d\n", H_MIN_SIZE)); } - VERBOSE(DEBUG_SYSTEM, - ("using minimum heap size %d\n",H_MIN_SIZE)); break; - + } case 'd': /* * Never produce crash dumps for internally detected -- cgit v1.2.3 From 97e5d2508d66b86453a33f0c101674df0fb73c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Wed, 16 Dec 2009 14:24:25 +0100 Subject: Add tracing capabilities for binary virtual heap --- erts/emulator/beam/erl_trace.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'erts/emulator/beam') diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index 2afb16fc52..0b13569ab7 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -2171,6 +2171,11 @@ erts_bif_trace(int bif_index, Process* p, void trace_gc(Process *p, Eterm what) { + ERTS_DECL_AM(bin_vheap_size); + ERTS_DECL_AM(bin_vheap_block_size); + ERTS_DECL_AM(bin_old_vheap_size); + ERTS_DECL_AM(bin_old_vheap_block_size); + ErlHeapFragment *bp = NULL; ErlOffHeap *off_heap; ERTS_TRACER_REF_TYPE tracer_ref = ERTS_NULL_TRACER_REF; /* Initialized @@ -2180,6 +2185,7 @@ trace_gc(Process *p, Eterm what) Eterm* hp; Eterm msg = NIL; Uint size; + Eterm tags[] = { am_old_heap_block_size, am_heap_block_size, @@ -2187,8 +2193,13 @@ trace_gc(Process *p, Eterm what) am_recent_size, am_stack_size, am_old_heap_size, - am_heap_size + am_heap_size, + AM_bin_vheap_size, + AM_bin_vheap_block_size, + AM_bin_old_vheap_size, + AM_bin_old_vheap_block_size }; + Uint values[] = { OLD_HEAP(p) ? OLD_HEND(p) - OLD_HEAP(p) : 0, HEAP_SIZE(p), @@ -2196,7 +2207,11 @@ trace_gc(Process *p, Eterm what) HIGH_WATER(p) - HEAP_START(p), STACK_START(p) - p->stop, OLD_HEAP(p) ? OLD_HTOP(p) - OLD_HEAP(p) : 0, - HEAP_TOP(p) - HEAP_START(p) + HEAP_TOP(p) - HEAP_START(p), + MSO(p).overhead, + BIN_VHEAP_SZ(p), + BIN_OLD_VHEAP(p), + BIN_OLD_VHEAP_SZ(p) }; Eterm local_heap[(sizeof(values)/sizeof(Uint)) *(2/*cons*/ + 3/*2-tuple*/ + BIG_UINT_HEAP_SIZE) -- cgit v1.2.3