* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>
perf(memory): keep install, update and runtime inside a small-RAM budget (#83)
* perf(memory): keep install, update and runtime inside a small-RAM budget
Small NAT/VPS targets have 128-512MB of RAM and no swap, so anything that
cannot be reclaimed is fatal. This tuning touches no swap and no mmap; it
works by not allocating in the first place.
Installer (covers install and update; update.sh only execs install.sh):
- Put the scratch directory under DATA_DIR instead of mktemp -d. /tmp is
tmpfs on many of these hosts, and without swap every byte there is pinned
in RAM: bundle, extracted release and a copy of the data directory were
held at once, exceeding total RAM of the machines being targeted.
- Hash assets on the way to disk instead of re-reading them. Download is a
single pass now; verification still completes before tar sees the bytes.
- Release the intermediate data.tar right after extraction rather than
holding the data directory twice for the rest of the run.
- Check scratch capacity before downloading, so we fail before the old
service is stopped rather than halfway through.
- Refresh Environment=GOMEMLIMIT/GOGC/THREE_M_UI_CORE_LOW_MEMORY and
MemoryMax on an existing unit. write_service() keeps an operator's unit,
which meant the values baked in at install time never tracked updates.
Panel:
- Bound the Go heap from the process itself via debug.SetMemoryLimit, so the
tuning reaches manual runs, containers and the installer's own init and
healthcheck instead of only a systemd unit. It acts in-process, so the
Mihomo core never inherits the panel's tighter GC target. An explicit
GOMEMLIMIT or GOGC always wins.
- Emit geodata-loader: memconservative for the core when low-memory mode is
on. The key is omitempty and pinned after user fragments merge, so nothing
changes for anyone who does not opt in, and no fragment can undo it.
No new calls to Mmap/Munmap/Madvise, no swap or mmap anywhere in the tree.
* fix(ci): keep the new scratch directory out of the installer's own paths
Two problems CI caught on the small-memory change, both from moving the
scratch directory from mktemp into DATA_DIR.
restore_files() rebuilds the data directory by deleting everything in it
except backups. The scratch directory now lives inside it, so a rollback
deleted the very directory it was reading its own rollback out of, and the
restore died looking for restore/ENABLED. Rollback therefore had to be
skipped, exempting the scratch directory from that purge; the cleanup trap
already removes it.
The test curl also modelled only one of curl's output modes. Writing to
stdout and answering -I are both normal curl behaviour, and both are now
covered, so the mock no longer pins the installer to a single invocation
shape. The distribution fake likewise emits its tampered asset on stdout
instead of through --output, keeping that test about checksum rejection
rather than about which flag was used.
---------
Co-authored-by: 風雪 <kazeyukiro@users.noreply.github.com>