Speed up VM create with work seeds
Beat VM create wall time without changing VM semantics. Generate a work-seed ext4 sidecar during image builds and rootfs rebuilds, then clone and resize that seed for each new VM instead of rebuilding /root from scratch. Plumb the new seed artifact through config, runtime metadata, store state, runtime-bundle defaults, doctor checks, and default-image reconciliation so older images still fall back cleanly. Add a daemon TAP pool to keep idle bridge-attached devices warm, expose stage timing in lifecycle logs, add a create/SSH benchmark script plus Make target, and teach verify.sh that tap-pool-* devices are reusable capacity rather than cleanup leaks. Validated with go test ./..., make build, ./verify.sh, and make bench-create ARGS="--runs 2".
This commit is contained in:
parent
a14a80fd6b
commit
c8d9a122f9
24 changed files with 695 additions and 44 deletions
|
|
@ -34,6 +34,9 @@ type Daemon struct {
|
|||
mu sync.Mutex
|
||||
vmLocksMu sync.Mutex
|
||||
vmLocks map[string]*sync.Mutex
|
||||
tapPoolMu sync.Mutex
|
||||
tapPool []string
|
||||
tapPoolNext int
|
||||
closing chan struct{}
|
||||
once sync.Once
|
||||
pid int
|
||||
|
|
@ -92,6 +95,11 @@ func Open(ctx context.Context) (d *Daemon, err error) {
|
|||
d.logger.Error("daemon open failed", "stage", "reconcile", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
if err = d.initializeTapPool(ctx); err != nil {
|
||||
d.logger.Error("daemon open failed", "stage", "initialize_tap_pool", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
go d.ensureTapPool(context.Background())
|
||||
return d, nil
|
||||
}
|
||||
|
||||
|
|
@ -436,7 +444,7 @@ func (d *Daemon) ensureDefaultImage(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
if d.logger != nil {
|
||||
d.logger.Info("default image reconciled", append(imageLogAttrs(updated), "previous_rootfs_path", image.RootfsPath, "previous_kernel_path", image.KernelPath)...)
|
||||
d.logger.Info("default image reconciled", append(imageLogAttrs(updated), "previous_rootfs_path", image.RootfsPath, "previous_work_seed_path", image.WorkSeedPath, "previous_kernel_path", image.KernelPath)...)
|
||||
}
|
||||
return nil
|
||||
case errors.Is(err, sql.ErrNoRows):
|
||||
|
|
@ -471,6 +479,7 @@ func (d *Daemon) desiredDefaultImage() (model.Image, bool) {
|
|||
Managed: false,
|
||||
ArtifactDir: "",
|
||||
RootfsPath: rootfs,
|
||||
WorkSeedPath: d.config.DefaultWorkSeed,
|
||||
KernelPath: kernel,
|
||||
InitrdPath: d.config.DefaultInitrd,
|
||||
ModulesDir: d.config.DefaultModulesDir,
|
||||
|
|
@ -484,6 +493,7 @@ func defaultImageMatches(current, desired model.Image) bool {
|
|||
current.Managed == desired.Managed &&
|
||||
current.ArtifactDir == desired.ArtifactDir &&
|
||||
current.RootfsPath == desired.RootfsPath &&
|
||||
current.WorkSeedPath == desired.WorkSeedPath &&
|
||||
current.KernelPath == desired.KernelPath &&
|
||||
current.InitrdPath == desired.InitrdPath &&
|
||||
current.ModulesDir == desired.ModulesDir &&
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue