From f3b6f8de1a54b648d46965a2ab9452dffcfd4d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 21 Jun 2021 19:35:47 +0100 Subject: [PATCH 1/6] add ability to ignore worker resources when scheduling. --- extern/sector-storage/manager.go | 4 ++++ extern/sector-storage/sched.go | 19 +++++++++-------- extern/sector-storage/storiface/worker.go | 7 ++++++- extern/sector-storage/worker_local.go | 25 +++++++++++++++-------- itests/kit/node_builder.go | 12 +++++++++++ 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 51558aaad50..b883a174f06 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -96,6 +96,10 @@ type SealerConfig struct { AllowPreCommit2 bool AllowCommit bool AllowUnseal bool + + // IgnoreResourceFiltering instructs the system to ignore available + // resources when assigning tasks to the local worker. + IgnoreResourceFiltering bool } type StorageAuth http.Header diff --git a/extern/sector-storage/sched.go b/extern/sector-storage/sched.go index 61411081afe..f70921f9198 100644 --- a/extern/sector-storage/sched.go +++ b/extern/sector-storage/sched.go @@ -349,24 +349,24 @@ func (sh *scheduler) trySched() { defer sh.workersLk.RUnlock() windowsLen := len(sh.openWindows) - queuneLen := sh.schedQueue.Len() + queueLen := sh.schedQueue.Len() - log.Debugf("SCHED %d queued; %d open windows", queuneLen, windowsLen) + log.Debugf("SCHED %d queued; %d open windows", queueLen, windowsLen) - if windowsLen == 0 || queuneLen == 0 { + if windowsLen == 0 || queueLen == 0 { // nothing to schedule on return } windows := make([]schedWindow, windowsLen) - acceptableWindows := make([][]int, queuneLen) + acceptableWindows := make([][]int, queueLen) // Step 1 throttle := make(chan struct{}, windowsLen) var wg sync.WaitGroup - wg.Add(queuneLen) - for i := 0; i < queuneLen; i++ { + wg.Add(queueLen) + for i := 0; i < queueLen; i++ { throttle <- struct{}{} go func(sqi int) { @@ -393,7 +393,8 @@ func (sh *scheduler) trySched() { } // TODO: allow bigger windows - if !windows[wnd].allocated.canHandleRequest(needRes, windowRequest.worker, "schedAcceptable", worker.info.Resources) { + ignoringResources := worker.info.IgnoreResources + if !ignoringResources && !windows[wnd].allocated.canHandleRequest(needRes, windowRequest.worker, "schedAcceptable", worker.info.Resources) { continue } @@ -451,9 +452,9 @@ func (sh *scheduler) trySched() { // Step 2 scheduled := 0 - rmQueue := make([]int, 0, queuneLen) + rmQueue := make([]int, 0, queueLen) - for sqi := 0; sqi < queuneLen; sqi++ { + for sqi := 0; sqi < queueLen; sqi++ { task := (*sh.schedQueue)[sqi] needRes := ResourceTable[task.taskType][task.sector.ProofType] diff --git a/extern/sector-storage/storiface/worker.go b/extern/sector-storage/storiface/worker.go index d3f4a2cd1c3..d1373f4c541 100644 --- a/extern/sector-storage/storiface/worker.go +++ b/extern/sector-storage/storiface/worker.go @@ -18,7 +18,12 @@ import ( type WorkerInfo struct { Hostname string - Resources WorkerResources + // IgnoreResources indicates whether the worker's available resources should + // be used ignored (true) or used (false) for the purposes of scheduling and + // task assignment. Only supported on local workers. Used for testing. + // Default should be false (zero value, i.e. resources taken into account). + IgnoreResources bool + Resources WorkerResources } type WorkerResources struct { diff --git a/extern/sector-storage/worker_local.go b/extern/sector-storage/worker_local.go index 2bb0f8300df..3e63f8659fc 100644 --- a/extern/sector-storage/worker_local.go +++ b/extern/sector-storage/worker_local.go @@ -20,7 +20,7 @@ import ( ffi "github.com/filecoin-project/filecoin-ffi" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-statestore" - storage "github.com/filecoin-project/specs-storage/storage" + "github.com/filecoin-project/specs-storage/storage" "github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper" "github.com/filecoin-project/lotus/extern/sector-storage/sealtasks" @@ -33,6 +33,11 @@ var pathTypes = []storiface.SectorFileType{storiface.FTUnsealed, storiface.FTSea type WorkerConfig struct { TaskTypes []sealtasks.TaskType NoSwap bool + + // IgnoreResourceFiltering enables task distribution to happen on this + // worker regardless of its currently available resources. Used in testing + // with the local worker. + IgnoreResourceFiltering bool } // used do provide custom proofs impl (mostly used in testing) @@ -46,6 +51,9 @@ type LocalWorker struct { executor ExecutorFunc noSwap bool + // see equivalent field on WorkerConfig. + ignoreResources bool + ct *workerCallTracker acceptTasks map[sealtasks.TaskType]struct{} running sync.WaitGroup @@ -71,12 +79,12 @@ func newLocalWorker(executor ExecutorFunc, wcfg WorkerConfig, store stores.Store ct: &workerCallTracker{ st: cst, }, - acceptTasks: acceptTasks, - executor: executor, - noSwap: wcfg.NoSwap, - - session: uuid.New(), - closing: make(chan struct{}), + acceptTasks: acceptTasks, + executor: executor, + noSwap: wcfg.NoSwap, + ignoreResources: wcfg.IgnoreResourceFiltering, + session: uuid.New(), + closing: make(chan struct{}), } if w.executor == nil { @@ -501,7 +509,8 @@ func (l *LocalWorker) Info(context.Context) (storiface.WorkerInfo, error) { } return storiface.WorkerInfo{ - Hostname: hostname, + Hostname: hostname, + IgnoreResources: l.ignoreResources, Resources: storiface.WorkerResources{ MemPhysical: mem.Total, MemSwap: memSwap, diff --git a/itests/kit/node_builder.go b/itests/kit/node_builder.go index 3780a766900..75cebf6bf0a 100644 --- a/itests/kit/node_builder.go +++ b/itests/kit/node_builder.go @@ -12,6 +12,7 @@ import ( "time" "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/node/config" "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" @@ -127,6 +128,12 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr node.Override(new(v1api.FullNode), tnd), node.Override(new(*lotusminer.Miner), lotusminer.NewTestMiner(mineBlock, act)), + node.Override(new(*sectorstorage.SealerConfig), func() *sectorstorage.SealerConfig { + scfg := config.DefaultStorageMiner() + scfg.Storage.IgnoreResourceFiltering = true + return &scfg.Storage + }), + opts, ) if err != nil { @@ -532,6 +539,11 @@ func mockMinerBuilderOpts(t *testing.T, fullOpts []FullNodeOpts, storage []Stora node.Override(new(sectorstorage.SectorManager), node.From(new(*mock.SectorMgr))), node.Override(new(sectorstorage.Unsealer), node.From(new(*mock.SectorMgr))), node.Override(new(sectorstorage.PieceProvider), node.From(new(*mock.SectorMgr))), + node.Override(new(*sectorstorage.SealerConfig), func() *sectorstorage.SealerConfig { + scfg := config.DefaultStorageMiner() + scfg.Storage.IgnoreResourceFiltering = true + return &scfg.Storage + }), node.Override(new(ffiwrapper.Verifier), mock.MockVerifier), node.Override(new(ffiwrapper.Prover), mock.MockProver), From b6147fb27f58f2ebb70a78a08874c4d4ec0f68f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 21 Jun 2021 20:28:15 +0100 Subject: [PATCH 2/6] extern/storage: retype resource filtering strategy to enum. --- extern/sector-storage/manager.go | 31 +++++++++--- extern/sector-storage/sched_test.go | 74 ++++++++++++++++++++--------- itests/kit/node_builder.go | 4 +- node/config/def.go | 3 ++ 4 files changed, 81 insertions(+), 31 deletions(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index b883a174f06..5bd372db0d6 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -87,6 +87,20 @@ type result struct { err error } +// ResourceFilteringStrategy is an enum indicating the kinds of resource +// filtering strategies that can be configured for workers. +type ResourceFilteringStrategy string + +const ( + // ResourceFilteringHardware specifies that available hardware resources + // should be evaluated when scheduling a task against the worker. + ResourceFilteringHardware = ResourceFilteringStrategy("hardware") + + // ResourceFilteringDisabled disables resource filtering against this + // worker. The scheduler may assign any task to this worker. + ResourceFilteringDisabled = ResourceFilteringStrategy("disabled") +) + type SealerConfig struct { ParallelFetchLimit int @@ -97,9 +111,10 @@ type SealerConfig struct { AllowCommit bool AllowUnseal bool - // IgnoreResourceFiltering instructs the system to ignore available - // resources when assigning tasks to the local worker. - IgnoreResourceFiltering bool + // ResourceFiltering instructs the system which resource filtering strategy + // to use when evaluating tasks against this worker. An empty value defaults + // to "hardware". + ResourceFiltering ResourceFilteringStrategy } type StorageAuth http.Header @@ -108,7 +123,6 @@ type WorkerStateStore *statestore.StateStore type ManagerStateStore *statestore.StateStore func New(ctx context.Context, lstor *stores.Local, stor *stores.Remote, ls stores.LocalStorage, si stores.SectorIndex, sc SealerConfig, wss WorkerStateStore, mss ManagerStateStore) (*Manager, error) { - prover, err := ffiwrapper.New(&readonlyProvider{stor: lstor, index: si}) if err != nil { return nil, xerrors.Errorf("creating prover instance: %w", err) @@ -155,9 +169,12 @@ func New(ctx context.Context, lstor *stores.Local, stor *stores.Remote, ls store localTasks = append(localTasks, sealtasks.TTUnseal) } - err = m.AddWorker(ctx, NewLocalWorker(WorkerConfig{ - TaskTypes: localTasks, - }, stor, lstor, si, m, wss)) + wcfg := WorkerConfig{ + IgnoreResourceFiltering: sc.ResourceFiltering == ResourceFilteringHardware, + TaskTypes: localTasks, + } + worker := NewLocalWorker(wcfg, stor, lstor, si, m, wss) + err = m.AddWorker(ctx, worker) if err != nil { return nil, xerrors.Errorf("adding local worker: %w", err) } diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index 63f3de64d00..38b3efda941 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -38,6 +38,20 @@ func TestWithPriority(t *testing.T) { require.Equal(t, 2222, getPriority(ctx)) } +var decentWorkerResources = storiface.WorkerResources{ + MemPhysical: 128 << 30, + MemSwap: 200 << 30, + MemReserved: 2 << 30, + CPUs: 32, + GPUs: []string{"a GPU"}, +} + +var constrainedWorkerResources = storiface.WorkerResources{ + MemPhysical: 1 << 30, + MemReserved: 2 << 30, + CPUs: 1, +} + type schedTestWorker struct { name string taskTypes map[sealtasks.TaskType]struct{} @@ -45,6 +59,9 @@ type schedTestWorker struct { closed bool session uuid.UUID + + resources storiface.WorkerResources + ignoreResources bool } func (s *schedTestWorker) SealPreCommit1(ctx context.Context, sector storage.SectorRef, ticket abi.SealRandomness, pieces []abi.PieceInfo) (storiface.CallID, error) { @@ -107,18 +124,11 @@ func (s *schedTestWorker) Paths(ctx context.Context) ([]stores.StoragePath, erro return s.paths, nil } -var decentWorkerResources = storiface.WorkerResources{ - MemPhysical: 128 << 30, - MemSwap: 200 << 30, - MemReserved: 2 << 30, - CPUs: 32, - GPUs: []string{"a GPU"}, -} - func (s *schedTestWorker) Info(ctx context.Context) (storiface.WorkerInfo, error) { return storiface.WorkerInfo{ - Hostname: s.name, - Resources: decentWorkerResources, + Hostname: s.name, + IgnoreResources: s.ignoreResources, + Resources: s.resources, }, nil } @@ -137,13 +147,16 @@ func (s *schedTestWorker) Close() error { var _ Worker = &schedTestWorker{} -func addTestWorker(t *testing.T, sched *scheduler, index *stores.Index, name string, taskTypes map[sealtasks.TaskType]struct{}) { +func addTestWorker(t *testing.T, sched *scheduler, index *stores.Index, name string, taskTypes map[sealtasks.TaskType]struct{}, resources storiface.WorkerResources, ignoreResources bool) { w := &schedTestWorker{ name: name, taskTypes: taskTypes, paths: []stores.StoragePath{{ID: "bb-8", Weight: 2, LocalPath: "food", CanSeal: true, CanStore: true}}, session: uuid.New(), + + resources: resources, + ignoreResources: ignoreResources, } for _, path := range w.paths { @@ -169,7 +182,7 @@ func TestSchedStartStop(t *testing.T) { sched := newScheduler() go sched.runSched() - addTestWorker(t, sched, stores.NewIndex(), "fred", nil) + addTestWorker(t, sched, stores.NewIndex(), "fred", nil, decentWorkerResources, false) require.NoError(t, sched.Close(context.TODO())) } @@ -183,6 +196,9 @@ func TestSched(t *testing.T) { type workerSpec struct { name string taskTypes map[sealtasks.TaskType]struct{} + + resources storiface.WorkerResources + ignoreResources bool } noopAction := func(ctx context.Context, w Worker) error { @@ -295,7 +311,7 @@ func TestSched(t *testing.T) { go sched.runSched() for _, worker := range workers { - addTestWorker(t, sched, index, worker.name, worker.taskTypes) + addTestWorker(t, sched, index, worker.name, worker.taskTypes, worker.resources, worker.ignoreResources) } rm := runMeta{ @@ -322,31 +338,45 @@ func TestSched(t *testing.T) { } } + t.Run("constrained-resources-not-scheduled", testFunc([]workerSpec{ + {name: "fred", resources: constrainedWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, + }, []task{ + sched("pc1-1", "fred", 8, sealtasks.TTPreCommit1), + taskNotScheduled("pc1-1"), + })) + + t.Run("constrained-resources-ignored-scheduled", testFunc([]workerSpec{ + {name: "fred", resources: constrainedWorkerResources, ignoreResources: true, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, + }, []task{ + sched("pc1-1", "fred", 8, sealtasks.TTPreCommit1), + taskStarted("pc1-1"), + })) + t.Run("one-pc1", testFunc([]workerSpec{ - {name: "fred", taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, + {name: "fred", resources: decentWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, }, []task{ sched("pc1-1", "fred", 8, sealtasks.TTPreCommit1), taskDone("pc1-1"), })) t.Run("pc1-2workers-1", testFunc([]workerSpec{ - {name: "fred2", taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit2: {}}}, - {name: "fred1", taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, + {name: "fred2", resources: decentWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit2: {}}}, + {name: "fred1", resources: decentWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, }, []task{ sched("pc1-1", "fred1", 8, sealtasks.TTPreCommit1), taskDone("pc1-1"), })) t.Run("pc1-2workers-2", testFunc([]workerSpec{ - {name: "fred1", taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, - {name: "fred2", taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit2: {}}}, + {name: "fred1", resources: decentWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, + {name: "fred2", resources: decentWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit2: {}}}, }, []task{ sched("pc1-1", "fred1", 8, sealtasks.TTPreCommit1), taskDone("pc1-1"), })) t.Run("pc1-block-pc2", testFunc([]workerSpec{ - {name: "fred", taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}, sealtasks.TTPreCommit2: {}}}, + {name: "fred", resources: decentWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}, sealtasks.TTPreCommit2: {}}}, }, []task{ sched("pc1", "fred", 8, sealtasks.TTPreCommit1), taskStarted("pc1"), @@ -359,7 +389,7 @@ func TestSched(t *testing.T) { })) t.Run("pc2-block-pc1", testFunc([]workerSpec{ - {name: "fred", taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}, sealtasks.TTPreCommit2: {}}}, + {name: "fred", resources: decentWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}, sealtasks.TTPreCommit2: {}}}, }, []task{ sched("pc2", "fred", 8, sealtasks.TTPreCommit2), taskStarted("pc2"), @@ -372,7 +402,7 @@ func TestSched(t *testing.T) { })) t.Run("pc1-batching", testFunc([]workerSpec{ - {name: "fred", taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, + {name: "fred", resources: decentWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, }, []task{ sched("t1", "fred", 8, sealtasks.TTPreCommit1), taskStarted("t1"), @@ -459,7 +489,7 @@ func TestSched(t *testing.T) { // run this one a bunch of times, it had a very annoying tendency to fail randomly for i := 0; i < 40; i++ { t.Run("pc1-pc2-prio", testFunc([]workerSpec{ - {name: "fred", taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}, sealtasks.TTPreCommit2: {}}}, + {name: "fred", resources: decentWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}, sealtasks.TTPreCommit2: {}}}, }, []task{ // fill queues twoPC1("w0", 0, taskStarted), diff --git a/itests/kit/node_builder.go b/itests/kit/node_builder.go index 75cebf6bf0a..3306d427f24 100644 --- a/itests/kit/node_builder.go +++ b/itests/kit/node_builder.go @@ -130,7 +130,7 @@ func CreateTestStorageNode(ctx context.Context, t *testing.T, waddr address.Addr node.Override(new(*sectorstorage.SealerConfig), func() *sectorstorage.SealerConfig { scfg := config.DefaultStorageMiner() - scfg.Storage.IgnoreResourceFiltering = true + scfg.Storage.ResourceFiltering = sectorstorage.ResourceFilteringDisabled return &scfg.Storage }), @@ -541,7 +541,7 @@ func mockMinerBuilderOpts(t *testing.T, fullOpts []FullNodeOpts, storage []Stora node.Override(new(sectorstorage.PieceProvider), node.From(new(*mock.SectorMgr))), node.Override(new(*sectorstorage.SealerConfig), func() *sectorstorage.SealerConfig { scfg := config.DefaultStorageMiner() - scfg.Storage.IgnoreResourceFiltering = true + scfg.Storage.ResourceFiltering = sectorstorage.ResourceFilteringDisabled return &scfg.Storage }), diff --git a/node/config/def.go b/node/config/def.go index 700a3f94f2e..a00ea730765 100644 --- a/node/config/def.go +++ b/node/config/def.go @@ -342,6 +342,9 @@ func DefaultStorageMiner() *StorageMiner { // Default to 10 - tcp should still be able to figure this out, and // it's the ratio between 10gbit / 1gbit ParallelFetchLimit: 10, + + // By default use the hardware resource filtering strategy. + ResourceFiltering: sectorstorage.ResourceFilteringHardware, }, Dealmaking: DealmakingConfig{ From 83839362c58edcccf0da2ba0c1c572dd19795800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 21 Jun 2021 20:35:51 +0100 Subject: [PATCH 3/6] fix boolean condition. --- extern/sector-storage/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/sector-storage/manager.go b/extern/sector-storage/manager.go index 5bd372db0d6..136c00252ec 100644 --- a/extern/sector-storage/manager.go +++ b/extern/sector-storage/manager.go @@ -170,7 +170,7 @@ func New(ctx context.Context, lstor *stores.Local, stor *stores.Remote, ls store } wcfg := WorkerConfig{ - IgnoreResourceFiltering: sc.ResourceFiltering == ResourceFilteringHardware, + IgnoreResourceFiltering: sc.ResourceFiltering == ResourceFilteringDisabled, TaskTypes: localTasks, } worker := NewLocalWorker(wcfg, stor, lstor, si, m, wss) From 59eab2df2593a0d277312b1a01e3a65c2b4752c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 21 Jun 2021 20:49:16 +0100 Subject: [PATCH 4/6] move scheduling filtering logic down. --- extern/sector-storage/sched.go | 9 ++++----- extern/sector-storage/sched_resources.go | 15 +++++++++++---- extern/sector-storage/sched_worker.go | 6 +++--- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/extern/sector-storage/sched.go b/extern/sector-storage/sched.go index f70921f9198..aabf6f0cef2 100644 --- a/extern/sector-storage/sched.go +++ b/extern/sector-storage/sched.go @@ -393,8 +393,7 @@ func (sh *scheduler) trySched() { } // TODO: allow bigger windows - ignoringResources := worker.info.IgnoreResources - if !ignoringResources && !windows[wnd].allocated.canHandleRequest(needRes, windowRequest.worker, "schedAcceptable", worker.info.Resources) { + if !windows[wnd].allocated.canHandleRequest(needRes, windowRequest.worker, "schedAcceptable", worker.info) { continue } @@ -461,18 +460,18 @@ func (sh *scheduler) trySched() { selectedWindow := -1 for _, wnd := range acceptableWindows[task.indexHeap] { wid := sh.openWindows[wnd].worker - wr := sh.workers[wid].info.Resources + info := sh.workers[wid].info log.Debugf("SCHED try assign sqi:%d sector %d to window %d", sqi, task.sector.ID.Number, wnd) // TODO: allow bigger windows - if !windows[wnd].allocated.canHandleRequest(needRes, wid, "schedAssign", wr) { + if !windows[wnd].allocated.canHandleRequest(needRes, wid, "schedAssign", info) { continue } log.Debugf("SCHED ASSIGNED sqi:%d sector %d task %s to window %d", sqi, task.sector.ID.Number, task.taskType, wnd) - windows[wnd].allocated.add(wr, needRes) + windows[wnd].allocated.add(info.Resources, needRes) // TODO: We probably want to re-sort acceptableWindows here based on new // workerHandle.utilization + windows[wnd].allocated.utilization (workerHandle.utilization is used in all // task selectors, but not in the same way, so need to figure out how to do that in a non-O(n^2 way), and diff --git a/extern/sector-storage/sched_resources.go b/extern/sector-storage/sched_resources.go index 3e359c1219b..96a1fa8638d 100644 --- a/extern/sector-storage/sched_resources.go +++ b/extern/sector-storage/sched_resources.go @@ -6,7 +6,7 @@ import ( "github.com/filecoin-project/lotus/extern/sector-storage/storiface" ) -func (a *activeResources) withResources(id WorkerID, wr storiface.WorkerResources, r Resources, locker sync.Locker, cb func() error) error { +func (a *activeResources) withResources(id WorkerID, wr storiface.WorkerInfo, r Resources, locker sync.Locker, cb func() error) error { for !a.canHandleRequest(r, id, "withResources", wr) { if a.cond == nil { a.cond = sync.NewCond(locker) @@ -14,11 +14,11 @@ func (a *activeResources) withResources(id WorkerID, wr storiface.WorkerResource a.cond.Wait() } - a.add(wr, r) + a.add(wr.Resources, r) err := cb() - a.free(wr, r) + a.free(wr.Resources, r) if a.cond != nil { a.cond.Broadcast() } @@ -44,8 +44,15 @@ func (a *activeResources) free(wr storiface.WorkerResources, r Resources) { a.memUsedMax -= r.MaxMemory } -func (a *activeResources) canHandleRequest(needRes Resources, wid WorkerID, caller string, res storiface.WorkerResources) bool { +// canHandleRequest evaluates if the worker has enough available resources to +// handle the request. +func (a *activeResources) canHandleRequest(needRes Resources, wid WorkerID, caller string, info storiface.WorkerInfo) bool { + if info.IgnoreResources { + // shortcircuit; if this worker is ignoring resources, it can always handle the request. + return true + } + res := info.Resources // TODO: dedupe needRes.BaseMinMemory per task type (don't add if that task is already running) minNeedMem := res.MemReserved + a.memUsedMin + needRes.MinMemory + needRes.BaseMinMemory if minNeedMem > res.MemPhysical { diff --git a/extern/sector-storage/sched_worker.go b/extern/sector-storage/sched_worker.go index 4e18e5c6f2b..7bc1affc3b6 100644 --- a/extern/sector-storage/sched_worker.go +++ b/extern/sector-storage/sched_worker.go @@ -296,7 +296,7 @@ func (sw *schedWorker) workerCompactWindows() { for ti, todo := range window.todo { needRes := ResourceTable[todo.taskType][todo.sector.ProofType] - if !lower.allocated.canHandleRequest(needRes, sw.wid, "compactWindows", worker.info.Resources) { + if !lower.allocated.canHandleRequest(needRes, sw.wid, "compactWindows", worker.info) { continue } @@ -352,7 +352,7 @@ assignLoop: worker.lk.Lock() for t, todo := range firstWindow.todo { needRes := ResourceTable[todo.taskType][todo.sector.ProofType] - if worker.preparing.canHandleRequest(needRes, sw.wid, "startPreparing", worker.info.Resources) { + if worker.preparing.canHandleRequest(needRes, sw.wid, "startPreparing", worker.info) { tidx = t break } @@ -424,7 +424,7 @@ func (sw *schedWorker) startProcessingTask(taskDone chan struct{}, req *workerRe } // wait (if needed) for resources in the 'active' window - err = w.active.withResources(sw.wid, w.info.Resources, needRes, &sh.workersLk, func() error { + err = w.active.withResources(sw.wid, w.info, needRes, &sh.workersLk, func() error { w.lk.Lock() w.preparing.free(w.info.Resources, needRes) w.lk.Unlock() From 684cce198fdff0e876487102bf11ecbea0035ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 21 Jun 2021 20:49:24 +0100 Subject: [PATCH 5/6] add a unit test. --- extern/sector-storage/sched_test.go | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/extern/sector-storage/sched_test.go b/extern/sector-storage/sched_test.go index 38b3efda941..fbc4d83ee07 100644 --- a/extern/sector-storage/sched_test.go +++ b/extern/sector-storage/sched_test.go @@ -338,18 +338,15 @@ func TestSched(t *testing.T) { } } - t.Run("constrained-resources-not-scheduled", testFunc([]workerSpec{ - {name: "fred", resources: constrainedWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, + // checks behaviour with workers with constrained resources + // the first one is not ignoring resource constraints, so we assign to the second worker, who is + t.Run("constrained-resources", testFunc([]workerSpec{ + {name: "fred1", resources: constrainedWorkerResources, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, + {name: "fred2", resources: constrainedWorkerResources, ignoreResources: true, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, }, []task{ - sched("pc1-1", "fred", 8, sealtasks.TTPreCommit1), - taskNotScheduled("pc1-1"), - })) - - t.Run("constrained-resources-ignored-scheduled", testFunc([]workerSpec{ - {name: "fred", resources: constrainedWorkerResources, ignoreResources: true, taskTypes: map[sealtasks.TaskType]struct{}{sealtasks.TTPreCommit1: {}}}, - }, []task{ - sched("pc1-1", "fred", 8, sealtasks.TTPreCommit1), + sched("pc1-1", "fred2", 8, sealtasks.TTPreCommit1), taskStarted("pc1-1"), + taskDone("pc1-1"), })) t.Run("one-pc1", testFunc([]workerSpec{ From c0a8a9f5b5a03817586a90db271db8cbaf88589b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Mon, 21 Jun 2021 20:52:59 +0100 Subject: [PATCH 6/6] make gen. --- build/openrpc/miner.json.gz | Bin 8088 -> 8104 bytes build/openrpc/worker.json.gz | Bin 2497 -> 2514 bytes documentation/en/api-v0-methods-miner.md | 1 + documentation/en/api-v0-methods-worker.md | 1 + 4 files changed, 2 insertions(+) diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 1d8ff7579b9810276be694c1bf01a4af2374c10b..b7c053d81c3189f4eb1635bef0b1ba56a9b63bf4 100644 GIT binary patch delta 8052 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 COu8!o delta 8053 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 D0yMtE diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 3c4fa4f701624af1b7af35092668b932227e41b9..411964f6549af607d0179d0709dbd490dbd836a8 100644 GIT binary patch literal 2514 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 L(#d+JPI3SMs8`^6 diff --git a/documentation/en/api-v0-methods-miner.md b/documentation/en/api-v0-methods-miner.md index 388213666fd..496f63a0851 100644 --- a/documentation/en/api-v0-methods-miner.md +++ b/documentation/en/api-v0-methods-miner.md @@ -2205,6 +2205,7 @@ Response: "ef8d99a2-6865-4189-8ffa-9fef0f806eee": { "Info": { "Hostname": "host", + "IgnoreResources": false, "Resources": { "MemPhysical": 274877906944, "MemSwap": 128849018880, diff --git a/documentation/en/api-v0-methods-worker.md b/documentation/en/api-v0-methods-worker.md index 925f8934bb2..c620113f489 100644 --- a/documentation/en/api-v0-methods-worker.md +++ b/documentation/en/api-v0-methods-worker.md @@ -89,6 +89,7 @@ Response: ```json { "Hostname": "string value", + "IgnoreResources": true, "Resources": { "MemPhysical": 42, "MemSwap": 42,