summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--gc.c26
-rw-r--r--gc.h1
-rw-r--r--genvim.txr2
-rw-r--r--lib.c1
-rw-r--r--txr.158
-rw-r--r--txr.c9
-rw-r--r--txr.h1
8 files changed, 116 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index f23f8107..2d74bda6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2014-09-08 Kaz Kylheku <kaz@kylheku.com>
+
+ * gc.c (MALLOC_DELTA_THRESH): Macro remaned to DFL_MALLOC_DELTA_THRESH.
+ (opt_gc_delta): New global variable.
+ (make_obj): Use opt_gc_delta rather than MALLOC_DELTA_THRESH.
+ (gc_set_delta, gc_wrap): New static functions.
+ (gc_late_init): New function.
+
+ * gc.h (gc_late_init): Declared.
+
+ * genvim.txr: scan gc.c also.
+
+ * lib.c (init): call gc_late_init.
+
+ * txr.1: Document new --gc-delta option and the functions
+ gc and gc-set-delta.
+
+ * txr.c (help): Help text for --gc-delta.
+ (txr_main): Parse --gc-delta option.
+
+ * txr.h (opt_gc_delta): Declared.
+
2014-09-06 Kaz Kylheku <kaz@kylheku.com>
Make the garbage collector aware of malloced bytes, to
diff --git a/gc.c b/gc.c
index 3143530a..516ba6d6 100644
--- a/gc.c
+++ b/gc.c
@@ -40,6 +40,7 @@
#include "stream.h"
#include "hash.h"
#include "txr.h"
+#include "eval.h"
#include "gc.h"
#include "signal.h"
@@ -49,7 +50,7 @@
#define MUTOBJ_VEC_SIZE (HEAP_SIZE / 4)
#define FULL_GC_INTERVAL 40
#define FRESHOBJ_VEC_SIZE (8 * HEAP_SIZE)
-#define MALLOC_DELTA_THRESH (64L * 1024 * 1024)
+#define DFL_MALLOC_DELTA_THRESH (64L * 1024 * 1024)
typedef struct heap {
struct heap *next;
@@ -78,6 +79,7 @@ static val heap_min_bound, heap_max_bound;
alloc_bytes_t gc_bytes;
static alloc_bytes_t prev_malloc_bytes;
+alloc_bytes_t opt_gc_delta = DFL_MALLOC_DELTA_THRESH;
int gc_enabled = 1;
@@ -160,14 +162,14 @@ val make_obj(void)
#if CONFIG_GEN_GC
if (opt_gc_debug || freshobj_idx >= FRESHOBJ_VEC_SIZE ||
- malloc_delta >= MALLOC_DELTA_THRESH)
+ malloc_delta >= opt_gc_delta)
{
gc();
assert (freshobj_idx < FRESHOBJ_VEC_SIZE);
prev_malloc_bytes = malloc_bytes;
}
#else
- if (opt_gc_debug || malloc_delta >= MALLOC_DELTA_THRESH) {
+ if (opt_gc_debug || malloc_delta >= opt_gc_delta) {
gc();
prev_malloc_bytes = malloc_bytes;
}
@@ -670,6 +672,24 @@ val gc_push(val obj, loc plist)
#endif
+static val gc_set_delta(val delta)
+{
+ opt_gc_delta = c_num(delta);
+ return nil;
+}
+
+static val gc_wrap(void)
+{
+ gc();
+ return nil;
+}
+
+void gc_late_init(void)
+{
+ reg_fun(intern(lit("gc"), system_package), func_n0(gc_wrap));
+ reg_fun(intern(lit("gc-set-delta"), system_package), func_n1(gc_set_delta));
+}
+
/*
* Useful functions for gdb'ing.
*/
diff --git a/gc.h b/gc.h
index 99e0938d..51452243 100644
--- a/gc.h
+++ b/gc.h
@@ -25,6 +25,7 @@
*/
void gc_init(val *stack_bottom);
+void gc_late_init(void);
val prot1(val *loc);
void rel1(val *loc);
void protect(val *, ...);
diff --git a/genvim.txr b/genvim.txr
index e9e6e7e5..25dfa04c 100644
--- a/genvim.txr
+++ b/genvim.txr
@@ -7,7 +7,7 @@ static void dir_tables_init(void)
@(until)
}
@(end)
-@(next @(open-files '("eval.c" "rand.c" "signal.c" "stream.c"
+@(next @(open-files '("eval.c" "rand.c" "signal.c" "stream.c" "gc.c"
"syslog.c" "filter.c" "txr.c" "arith.c")))
@(collect)
@ (block)
diff --git a/lib.c b/lib.c
index da3ccf35..2b742192 100644
--- a/lib.c
+++ b/lib.c
@@ -6641,6 +6641,7 @@ void init(const wchar_t *pn, mem_t *(*oom)(mem_t *, size_t),
filter_init();
hash_init();
regex_init();
+ gc_late_init();
gc_state(gc_save);
}
diff --git a/txr.1 b/txr.1
index c856165a..6d44f3fe 100644
--- a/txr.1
+++ b/txr.1
@@ -206,6 +206,13 @@ supports that behavior, or even that exact version.
For more information, see the COMPATIBILITY section.
+.IP "--gc-delta=number"
+
+The argument to this option must be a decimal integer. It represents
+a megabyte value, the "GC delta": one megabyte is 1048576 bytes. The "GC
+delta" controls an aspect of the garbage collector behavior.
+See the gc-set-delta function for a description.
+
.IP --help
Prints usage summary on standard output, and terminates successfully.
@@ -15839,6 +15846,57 @@ pprof prints these statistics are printed in a concise report on the
The pprof macro relies on the prof operator.
+.SH GARBAGE COLLECTION
+
+.SS Function sys:gc
+
+.TP
+Syntax:
+
+ (sys:gc)
+
+.TP
+Description:
+
+The gc function triggers garbage collection. Garbage collection means
+that unreachable objects are identified and reclaimed, so that their
+storage can be re-used.
+
+.SS Function sys:gc-set-delta
+
+.TP
+Syntax:
+
+ (sys:gc-set-delta <bytes>)
+
+.TP
+Description:
+
+The gc-set-delta function sets the GC delta parameter.
+
+Note: This function may disappear in a future release of TXR or suffer
+a backward-incompatible change in its syntax or behavior.
+
+When the amount of new dynamic memory allocated since the last garbage
+collection equals or exceeds the GC delta, a garbage collection pass is
+triggered. From that point, a new delta begins to be accumulated.
+
+Dynamic memory is used for allocating heaps of small garbage-collected objects
+such as cons cells, as well as the satellite data attached to some objects:
+like the storage arrays of vectors, strings or bignum integers. Most garbage
+collector behaviors are based on counting objects in the heaps.
+
+Sometimes a program works with a small number of objects which are very large,
+frequently allocating new, large objects and turning old ones into garbage.
+For instance a single large integer could be many megabytes long. In such a
+situation, a small number of heap objects therefore control a large amount of
+memory. This requires garbage collection to be triggered much more often than
+when working with small objects, such as conses, to prevent runaway allocation
+of memory. It is for this reason that the garbage collector uses the GC delta.
+
+There is a default GC delta of 64 megabytes. This may be overridden in
+special builds of TXR for small systems.
+
.SH MODULARIZATION
.SS Special variable *self-path*
diff --git a/txr.c b/txr.c
index a2bb9dd2..b9239d9c 100644
--- a/txr.c
+++ b/txr.c
@@ -129,6 +129,8 @@ static void help(void)
" section at the bottom of the license.\n"
"--lisp-bindings Synonym for -l\n"
"--debugger Synonym for -d\n"
+"--gc-delta=N Invoke garbage collection when malloc activity\n"
+" increments by N megabytes since last collection.\n"
"\n"
"Options that take no argument can be combined. The -q and -v options\n"
"are mutually exclusive; the right-most one dominates.\n"
@@ -356,6 +358,13 @@ int txr_main(int argc, char **argv)
continue;
}
+ if (match_str(arg, lit("--gc-delta="), zero)) {
+ val megs = mul(int_str(sub(arg, num_fast(11), t), num_fast(10)),
+ num_fast(1048576));
+ opt_gc_delta = c_num(megs);
+ continue;
+ }
+
if (equal(arg, lit("--version"))) {
format(std_output, lit("~a: version ~a\n"),
prog_string, auto_str(version), nao);
diff --git a/txr.h b/txr.h
index 201bd385..e6a1f5f7 100644
--- a/txr.h
+++ b/txr.h
@@ -34,5 +34,6 @@ extern int opt_vg_debug;
#endif
extern int opt_derivative_regex;
extern int opt_compat;
+extern alloc_bytes_t opt_gc_delta;
extern const wchli_t *version;
extern const wchar_t *progname;