Tweaked lfsr_file_read to only buffer one btree entry at a time
This lets us cache more of each btree entry during reads, since the
buffer is no longer filled with unlikely-to-be-relevant, earlier btree
entries.
Also added lfsr_ftree_readnext for reading one btree entry, which is a
bit more flexible than the hint mechanism.
Code changes:
code stack
before: 32776 2944
after: 32804 (+0.1%) 2944 (+0.0%)
This commit is contained in:
@@ -9151,7 +9151,7 @@ static inline bool lfsr_f_iserrored(uint32_t flags) {
|
|||||||
// needed in lfsr_file_opencfg
|
// needed in lfsr_file_opencfg
|
||||||
static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs,
|
static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs,
|
||||||
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree,
|
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree,
|
||||||
lfs_off_t pos, uint8_t *buffer, lfs_size_t size, lfs_size_t hint);
|
lfs_off_t pos, uint8_t *buffer, lfs_size_t size);
|
||||||
|
|
||||||
int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
||||||
const char *path, uint32_t flags,
|
const char *path, uint32_t flags,
|
||||||
@@ -9313,7 +9313,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
&& file->size <= lfs->cfg->fragment_size) {
|
&& file->size <= lfs->cfg->fragment_size) {
|
||||||
lfs_ssize_t d = lfsr_ftree_read(lfs,
|
lfs_ssize_t d = lfsr_ftree_read(lfs,
|
||||||
&file->mdir, &file->ftree,
|
&file->mdir, &file->ftree,
|
||||||
0, file->buffer, file->size, file->size);
|
0, file->buffer, file->size);
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
err = d;
|
err = d;
|
||||||
goto failed_with_buffer;
|
goto failed_with_buffer;
|
||||||
@@ -9474,12 +9474,11 @@ static int lfsr_ftree_lookupnext(lfs_t *lfs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs,
|
static lfs_ssize_t lfsr_ftree_readnext(lfs_t *lfs,
|
||||||
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree,
|
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree,
|
||||||
lfs_off_t pos, uint8_t *buffer, lfs_size_t size, lfs_size_t hint) {
|
lfs_off_t pos, uint8_t *buffer, lfs_size_t size) {
|
||||||
lfs_off_t pos_ = pos;
|
lfs_off_t pos_ = pos;
|
||||||
lfs_ssize_t size_ = size;
|
// read one btree entry
|
||||||
while (size_ > 0 && pos_ < lfsr_ftree_size(ftree)) {
|
|
||||||
lfsr_bid_t bid;
|
lfsr_bid_t bid;
|
||||||
lfsr_tag_t tag;
|
lfsr_tag_t tag;
|
||||||
lfsr_bid_t weight;
|
lfsr_bid_t weight;
|
||||||
@@ -9488,7 +9487,6 @@ static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs,
|
|||||||
mdir, ftree, pos_,
|
mdir, ftree, pos_,
|
||||||
&bid, &tag, &weight, &bptr, NULL);
|
&bid, &tag, &weight, &bptr, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9497,7 +9495,7 @@ static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs,
|
|||||||
// note one important side-effect here is a strict
|
// note one important side-effect here is a strict
|
||||||
// data hint
|
// data hint
|
||||||
lfs_ssize_t d = lfs_min32(
|
lfs_ssize_t d = lfs_min32(
|
||||||
hint,
|
size,
|
||||||
lfsr_data_size(&bptr.data)
|
lfsr_data_size(&bptr.data)
|
||||||
- (pos_ - (bid-(weight-1))));
|
- (pos_ - (bid-(weight-1))));
|
||||||
lfsr_data_t slice = lfsr_data_slice(bptr.data,
|
lfsr_data_t slice = lfsr_data_slice(bptr.data,
|
||||||
@@ -9511,18 +9509,35 @@ static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs,
|
|||||||
|
|
||||||
pos_ += d;
|
pos_ += d;
|
||||||
buffer += d;
|
buffer += d;
|
||||||
size_ -= d;
|
size -= d;
|
||||||
hint -= d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// found a hole? write zeros
|
// found a hole? write zeros
|
||||||
lfs_ssize_t d = lfs_min32(hint, bid+1 - pos_);
|
lfs_ssize_t d = lfs_min32(size, bid+1 - pos_);
|
||||||
memset(buffer, 0, d);
|
memset(buffer, 0, d);
|
||||||
|
|
||||||
pos_ += d;
|
pos_ += d;
|
||||||
buffer += d;
|
buffer += d;
|
||||||
size_ -= d;
|
size -= d;
|
||||||
hint -= d;
|
|
||||||
|
return pos_ - pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static lfs_ssize_t lfsr_ftree_read(lfs_t *lfs,
|
||||||
|
const lfsr_mdir_t *mdir, const lfsr_ftree_t *ftree,
|
||||||
|
lfs_off_t pos, uint8_t *buffer, lfs_size_t size) {
|
||||||
|
lfs_off_t pos_ = pos;
|
||||||
|
while (size > 0 && pos_ < lfsr_ftree_size(ftree)) {
|
||||||
|
lfs_ssize_t d = lfsr_ftree_readnext(lfs, mdir, ftree,
|
||||||
|
pos_, buffer, size);
|
||||||
|
if (d < 0) {
|
||||||
|
LFS_ASSERT(d != LFS_ERR_NOENT);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos_ += d;
|
||||||
|
buffer += d;
|
||||||
|
size -= d;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pos_ - pos;
|
return pos_ - pos;
|
||||||
@@ -10328,24 +10343,8 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
d = lfs_min32(d, file->buffer_pos - pos_);
|
d = lfs_min32(d, file->buffer_pos - pos_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bypass buffer?
|
// beyond end of ftree? fill with zeros
|
||||||
if ((lfs_size_t)d >= lfs->cfg->cache_size) {
|
if (pos_ > lfsr_ftree_size(&file->ftree)) {
|
||||||
// any data in our ftree?
|
|
||||||
if (pos_ < lfsr_ftree_size(&file->ftree)) {
|
|
||||||
lfs_ssize_t d_ = lfsr_ftree_read(lfs,
|
|
||||||
&file->mdir, &file->ftree,
|
|
||||||
pos_, buffer_, d, d);
|
|
||||||
if (d_ < 0) {
|
|
||||||
return d_;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos_ += d_;
|
|
||||||
buffer_ += d_;
|
|
||||||
size -= d_;
|
|
||||||
d -= d_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// found a hole? write zeros
|
|
||||||
memset(buffer_, 0, d);
|
memset(buffer_, 0, d);
|
||||||
|
|
||||||
pos_ += d;
|
pos_ += d;
|
||||||
@@ -10354,16 +10353,34 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unused buffer? we can move this where we need it
|
// bypass buffer?
|
||||||
if (file->buffer_size == 0) {
|
if ((lfs_size_t)d >= lfs->cfg->cache_size) {
|
||||||
// try to fill our buffer with some data
|
lfs_ssize_t d_ = lfsr_ftree_readnext(lfs,
|
||||||
file->buffer_pos = pos_;
|
&file->mdir, &file->ftree,
|
||||||
lfs_ssize_t d_ = lfsr_ftree_read(lfs, &file->mdir, &file->ftree,
|
pos_, buffer_, d);
|
||||||
pos_, file->buffer, d, lfs->cfg->cache_size);
|
|
||||||
if (d_ < 0) {
|
if (d_ < 0) {
|
||||||
|
LFS_ASSERT(d_ != LFS_ERR_NOENT);
|
||||||
return d_;
|
return d_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos_ += d_;
|
||||||
|
buffer_ += d_;
|
||||||
|
size -= d_;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unused buffer? we can move this where we need it
|
||||||
|
if (file->buffer_size == 0) {
|
||||||
|
// try to fill our buffer with some data
|
||||||
|
lfs_ssize_t d_ = lfsr_ftree_readnext(lfs,
|
||||||
|
&file->mdir, &file->ftree,
|
||||||
|
pos_, file->buffer, d);
|
||||||
|
if (d_ < 0) {
|
||||||
|
LFS_ASSERT(d != LFS_ERR_NOENT);
|
||||||
|
return d_;
|
||||||
|
}
|
||||||
|
|
||||||
|
file->buffer_pos = pos_;
|
||||||
file->buffer_size = d_;
|
file->buffer_size = d_;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -10725,7 +10742,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size) {
|
|||||||
|
|
||||||
lfs_ssize_t d = lfsr_ftree_read(lfs,
|
lfs_ssize_t d = lfsr_ftree_read(lfs,
|
||||||
&file->mdir, &file->ftree,
|
&file->mdir, &file->ftree,
|
||||||
0, file->buffer, size, size);
|
0, file->buffer, size);
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
err = d;
|
err = d;
|
||||||
goto failed;
|
goto failed;
|
||||||
@@ -10824,7 +10841,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size) {
|
|||||||
lfs_ssize_t d = lfsr_ftree_read(lfs,
|
lfs_ssize_t d = lfsr_ftree_read(lfs,
|
||||||
&file->mdir, &file->ftree,
|
&file->mdir, &file->ftree,
|
||||||
file->size - lfs_min32(size, file->size),
|
file->size - lfs_min32(size, file->size),
|
||||||
file->buffer, size, size);
|
file->buffer, size);
|
||||||
if (d < 0) {
|
if (d < 0) {
|
||||||
err = d;
|
err = d;
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|||||||
Reference in New Issue
Block a user