mobile-nixos/mobile-nixos

build.disk-image via binfmt taking 40mins doing a find/du on my /nix/store

tomfitzhenry opened this issue · 2 comments

nixpkgs: 7e567a3d092b7de69cdf5deaeb8d9526de230916
mobile-nixos: 85557dc

(Both taken from https://hydra.nixos.org/build/146100953#tabs-buildinputs )

I'm running a NixOS 21.05 x86-64 machine with aarch64-linux binfmt enabled, with btrfs on an NVMe drive.

Here's my local.nix:

{ lib, pkgs, ... }:

{
  imports = [
    ./examples/demo/configuration.nix
  ];
  nixpkgs.system = "aarch64-linux";
}

I executed -A build.disk-image, which pulled a bunch from cache.nixos.org and then has spent 28 minutes stuck on:

Done copying system closure...
'/nix/store/w945b9mikl1c480xnkx3w9lhc8pi28bl-closure-info/registration' -> './nix-path-registration'

Full command output: https://paste.debian.net/1203023/

Some diagnostics

pstree shows nix-daemon is building something that triggers find with du:

 | \-+= 43478 root nix-daemon 43465    
 |   |-+= 47223 nixbld1 /nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64 /nix/store/kawx6qqji9c8jal32d554whblbjj81l3-bash-4.4-p23/bin/bash -e /nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh 
 |   | \-+- 50100 nixbld1 /nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64 /nix/store/kawx6qqji9c8jal32d554whblbjj81l3-bash-4.4-p23/bin/bash -e /nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh 
 |   |   \-+- 50102 nixbld1 /nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64 /nix/store/kawx6qqji9c8jal32d554whblbjj81l3-bash-4.4-p23/bin/bash -e /nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh 
 |   |     \-+- 50104 nixbld1 /nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64 /nix/store/kawx6qqji9c8jal32d554whblbjj81l3-bash-4.4-p23/bin/bash -e /nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh 
 |   |       |--- 50110 nixbld1 /nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64 /nix/store/kawx6qqji9c8jal32d554whblbjj81l3-bash-4.4-p23/bin/bash -e /nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh 
 |   |       |--- 50108 nixbld1 /nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64 /nix/store/pcc3dbxii97a919fm0bs39mqfwlzkdma-coreutils-8.32/bin/cut -f1 
 |   |       \-+- 50106 nixbld1 /nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64 /nix/store/ns6p3l0gvl1yq4mb7a04zd2hs05sws0h-findutils-4.7.0/bin/find . ! -type d -exec du --apparent-size --block-size 4096 {} ; 
 |   |         \--- 388354 nixbld1 /nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64 /nix/store/pcc3dbxii97a919fm0bs39mqfwlzkdma-coreutils-8.32/bin/du --apparent-size --block-size 4096 ./nix/store/9pakc0y95f0nyr0vv3x49r6b217qnd74-libfido2-1.7.0/share/man/man3/fido_assert_set_hmac_secret.3.gz 

That find has been running for 37 mins (update it took 40 mins in total), and is still running:

$ ps aux | grep 50106
nixbld1    50106  0.9  0.0 240320 15460 ?        Sl   21:48   0:20 /nix/store/4s5s0bgp6708nnyl9zbc7fa6s8c5xh59-qemu-6.0.0/bin/qemu-aarch64 /nix/store/ns6p3l0gvl1yq4mb7a04zd2hs05sws0h-findutils-4.7.0/bin/find . ! -type d -exec du --apparent-size --block-size 4096 {} ;
tom       397543  0.0  0.0 223452  2328 pts/1    S+   22:25   0:00 grep 50106

$ ps -o etime= -p 50106
      37:22

$ date
Thu Jul  1 10:25:49 PM AEST 2021

After 40 mins, the build succeeded, with a 4GB disk image.

find/du used to get a proper reading of the actual block size the files will require. That is, a file that is 1 byte long still take a full filesystem "block".

Otherwise, the way blocks are always rounded up could result in the filesystem being too small! Imagine 100 000 files in the filesystem, all of them being under half a 512 bytes block rounded up, so:

(256 * 100_000) / 1024.0 / 1024.0
=> 24.4140625

This is about a 24 MiB difference! The image building infra is used in a way the filesystem images are reduced to their most minimal size.

Though note that I'll be taking a look at genimage in the future. Hopefully it can help somewhat here in the binfmt use case. (I'm using the same infra to build images no that other project.)