[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1004583: overwriting {,src}pkgcache.bin on near-every APT call strains flash



Package: apt
Version: 2.3.14
Severity: minor
Control: found -1 1.8.2.3

	[Please do not Cc: me, for I’m “on the list,” so to say, and
	I try to reserve my inbox for private communication only.
	I’d have set up Mail-Followup-To:, but there doesn’t seem to
	be a way to make it point to the bug being filed.]

	As of this writing, pkgcache.bin and srcpkgcache.bin files for
	an APT instance configured for testing / Sid are 61 MiB combined.

	The way those caches are updated is by writing a new version
	into a temporary file and then calling rename(2) to atomically
	replace the old version with the new.  As such, every time the
	caches are updated, some 61 MiB gets written to the filesystem

	While it could be argued that such an amount written makes
	no measurable impact on HDDs, and rather marginally affects
	the lifetime of contemporary SSDs, it’s not uncommon to start
	Debian from a micro-SD card on single-board computers, where
	write cycles may be considerably more limited.

	Similarly, when filesystems-level snapshots are supported
	(Btrfs, Nilfs, etc.), the issue described prevents space (and
	bandwidth, when snapshots are transferred with btrfs-send(8) /
	btrfs-receive(8)) savings by getting in the way of the
	filesystem’s copy-on-write behavior.

	(FWIW, apt is by no means the only package with such an issue:
	dpkg’s status file is updated the same way, and so is the
	templates.dat file debconf uses by default; yet dpkg/status is
	smaller, and debconf can be configured to use Driver: PackageDir,
	also lowering the impact.  Outside of the Debian infrastructure,
	tor caches are also ill-suited for write-limited media.)

	Consider, for example, the following chroot environment with a
	freshly installed Debian Bookworm (--arch=amd64 --variant=minbase
	and a couple of packages on top of that):

chroot# apt-get update 
Hit:1 http://cdn-fastly.deb.debian.org/debian bookworm InRelease
Hit:2 http://security.debian.org/debian-security bookworm-security/updates InRelease
Reading package lists...
chroot# 

	Now, let’s try to install some lightweight packages, checking
	the ‘lifetime writes’ meter before and after the apt-get call:

base# mount -o remount,ro -- /dev/vgfoo/lvchild-z61f590 \
          && dumpe2fs -- /dev/vgfoo/lvchild-z61f590 | grep -E -- ^Lifetime 
Lifetime writes:          5418 MB
base# 

chroot# apt-get install -- jpeginfo 
Reading package lists...
Building dependency tree...
Reading state information...
The following additional packages will be installed:
  libjpeg62-turbo
The following NEW packages will be installed:
  jpeginfo libjpeg62-turbo
0 upgraded, 2 newly installed, 0 to remove and 5 not upgraded.
Need to get 0 B/177 kB of archives.
After this operation, 725 kB of additional disk space will be used.
Do you want to continue? [Y/n] 
debconf: delaying package configuration, since apt-utils is not installed
E: Can not write log (Is /dev/pts mounted?) - posix_openpt (19: No such device)
Selecting previously unselected package libjpeg62-turbo:amd64.
(Reading database ... 6737 files and directories currently installed.)
Preparing to unpack .../libjpeg62-turbo_1%3a2.1.2-1_amd64.deb ...
Unpacking libjpeg62-turbo:amd64 (1:2.1.2-1) ...
Selecting previously unselected package jpeginfo.
Preparing to unpack .../jpeginfo_1.6.1-1_amd64.deb ...
Unpacking jpeginfo (1.6.1-1) ...
Setting up libjpeg62-turbo:amd64 (1:2.1.2-1) ...
Setting up jpeginfo (1.6.1-1) ...
Processing triggers for libc-bin (2.33-3) ...
chroot# 

base# mount -o remount,ro -- /dev/vgfoo/lvchild-z61f590 \
          && dumpe2fs -- /dev/vgfoo/lvchild-z61f590 | grep -E -- ^Lifetime 
Lifetime writes:          5740 MB
base# 

	By the looks of it, installing 725 KiB worth of Debian packages
	resulted in some 322 MiB getting written to the filesystem,
	for which I’m inclined to think that APT cache update behavior
	is in no small part responsible.  (I suppose running apt-get
	under strace would allow for a more accurate estimate.)

	For instance, largest recently changed files on the FS right
	after the # apt-get install call were (note that the .deb files
	to be installed were obtained earlier, and also that
	/var/cache/apt/archives was on a separate FS anyway):

chroot# find / -xdev -cmin -4 -printf %k\\t%p\\n | sort -srn 
31568   /var/cache/apt/pkgcache.bin
31548   /var/cache/apt/srcpkgcache.bin
580     /usr/lib/x86_64-linux-gnu/libjpeg.so.62.3.0
88      /var/lib/dpkg/status-old
88      /var/lib/dpkg/status
52      /var/log/dpkg.log
40      /usr/share/doc/libjpeg62-turbo/copyright

	A proper solution would be to move to some file format that
	allows in-place updates, such as Berkeley DB or SQLite.

	As a work-around, it’s possible to move the cache to tmpfs;
	consider, e. g.:

$ cat < /etc/apt/apt.conf.d/99-run-pkgcache 
Dir::Cache::pkgcache "/run/apt/pkgcache.bin";
Dir::Cache::srcpkgcache "/run/apt/srcpkgcache.bin";
$ grep -F -- /run/apt < /etc/fstab 
run.apt   /run/apt  tmpfs   rw,nodev,noexec,nosuid,mode=0755,size=256M,X-mount.mkdir  0 0
$ 

	When RAM is also limited (which is to say, the filesystem size=
	limit above isn’t negligible), it may make sense to remove the
	files when not in use, such as by enabling the atime filesystem
	option and using the following (untested) Cron job:

$ grep -F -- /run/apt < /etc/fstab 
run.apt   /run/apt  tmpfs   rw,nodev,noexec,nosuid,mode=0755,size=256M,X-mount.mkdir,atime  0 0
$ cat < /etc/cron.hourly/cleanup-run-apt 
#!/bin/sh
set -e
set -C -u

test -d /run/apt \
    || exit

## .
exec find /run/apt/ -maxdepth 1 \
    -type f -amin +113 -cmin +113 \
    -size +63k -name \*pkgcache.bin\* \
    -execdir rm -- {} +
$ 

-- 
FSF associate member #7257  http://am-1.org/~ivan/


Reply to: