Skip to content

Commit 6a2eacf

Browse files
authored
[filedao] improve HeaderFooterByHeight() efficiency (#2472)
1 parent db4f15d commit 6a2eacf

File tree

8 files changed

+132
-117
lines changed

8 files changed

+132
-117
lines changed

blockchain/blockdao/blockdao.go

Lines changed: 9 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,9 @@ type (
4545
// BlockDAO represents the block data access object
4646
BlockDAO interface {
4747
filedao.FileDAO
48-
Header(hash.Hash256) (*block.Header, error)
49-
Body(hash.Hash256) (*block.Body, error)
50-
Footer(hash.Hash256) (*block.Footer, error)
5148
GetActionByActionHash(hash.Hash256, uint64) (action.SealedEnvelope, error)
5249
GetReceiptByActionHash(hash.Hash256, uint64) (*action.Receipt, error)
5350
DeleteBlockToTarget(uint64) error
54-
HeaderByHeight(uint64) (*block.Header, error)
55-
FooterByHeight(uint64) (*block.Footer, error)
5651
}
5752

5853
// BlockIndexer defines an interface to accept block to build index
@@ -222,14 +217,13 @@ func (dao *blockDAO) HeaderByHeight(height uint64) (*block.Header, error) {
222217
}
223218
cacheMtc.WithLabelValues("miss_header").Inc()
224219

225-
blk, err := dao.blockStore.GetBlockByHeight(height)
220+
header, err := dao.blockStore.HeaderByHeight(height)
226221
if err != nil {
227222
return nil, err
228223
}
229224

230-
header := blk.Header
231-
lruCachePut(dao.headerCache, height, &header)
232-
return &header, nil
225+
lruCachePut(dao.headerCache, height, header)
226+
return header, nil
233227
}
234228

235229
func (dao *blockDAO) FooterByHeight(height uint64) (*block.Footer, error) {
@@ -239,14 +233,13 @@ func (dao *blockDAO) FooterByHeight(height uint64) (*block.Footer, error) {
239233
}
240234
cacheMtc.WithLabelValues("miss_footer").Inc()
241235

242-
blk, err := dao.blockStore.GetBlockByHeight(height)
236+
footer, err := dao.blockStore.FooterByHeight(height)
243237
if err != nil {
244238
return nil, err
245239
}
246240

247-
footer := blk.Footer
248-
lruCachePut(dao.footerCache, height, &footer)
249-
return &footer, nil
241+
lruCachePut(dao.footerCache, height, footer)
242+
return footer, nil
250243
}
251244

252245
func (dao *blockDAO) Height() (uint64, error) {
@@ -260,48 +253,13 @@ func (dao *blockDAO) Header(h hash.Hash256) (*block.Header, error) {
260253
}
261254
cacheMtc.WithLabelValues("miss_header").Inc()
262255

263-
blk, err := dao.GetBlock(h)
264-
if err != nil {
265-
return nil, err
266-
}
267-
268-
header := blk.Header
269-
lruCachePut(dao.headerCache, h, &header)
270-
return &header, nil
271-
}
272-
273-
func (dao *blockDAO) Body(h hash.Hash256) (*block.Body, error) {
274-
if v, ok := lruCacheGet(dao.bodyCache, h); ok {
275-
cacheMtc.WithLabelValues("hit_body").Inc()
276-
return v.(*block.Body), nil
277-
}
278-
cacheMtc.WithLabelValues("miss_body").Inc()
279-
280-
blk, err := dao.GetBlock(h)
281-
if err != nil {
282-
return nil, err
283-
}
284-
285-
body := blk.Body
286-
lruCachePut(dao.bodyCache, h, &body)
287-
return &body, nil
288-
}
289-
290-
func (dao *blockDAO) Footer(h hash.Hash256) (*block.Footer, error) {
291-
if v, ok := lruCacheGet(dao.footerCache, h); ok {
292-
cacheMtc.WithLabelValues("hit_footer").Inc()
293-
return v.(*block.Footer), nil
294-
}
295-
cacheMtc.WithLabelValues("miss_footer").Inc()
296-
297-
blk, err := dao.GetBlock(h)
256+
header, err := dao.blockStore.Header(h)
298257
if err != nil {
299258
return nil, err
300259
}
301260

302-
footer := blk.Footer
303-
lruCachePut(dao.footerCache, h, &footer)
304-
return &footer, nil
261+
lruCachePut(dao.headerCache, h, header)
262+
return header, nil
305263
}
306264

307265
func (dao *blockDAO) GetActionByActionHash(h hash.Hash256, height uint64) (action.SealedEnvelope, error) {

blockchain/blockdao/blockdao_test.go

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -224,16 +224,10 @@ func TestBlockDAO(t *testing.T) {
224224
header, err := dao.Header(hash)
225225
require.NoError(err)
226226
require.Equal(&tipBlk.Header, header)
227-
body, err := dao.Body(hash)
228-
require.NoError(err)
229-
require.Equal(&tipBlk.Body, body)
230-
footer, err := dao.Footer(hash)
231-
require.NoError(err)
232-
require.Equal(&tipBlk.Footer, footer)
233227
header, err = dao.HeaderByHeight(height)
234228
require.NoError(err)
235229
require.Equal(&tipBlk.Header, header)
236-
footer, err = dao.FooterByHeight(height)
230+
footer, err := dao.FooterByHeight(height)
237231
require.NoError(err)
238232
require.Equal(&tipBlk.Footer, footer)
239233
}
@@ -346,16 +340,10 @@ func TestBlockDAO(t *testing.T) {
346340
header, err := dao.Header(h)
347341
require.NoError(err)
348342
require.Equal(&tipBlk.Header, header)
349-
body, err := dao.Body(h)
350-
require.NoError(err)
351-
require.Equal(&tipBlk.Body, body)
352-
footer, err := dao.Footer(h)
353-
require.NoError(err)
354-
require.Equal(&tipBlk.Footer, footer)
355343
header, err = dao.HeaderByHeight(height)
356344
require.NoError(err)
357345
require.Equal(&tipBlk.Header, header)
358-
footer, err = dao.FooterByHeight(height)
346+
footer, err := dao.FooterByHeight(height)
359347
require.NoError(err)
360348
require.Equal(&tipBlk.Footer, footer)
361349
}

blockchain/filedao/filedao.go

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ var (
4545
)
4646

4747
type (
48-
// FileDAO represents the data access object for managing block db file
49-
FileDAO interface {
48+
// BaseFileDAO represents the basic data access object
49+
BaseFileDAO interface {
5050
Start(ctx context.Context) error
5151
Stop(ctx context.Context) error
5252
Height() (uint64, error)
@@ -61,13 +61,21 @@ type (
6161
DeleteTipBlock() error
6262
}
6363

64+
// FileDAO represents the data access object for managing block db file
65+
FileDAO interface {
66+
BaseFileDAO
67+
Header(hash.Hash256) (*block.Header, error)
68+
HeaderByHeight(uint64) (*block.Header, error)
69+
FooterByHeight(uint64) (*block.Footer, error)
70+
}
71+
6472
// fileDAO implements FileDAO
6573
fileDAO struct {
6674
lock sync.Mutex
6775
topIndex uint64
6876
splitHeight uint64
6977
cfg config.DB
70-
currFd FileDAO
78+
currFd BaseFileDAO
7179
legacyFd FileDAO
7280
v2Fd *FileV2Manager // a collection of v2 db files
7381
}
@@ -204,6 +212,57 @@ func (fd *fileDAO) GetBlockByHeight(height uint64) (*block.Block, error) {
204212
return nil, ErrNotSupported
205213
}
206214

215+
func (fd *fileDAO) Header(hash hash.Hash256) (*block.Header, error) {
216+
var (
217+
blk *block.Block
218+
err error
219+
)
220+
if fd.v2Fd != nil {
221+
if blk, err = fd.v2Fd.GetBlock(hash); err == nil {
222+
return &blk.Header, nil
223+
}
224+
}
225+
226+
if fd.legacyFd != nil {
227+
return fd.legacyFd.Header(hash)
228+
}
229+
return nil, err
230+
}
231+
232+
func (fd *fileDAO) HeaderByHeight(height uint64) (*block.Header, error) {
233+
if fd.v2Fd != nil {
234+
if v2 := fd.v2Fd.FileDAOByHeight(height); v2 != nil {
235+
blk, err := v2.GetBlockByHeight(height)
236+
if err != nil {
237+
return nil, err
238+
}
239+
return &blk.Header, nil
240+
}
241+
}
242+
243+
if fd.legacyFd != nil {
244+
return fd.legacyFd.HeaderByHeight(height)
245+
}
246+
return nil, ErrNotSupported
247+
}
248+
249+
func (fd *fileDAO) FooterByHeight(height uint64) (*block.Footer, error) {
250+
if fd.v2Fd != nil {
251+
if v2 := fd.v2Fd.FileDAOByHeight(height); v2 != nil {
252+
blk, err := v2.GetBlockByHeight(height)
253+
if err != nil {
254+
return nil, err
255+
}
256+
return &blk.Footer, nil
257+
}
258+
}
259+
260+
if fd.legacyFd != nil {
261+
return fd.legacyFd.FooterByHeight(height)
262+
}
263+
return nil, ErrNotSupported
264+
}
265+
207266
func (fd *fileDAO) GetReceipts(height uint64) ([]*action.Receipt, error) {
208267
if fd.v2Fd != nil {
209268
if v2 := fd.v2Fd.FileDAOByHeight(height); v2 != nil {

blockchain/filedao/filedao_legacy.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func (fd *fileDAOLegacy) GetBlockHeight(h hash.Hash256) (uint64, error) {
148148
}
149149

150150
func (fd *fileDAOLegacy) GetBlock(h hash.Hash256) (*block.Block, error) {
151-
header, err := fd.header(h)
151+
header, err := fd.Header(h)
152152
if err != nil {
153153
return nil, errors.Wrapf(err, "failed to get block header %x", h)
154154
}
@@ -175,6 +175,22 @@ func (fd *fileDAOLegacy) GetBlockByHeight(height uint64) (*block.Block, error) {
175175
return fd.GetBlock(hash)
176176
}
177177

178+
func (fd *fileDAOLegacy) HeaderByHeight(height uint64) (*block.Header, error) {
179+
hash, err := fd.GetBlockHash(height)
180+
if err != nil {
181+
return nil, err
182+
}
183+
return fd.Header(hash)
184+
}
185+
186+
func (fd *fileDAOLegacy) FooterByHeight(height uint64) (*block.Footer, error) {
187+
hash, err := fd.GetBlockHash(height)
188+
if err != nil {
189+
return nil, err
190+
}
191+
return fd.footer(hash)
192+
}
193+
178194
func (fd *fileDAOLegacy) GetReceipts(height uint64) ([]*action.Receipt, error) {
179195
kvStore, _, err := fd.getDBFromHeight(height)
180196
if err != nil {
@@ -201,7 +217,7 @@ func (fd *fileDAOLegacy) GetReceipts(height uint64) ([]*action.Receipt, error) {
201217
return blockReceipts, nil
202218
}
203219

204-
func (fd *fileDAOLegacy) header(h hash.Hash256) (*block.Header, error) {
220+
func (fd *fileDAOLegacy) Header(h hash.Hash256) (*block.Header, error) {
205221
value, err := fd.getBlockValue(blockHeaderNS, h)
206222
if err != nil {
207223
return nil, errors.Wrapf(err, "failed to get block header %x", h)

blockchain/filedao/filedao_v2_manager.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (fm *FileV2Manager) Stop(ctx context.Context) error {
7373
}
7474

7575
// FileDAOByHeight returns FileDAO for the given height
76-
func (fm *FileV2Manager) FileDAOByHeight(height uint64) FileDAO {
76+
func (fm *FileV2Manager) FileDAOByHeight(height uint64) BaseFileDAO {
7777
right := len(fm.Indices) - 1
7878
if height >= fm.Indices[right].start {
7979
return fm.Indices[right].fd
@@ -134,7 +134,7 @@ func (fm *FileV2Manager) AddFileDAO(fd *fileDAOv2, start uint64) error {
134134
}
135135

136136
// TopFd returns the top (with maximum height) v2 file
137-
func (fm *FileV2Manager) TopFd() (FileDAO, uint64) {
137+
func (fm *FileV2Manager) TopFd() (BaseFileDAO, uint64) {
138138
top := fm.Indices[len(fm.Indices)-1]
139139
return top.fd, top.start
140140
}

blockchain/filedao/testing.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,30 @@ func newFileDAOv2InMem(bottom uint64) (*fileDAOv2, error) {
7171
return &fd, nil
7272
}
7373

74+
func (fd *testInMemFd) Header(h hash.Hash256) (*block.Header, error) {
75+
blk, err := fd.GetBlock(h)
76+
if err != nil {
77+
return nil, err
78+
}
79+
return &blk.Header, nil
80+
}
81+
82+
func (fd *testInMemFd) HeaderByHeight(height uint64) (*block.Header, error) {
83+
blk, err := fd.GetBlockByHeight(height)
84+
if err != nil {
85+
return nil, err
86+
}
87+
return &blk.Header, nil
88+
}
89+
90+
func (fd *testInMemFd) FooterByHeight(height uint64) (*block.Footer, error) {
91+
blk, err := fd.GetBlockByHeight(height)
92+
if err != nil {
93+
return nil, err
94+
}
95+
return &blk.Footer, nil
96+
}
97+
7498
func (fd *testInMemFd) PutBlock(ctx context.Context, blk *block.Block) error {
7599
// bail out if block already exists
76100
h := blk.HashBlock()
@@ -104,7 +128,7 @@ func (tf *testFailPutBlock) PutBlock(ctx context.Context, blk *block.Block) erro
104128
return tf.currFd.PutBlock(ctx, blk)
105129
}
106130

107-
func testCommitBlocks(t *testing.T, fd FileDAO, start, end uint64, h hash.Hash256) error {
131+
func testCommitBlocks(t *testing.T, fd BaseFileDAO, start, end uint64, h hash.Hash256) error {
108132
ctx := context.Background()
109133
builder := block.NewTestingBuilder()
110134
for i := start; i <= end; i++ {

misc/scripts/mockgen.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ mockgen -destination=./test/mock/mock_blockchain/mock_blockchain.go \
1717
mkdir -p ./test/mock/mock_blockdao
1818
mockgen -destination=./test/mock/mock_blockdao/mock_blockdao.go \
1919
-source=./blockchain/blockdao/blockdao.go \
20-
-aux_files=github.com/iotexproject/iotex-core/blockchain/blockdao=./blockchain/blockdao/filedao.go \
20+
-aux_files=github.com/iotexproject/iotex-core/blockchain/blockdao=./blockchain/filedao/filedao.go \
2121
-package=mock_blockdao \
2222
BlockDAO
2323

0 commit comments

Comments
 (0)