Hello,

I originally starting working on a "game engine" in Common Lisp (quotations
as it's actually a visualization tool). Eventually, I ran into memory
management/GC issues so I sought out another Lisp-based language with a
more hackable implementation. In my own system, one of the goals is to
maximize expressiveness and dynamicness, however, balanced with pragmatism
and simplicity. I found PicoLisp which has similar principles and is an
awesome system! It's exactly what I've been looking except for a few things
which seem feasible to implement.

Because my system has soft deadlines, I would like to implement per-frame
allocation which gives more deterministic/bounded execution. Allocation is
simply pointer bumping (as is now) and freeing would be reseting a pointer
to the memory base giving O(1) performance. Nothing would be shared between
frames (anything needed is copied). Of course, I would need to handle the
typical pitfalls associated with manual memory management, however, the
nature of my system limits those.

I was reading about memory management in Lisp Machines back in the day, and
they used a concept called "areas" consisting of "regions" (the meaning of
those terms, including "arena" and "pool", has become conflated these
days), which gives much more control over memory management, while still
involving the GC:

* https://hanshuebner.github.io/lmman/areas.xml
* http://www.unlambda.com/lmman/lmman_21.html

Initially, I thought about implementing a similar system into PicoLisp, but
I feel that would be restrictive and complex; however, if implemented more
fundamental functionality, it would provide greater flexibility for memory
management schemes, albeit at the lisp level (performance not withstanding).

Thus, I propose a few changes to the memory system:
* Expose *Heaps and *Avail pointers
  * Or more formally, expose Heaps as a list of lists of cons cells, and
Avail as a single cons cell.
* Create/expose global "*GC" to enable/disable GC
  * cons* functions would need to check this
  * The current functionality could be retain and force GC anyways if there
is no space, i.e. trust the user but provide fallback mechanism
* Heap size can already be controlled with gc, however, could make heap
resizing a separate function so GC need not be performed with the resize.
  * This makes sense with automatic collection, but adds unnecessary work
if doing manual management.
  * If Heap/Avail pointers exposed, then this could also be done manually
in lisp.

In my situation, I would simply allocate a heap of sufficient memory at the
beginning of the program/frame, then allocate as usual, and finally reset
*Avail at the start/end of the frame.

A few other questions:
* Is there any particular reason, such as for convenience or preventing
fragmentation, that CELLS is defined rather than a variable?
* Is it possible to add a hook for when the GC is called? This would assist
in profiling and diagnostics.

I believe memory management need not be a dichotomy between malloc/free and
GC; tools can be provided to work in the grey space, which typically is
some form of arenas/regions/pools. Many implementations also lack said
tools as they strictly adhere to one or the other, which results in
inadequate workarounds and/or increasing complexity, had the implementation
had support in the first place. Last but not least, it could help make
PicoLisp more compelling for real-time scenarios; especially for situations
where GC tuning is insufficient, but complete manual memory management is
not feasible (see Java's various GC implementations).


Sincerely,
Kevin Ednalino

Reply via email to