Skip to content

Commit 8900d55

Browse files
committed
replace channel by RWMutex for a few triePrefetcher APIs
For APIs like: trie(), copy(), used(), it is simpler and more efficient to use a RWMutex instead of channel communicaton. Since the mainLoop would be busy handling trie request, while these trie request can be processed in parallism. We would only keep prefetch and close within the mainLoop, since they could update the fetchers
1 parent e2afc0e commit 8900d55

File tree

1 file changed

+27
-68
lines changed

1 file changed

+27
-68
lines changed

core/state/trie_prefetcher.go

+27-68
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,6 @@ type prefetchMsg struct {
4141
keys [][]byte
4242
}
4343

44-
type usedMsg struct {
45-
root common.Hash
46-
used [][]byte
47-
}
48-
49-
type trieMsg struct {
50-
root common.Hash
51-
resultChan chan *subfetcher
52-
}
53-
5444
// triePrefetcher is an active prefetcher, which receives accounts or storage
5545
// items and does trie-loading of them. The goal is to get as much useful content
5646
// into the caches as possible.
@@ -65,11 +55,8 @@ type triePrefetcher struct {
6555
closed int32
6656
closeMainChan chan struct{} // it is to inform the mainLoop
6757
closeMainDoneChan chan struct{}
68-
copyChan chan struct{}
69-
copyDoneChan chan *triePrefetcher
58+
fetchersMutex sync.RWMutex
7059
prefetchChan chan *prefetchMsg // no need to wait for return
71-
trieChan chan *trieMsg
72-
usedChan chan *usedMsg // no need to wait for return
7360

7461
abortChan chan *subfetcher
7562
closeAbortChan chan struct{} // it is used to inform abortLoop
@@ -97,11 +84,7 @@ func newTriePrefetcher(db Database, root common.Hash, namespace string) *triePre
9784

9885
closeMainChan: make(chan struct{}),
9986
closeMainDoneChan: make(chan struct{}),
100-
copyChan: make(chan struct{}, concurrentChanSize),
101-
copyDoneChan: make(chan *triePrefetcher, concurrentChanSize),
10287
prefetchChan: make(chan *prefetchMsg, concurrentChanSize),
103-
trieChan: make(chan *trieMsg, concurrentChanSize),
104-
usedChan: make(chan *usedMsg, concurrentChanSize),
10588

10689
deliveryMissMeter: metrics.GetOrRegisterMeter(prefix+"/deliverymiss", nil),
10790
accountLoadMeter: metrics.GetOrRegisterMeter(prefix+"/account/load", nil),
@@ -121,34 +104,16 @@ func newTriePrefetcher(db Database, root common.Hash, namespace string) *triePre
121104
func (p *triePrefetcher) mainLoop() {
122105
for {
123106
select {
124-
case <-p.copyChan:
125-
fetcherCopied := &triePrefetcher{
126-
db: p.db,
127-
root: p.root,
128-
fetches: make(map[common.Hash]Trie, len(p.fetchers)),
129-
}
130-
// we're copying an active fetcher, retrieve the current states
131-
for root, fetcher := range p.fetchers {
132-
fetcherCopied.fetches[root] = fetcher.peek()
133-
}
134-
p.copyDoneChan <- fetcherCopied
135-
136107
case pMsg := <-p.prefetchChan:
137108
fetcher := p.fetchers[pMsg.root]
138109
if fetcher == nil {
139110
fetcher = newSubfetcher(p.db, pMsg.root, pMsg.accountHash)
111+
p.fetchersMutex.Lock()
140112
p.fetchers[pMsg.root] = fetcher
113+
p.fetchersMutex.Unlock()
141114
}
142115
fetcher.schedule(pMsg.keys)
143116

144-
case tireMsg := <-p.trieChan:
145-
tireMsg.resultChan <- p.fetchers[tireMsg.root]
146-
147-
case uMsg := <-p.usedChan:
148-
if fetcher := p.fetchers[uMsg.root]; fetcher != nil {
149-
fetcher.used = uMsg.used
150-
}
151-
152117
case <-p.closeMainChan:
153118
for _, fetcher := range p.fetchers {
154119
p.abortChan <- fetcher // safe to do multiple times
@@ -177,14 +142,14 @@ func (p *triePrefetcher) mainLoop() {
177142
}
178143
close(p.closeAbortChan)
179144
close(p.closeMainDoneChan)
145+
p.fetchersMutex.Lock()
180146
p.fetchers = nil
147+
p.fetchersMutex.Unlock()
148+
181149
// drain all the channels before quit the loop
182150
for {
183151
select {
184-
case <-p.copyChan:
185152
case <-p.prefetchChan:
186-
case <-p.trieChan:
187-
case <-p.usedChan:
188153
default:
189154
return
190155
}
@@ -238,24 +203,28 @@ func (p *triePrefetcher) copy() *triePrefetcher {
238203
}
239204
return fetcherCopied
240205
}
241-
p.copyChan <- struct{}{}
206+
242207
select {
243208
case <-p.closeMainChan:
244-
select {
245-
case <-p.copyChan: // to discard the message sent
246-
default:
209+
// for closed trie prefetcher, the fetches should not be nil
210+
fetcherCopied := &triePrefetcher{
211+
db: p.db,
212+
root: p.root,
213+
fetches: make(map[common.Hash]Trie),
247214
}
215+
return fetcherCopied
216+
default:
217+
p.fetchersMutex.RLock()
248218
fetcherCopied := &triePrefetcher{
249219
db: p.db,
250220
root: p.root,
251-
fetches: make(map[common.Hash]Trie, len(p.fetches)),
221+
fetches: make(map[common.Hash]Trie, len(p.fetchers)),
252222
}
253-
// for closed trie prefetcher, retrieve the current states
223+
// we're copying an active fetcher, retrieve the current states
254224
for root, fetcher := range p.fetchers {
255225
fetcherCopied.fetches[root] = fetcher.peek()
256226
}
257-
return fetcherCopied
258-
case fetcherCopied := <-p.copyDoneChan:
227+
p.fetchersMutex.RUnlock()
259228
return fetcherCopied
260229
}
261230
}
@@ -268,7 +237,6 @@ func (p *triePrefetcher) prefetch(root common.Hash, keys [][]byte, accountHash c
268237
}
269238
select {
270239
case <-p.closeMainChan: // skip closed trie prefetcher
271-
return
272240
case p.prefetchChan <- &prefetchMsg{root, accountHash, keys}:
273241
}
274242
}
@@ -285,19 +253,9 @@ func (p *triePrefetcher) trie(root common.Hash) Trie {
285253
return p.db.CopyTrie(trie)
286254
}
287255

288-
var fetcher *subfetcher
289-
// currentTrieChan is to make sure we receive root's fetcher in concurrency mode.
290-
currentTrieChan := make(chan *subfetcher)
291-
p.trieChan <- &trieMsg{root, currentTrieChan}
292-
select {
293-
case <-p.closeMainChan:
294-
select {
295-
case <-p.trieChan:
296-
default:
297-
}
298-
fetcher = p.fetchers[root]
299-
case fetcher = <-currentTrieChan:
300-
}
256+
p.fetchersMutex.RLock()
257+
fetcher := p.fetchers[root]
258+
p.fetchersMutex.RUnlock()
301259
if fetcher == nil {
302260
p.deliveryMissMeter.Mark(1)
303261
return nil
@@ -329,12 +287,13 @@ func (p *triePrefetcher) used(root common.Hash, used [][]byte) {
329287
return
330288
}
331289
select {
332-
case <-p.closeAbortChan:
333-
select {
334-
case <-p.usedChan:
335-
default:
290+
case <-p.closeMainChan:
291+
default:
292+
p.fetchersMutex.RLock()
293+
if fetcher := p.fetchers[root]; fetcher != nil {
294+
fetcher.used = used
336295
}
337-
case p.usedChan <- &usedMsg{root, used}:
296+
p.fetchersMutex.RUnlock()
338297
}
339298
}
340299

0 commit comments

Comments
 (0)