Memory Investigation: PermaplanT Map Editor

Objective

Investigate memory usage and potential leaks in the map editor (using Firefox 151.0.1 (64-bit)).

Key questions:

  • How does memory scale with map complexity?
  • Are there leaks during long sessions?
  • Is memory released when switching maps?
  • What kind of hardware is recommended for Permaplant usage?

Test environment

PermaplanT build

A local development build was used for this investigation because it provides easier access to debugging information, browser developer tooling, and profiling instrumentation.

However, local builds may differ slightly from production builds due to various unpredictable deviations.

For reproducible benchmarking and final performance validation, production builds should also be tested.

Hardware

Record hardware specifications for every test:

  • CPU model
  • CPU clock speed
  • CPU number of cores/threads
  • CPU architecture (x86_64 or ARM64)
  • Installed RAM
  • GPU
  • Operating system

How to record hardware information (on Linux)

Run the following commands in Terminal:

  • CPU info (model, clock speed, number of cores/threads, architecture): lscpu | grep -E "Model name|Architecture|CPU\(s\)|Core\(s\) per socket|Thread\(s\) per core|Socket\(s\)|CPU max MHz".
  • Architecture and Model name self-explanatory.
  • Clock speed is the CPU max MHz value; convert to GHz.
  • Number of cores is total, i.e. Core(s) per socket multiplied by Socket(s).
  • Number of threads is total, i.e. Thread(s) per core multiplied by Core(s) per socket multiplied by Socket(s).
  • Installed RAM: free -h --si; check the value under total in the Mem: row. Alternative: grep MemTotal /proc/meminfo and convert to GB.
  • GPU: lspci | grep -iE "vga|3d|display". May show multiple GPUs (e.g. integrated and dedicated), write down both.
  • Operating system: cat /etc/os-release

Browser

This tutorial is for Firefox (Developer Edition also works well).

Firefox DevTools

1. Memory Panel

  • Heap snapshots
  • Aggregate view

2. Performance Panel

  • Enable:
    • JS Allocations
    • Memory
  • Record long sessions to observe trends

PostgreSQL

The PostgreSQL version used in production is 17.9 and it does not have native support for creation of uuidv7 (needed for automatic plant insertion).

This extension is needed: https://github.com/fboulnois/pg_uuidv7. The installation tutorial is in the README in the github link.

Investigation plan

How to automatically add plants

I am using the aforementioned PostgreSQL extension and its function uuid_generate_v7().

If you have version 18 or above, you should simply use uuidv7().

Steps for plant insertion:

  • On the empty test map, insert one plant (example here is Allium cepa).
  • Run the following command in Terminal: psql -h localhost -p 5432 -U permaplant.
  • In PostgreSQL, run SELECT * FROM plantings ORDER BY created_at DESC; find the planting you just created and find the created_by, modified_by and layer_id values.
  • Run ./tools/insert_plants.sh, usage described in the respective README.
  • Substitute <created_by>, <modified_by> and <layer_id> with their respective values, copying them from the manually created planting.
  • Refresh the page in the browser to see the plantings

General plan

After each test described below, measure the metrics described in Data & Metrics and fill out the report by making a new report_yyyymmdd.md file and copying the blank report from report_blank.md.

MEM-01 - Load Empty Map Baseline

Open an empty map and allow the editor to fully load.

MEM-02 - Load Map With 100 Plantings

Open a map containing 100 plantings and evaluate memory usage after full load.

MEM-03 - Load Map With 500 Plantings

Open a map containing 500 plantings and evaluate memory usage after full load.

MEM-04 - Load Map With 1000 Plantings

Open a map containing 1000 plantings and evaluate memory usage after full load.

MEM-05 - Load Map With 5000 Plantings

Open a map containing 5000 plantings and evaluate memory usage after full load.

MEM-06 - Switch From Large Map To Empty Map

Open an empty map, measure baseline, then open a map containing 5000 plantings, evaluate memory usage, then switch to an empty map and observe memory retention behavior.

MEM-07 - Continuous Editing Session Over One Hour

Use a medium-sized map continuously for approximately one hour with:

  • repeated plant editing,
  • frequent layer switching,
  • moderate undo/redo usage,
  • viewport navigation,

without adding additional plantings.

Behavior analysis

Healthy (expected) behavior

  • Linear/sub-linear memory growth with plants
  • Stable memory during long sessions
  • Memory drops after map switch
  • No detached DOM accumulation

Problem indicators

  • Memory never decreases after garbage collection
  • Growth independent of visible objects
  • Increasing baseline after each map switch
  • Large (200+ MB) retained trees in snapshots

4. Map editing over long time

Steps

  • Medium-sized map (100-500 plants)
  • Continuous plant editing
  • Frequent layer changes
  • Moderate undo/redo usage
  • Total work time should be around 1 hour
  • Check for JS Heap growth & tab memory growth

Data & Metrics

Test data sets

DatasetPlantingsValue
Empty0
Medium100
Big500
Large1000
Very Large5000

Scope of this investigation

This investigation focuses exclusively on the impact of planting count.

Other map content may influence memory consumption differently and was not evaluated, including:

  • area layers (hydrology, soil texture, shade, etc.)
  • high-resolution background images
  • timeline entries and historical data

Separate investigations may be required to evaluate the memory impact of these data types.

Metrics

MetricValue
JS Heap used
Memory used in browser tab
Load stability

JS Heap used is measured like this:

  • DevTools -> Memory
  • Take snapshot
  • Select Aggregate view
  • Look for value under "Bytes" (and convert it to MB)

Memory used in browser tab is shown in about:processes

Load stability is observed manually in about:processes - if the CPU values fluctuates too much or stays consistently high (10-30%) and doesn't go back to near 0, it is unstable and there is likely some kind of leak.