Skip to content

Commit

Permalink
allow setting cache concurrency, default to shared
Browse files Browse the repository at this point in the history
This was changed to Locked a while back because it was breaking nix
builds or something. But defaulting to Locked is counter-productive; it
can make builds even slower by serializing them.
  • Loading branch information
vito committed Apr 10, 2023
1 parent bec18f5 commit 7888652
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 23 deletions.
15 changes: 12 additions & 3 deletions pkg/bass/cache_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,22 @@ import (

// CachePath is a Path within an ephemeral directory managed by the runtime.
type CachePath struct {
ID string
Path FileOrDirPath
ID string
ConcurrencyMode ConcurrencyMode
Path FileOrDirPath
}

type ConcurrencyMode int

const (
ConcurrencyModeShared = iota
ConcurrencyModePrivate
ConcurrencyModeLocked
)

var _ Value = CachePath{}

func NewCacheDir(id string) CachePath {
func NewCacheDir(id string, mode ...ConcurrencyMode) CachePath {
return NewCachePath(id, ParseFileOrDirPath("."))
}

Expand Down
28 changes: 25 additions & 3 deletions pkg/bass/ground.go
Original file line number Diff line number Diff line change
Expand Up @@ -801,9 +801,31 @@ func init() {
)

Ground.Set("cache-dir",
Func("cache-dir", "[id]", NewCacheDir),
`returns a cache directory corresponding to the string identifier`,
`Cache directories may be mounted to thunks. Their content persists across thunk runs.`)
Func("cache-dir", "[id & mode]", func(id string, mode ...Symbol) (CachePath, error) {
cache := NewCacheDir(id)
if len(mode) > 0 {
switch mode[0] {
case "locked":
cache.ConcurrencyMode = ConcurrencyModeLocked
case "private":
cache.ConcurrencyMode = ConcurrencyModePrivate
case "shared":
cache.ConcurrencyMode = ConcurrencyModeShared
default:
return CachePath{}, fmt.Errorf("invalid cache mode: %s", mode[0])
}
}

return cache, nil
}),
`returns a cache directory with the given identifier and concurrency mode`,
`Cache directories may be mounted to thunks. Their content persists across thunk runs.`,
`The :shared concurrency mode allows multiple thunks to run concurrently with the same cache.`,
`The :locked mode allows only one thunk to run at a time with the same cache.`,
`The :private mode creates a new mount for concurrent thunks.`,
`The default mode is :shared.`,
`=> (cache-dir "foo")`,
`=> (cache-dir "foo" :locked)`)

Ground.Set("binds?",
Func("binds?", "[scope sym]", (*Scope).Binds),
Expand Down
12 changes: 11 additions & 1 deletion pkg/runtimes/buildkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -1312,10 +1312,20 @@ func (b *buildkitBuilder) initializeMount(ctx context.Context, source bass.Thunk
return llb.AddMount(targetPath, st, llb.SourcePath(sp)), sp, false, nil

case source.Cache != nil:
var mode llb.CacheMountSharingMode
switch source.Cache.ConcurrencyMode {
case bass.ConcurrencyModeShared:
mode = llb.CacheMountShared
case bass.ConcurrencyModePrivate:
mode = llb.CacheMountPrivate
case bass.ConcurrencyModeLocked:
mode = llb.CacheMountLocked
}

return llb.AddMount(
targetPath,
llb.Scratch(),
llb.AsPersistentCacheDir(source.Cache.ID, llb.CacheMountLocked),
llb.AsPersistentCacheDir(source.Cache.ID, mode),
llb.SourcePath(source.Cache.Path.FilesystemPath().FromSlash()),
), "", false, nil

Expand Down
12 changes: 11 additions & 1 deletion pkg/runtimes/dagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,21 @@ func (runtime *Dagger) mount(ctx context.Context, client *dagger.Client, ctr *da
return nil, fmt.Errorf("mounting subpaths of cache not implemented yet: %s", fsp.Slash())
}

var mode dagger.CacheSharingMode
switch src.Cache.ConcurrencyMode {
case bass.ConcurrencyModeShared:
mode = dagger.Shared
case bass.ConcurrencyModePrivate:
mode = dagger.Private
case bass.ConcurrencyModeLocked:
mode = dagger.Locked
}

return ctr.WithMountedCache(
target,
client.CacheVolume(src.Cache.ID),
dagger.ContainerWithMountedCacheOpts{
Sharing: dagger.Locked,
Sharing: mode,
},
), nil
case src.FSPath != nil:
Expand Down
12 changes: 0 additions & 12 deletions pkg/runtimes/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,6 @@ func Suite(t *testing.T, runtimeConfig bass.RuntimeConfig, opts ...SuiteOpt) {
},
{
File: "cache-sync.bass",
Result: bass.NewList(
bass.NewList(bass.String("1")),
bass.NewList(bass.String("2")),
bass.NewList(bass.String("3")),
bass.NewList(bass.String("4")),
bass.NewList(bass.String("5")),
bass.NewList(bass.String("6")),
bass.NewList(bass.String("7")),
bass.NewList(bass.String("8")),
bass.NewList(bass.String("9")),
bass.NewList(bass.String("10")),
),
},
{
File: "cache-cmd.bass",
Expand Down
7 changes: 4 additions & 3 deletions pkg/runtimes/testdata/cache-sync.bass
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(def test-cache-path
(cache-dir (str "test-cache-sync-" (now 0))))
(cache-dir (str "test-cache-sync-" (now 0)) :locked))

(defn counter [tag]
(subpath
Expand All @@ -18,7 +18,8 @@
(let [files (map counter tags)]
(-> ($ sh -c "cat $@ | sort -n" ignored & $files)
(with-image (linux/alpine))
(read :unix-table)
(read :lines)
all)))

(counts "a" "b" "c" "d" "e" "f" "g" "h" "i" "j")
(assert = ["1" "2" "3" "4" "5" "6" "7" "8" "9" "10"]
(counts "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"))

0 comments on commit 7888652

Please sign in to comment.