Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
memoises decoded column arrays per block, so each is decoded once. ~50% less
time on a wide `-r … --tsv` over a 1 M-row file; output byte-identical. The
cache is region-mode only, so a sequential full scan is unaffected.
- **Tabix range queries reuse the line buffer.** `TabixInputStream` allocated and
freed an htslib `kstring` per record; it now keeps one buffer for the whole
scan (htslib reallocs only when a line outgrows it). Output unchanged.

### Fixed
- **bigWig/bigBed misaligned read (aarch64 correctness).** libBigWig read each
Expand Down
12 changes: 7 additions & 5 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,10 @@ class TabixInputStream : public arrow::io::InputStream {
size_t pos_ = 0;
bool eof_ = false;
bool closed_ = false;
// Reused across records: htslib's line reader (bgzf_getline) resets `l` and
// reallocs `s` only when a line outgrows it, so keeping one buffer for the
// whole scan avoids a malloc+free per record. Freed once in the destructor.
kstring_t ks_ = {0, 0, nullptr};
public:
static std::string open(const std::string& path,
const std::string& region,
Expand Down Expand Up @@ -1697,6 +1701,7 @@ class TabixInputStream : public arrow::io::InputStream {
for (auto* it : iters_) if (it) tbx_itr_destroy(it);
if (tbx_) tbx_destroy(tbx_);
if (fp_) hts_close(fp_);
if (ks_.s) free(ks_.s);
}

arrow::Status Close() override { closed_ = true; return arrow::Status::OK(); }
Expand Down Expand Up @@ -1727,19 +1732,16 @@ class TabixInputStream : public arrow::io::InputStream {
}
private:
bool fetch_next_line() {
kstring_t s = {0, 0, nullptr};
while (cur_iter_ < iters_.size()) {
int r = tbx_itr_next(fp_, tbx_, iters_[cur_iter_], &s);
int r = tbx_itr_next(fp_, tbx_, iters_[cur_iter_], &ks_);
if (r >= 0) {
buf_.assign(s.s, s.l);
buf_.assign(ks_.s, ks_.l);
buf_ += '\n';
pos_ = 0;
if (s.s) free(s.s);
return true;
}
++cur_iter_;
}
if (s.s) free(s.s);
eof_ = true;
return false;
}
Expand Down
Loading