@@ -2,6 +2,7 @@ package lf3
2
2
3
3
import (
4
4
"context"
5
+ "runtime"
5
6
"sort"
6
7
"sync"
7
8
"time"
@@ -36,6 +37,7 @@ type ecWrapper struct {
36
37
37
38
powerTableComputeLock sync.Mutex
38
39
powerTableComputeJobs map [types.TipSetKey ]chan struct {}
40
+ powerTableComputeSema chan struct {}
39
41
}
40
42
41
43
func newEcWrapper (chainStore * store.ChainStore , syncer * chain.Syncer , stateManager * stmgr.StateManager ) * ecWrapper {
@@ -50,6 +52,7 @@ func newEcWrapper(chainStore *store.ChainStore, syncer *chain.Syncer, stateManag
50
52
cache : cache ,
51
53
52
54
powerTableComputeJobs : make (map [types.TipSetKey ]chan struct {}),
55
+ powerTableComputeSema : make (chan struct {}, min (4 , runtime .NumCPU ()/ 2 )),
53
56
}
54
57
}
55
58
@@ -140,6 +143,7 @@ func (ec *ecWrapper) GetPowerTable(ctx context.Context, tskF3 gpbft.TipSetKey) (
140
143
}
141
144
142
145
func (ec * ecWrapper ) getPowerTableLotusTSK (ctx context.Context , tsk types.TipSetKey ) (gpbft.PowerEntries , error ) {
146
+ // Either wait for someone else to compute the power table, or claim the job.
143
147
for {
144
148
// check the cache
145
149
pe , ok := ec .cache .Get (tsk )
@@ -160,10 +164,13 @@ func (ec *ecWrapper) getPowerTableLotusTSK(ctx context.Context, tsk types.TipSet
160
164
}
161
165
}
162
166
167
+ // Ok, we have the lock and nobody else has claimed the job. Claim it.
163
168
myWaitCh := make (chan struct {})
164
169
ec .powerTableComputeJobs [tsk ] = myWaitCh
165
170
ec .powerTableComputeLock .Unlock ()
166
171
172
+ // Make sure to "unlock" the job when we're done, even if we don't complete it. Someone else
173
+ // will complete it in that case.
167
174
defer func () {
168
175
ec .powerTableComputeLock .Lock ()
169
176
delete (ec .powerTableComputeJobs , tsk )
@@ -172,6 +179,17 @@ func (ec *ecWrapper) getPowerTableLotusTSK(ctx context.Context, tsk types.TipSet
172
179
close (myWaitCh )
173
180
}()
174
181
182
+ // Then wait in line. We only allow 4 jobs at once.
183
+ select {
184
+ case ec .powerTableComputeSema <- struct {}{}:
185
+ case <- ctx .Done ():
186
+ return nil , ctx .Err ()
187
+ }
188
+ defer func () {
189
+ <- ec .powerTableComputeSema
190
+ }()
191
+
192
+ // Finally, do the actual compute.
175
193
ts , err := ec .chainStore .GetTipSetFromKey (ctx , tsk )
176
194
if err != nil {
177
195
return nil , xerrors .Errorf ("getting tipset by key for get parent: %w" , err )
0 commit comments