[PATCH hare 1/2] bufio: Fix excessive memmoves in buffered_read
Export this patch
The buffer contents are now only moved to index 0 whenever new data is
to be read from the underlying reader. The start of buffered data is
tracked by the new rpos field.
Some room for improvement remains (ring buffer, maybe?), but at least it
performs better than no buffering...
Signed-off-by: Lassi Pulkkinen <lassi@pulk.fi>
---
bufio/buffered.ha | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/bufio/buffered.ha b/bufio/buffered.ha
index e7c5f2e7..6e17eabb 100644
--- a/bufio/buffered.ha
@@ -33,6 +33,7 @@ export type bufstream = struct {
source: io::handle,
rbuffer: []u8,
wbuffer: []u8,
+ rpos: size,
ravail: size,
wavail: size,
flush: []u8,
@@ -79,6 +80,7 @@ export fn buffered(
rbuffer = rbuf,
wbuffer = wbuf,
flush = flush_default,
+ rpos = len(rbuf), // necessary for unread() before read()
...
};
};
@@ -135,10 +137,10 @@ export fn unread(s: io::handle, buf: []u8) void = {
case =>
abort("Attempted unread on unbuffered stream");
};
- assert(len(s.rbuffer) - s.ravail >= len(buf),
+ assert(s.rpos >= len(buf),
"Attempted to unread more data than buffer has available");
- let sl = s.rbuffer[..s.ravail];
- static insert(sl[0], buf...);
+ s.rbuffer[s.rpos - len(buf)..s.rpos] = buf;
+ s.rpos -= len(buf);
s.ravail += len(buf);
};
@@ -168,26 +170,25 @@ fn buffered_close_static(s: *io::stream) (void | io::error) = {
fn buffered_read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = {
assert(s.reader == &buffered_read);
let s = s: *bufstream;
- let n = if (len(buf) < len(s.rbuffer)) len(buf) else len(s.rbuffer);
- if (n > s.ravail) {
- let z = match (io::read(s.source, s.rbuffer[s.ravail..])) {
+
+ if (s.ravail < len(buf) && s.ravail < len(s.rbuffer)) {
+ s.rbuffer[..s.ravail] = s.rbuffer[s.rpos..s.rpos + s.ravail];
+ s.rpos = 0;
+ match (io::read(s.source, s.rbuffer[s.ravail..])) {
case let err: io::error =>
return err;
case io::EOF =>
if (s.ravail == 0) {
return io::EOF;
};
- yield 0z;
case let z: size =>
- yield z;
+ s.ravail += z;
};
- s.ravail += z;
- n = if (n > s.ravail) s.ravail else n;
- assert(n != 0);
};
- buf[..n] = s.rbuffer[..n];
- s.rbuffer[..len(s.rbuffer) - n] = s.rbuffer[n..];
+ const n = if (len(buf) < s.ravail) len(buf) else s.ravail;
+ buf[..n] = s.rbuffer[s.rpos..s.rpos + n];
+ s.rpos += n;
s.ravail -= n;
return n;
};
--
2.39.2
Thanks!
To git@git.sr.ht:~sircmpwn/hare
b0806f69..f22695bc master -> master
[PATCH hare 2/2] bufio: Skip flush byte search when none are set
Export this patch
Signed-off-by: Lassi Pulkkinen <lassi@pulk.fi>
---
bufio/buffered.ha | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/bufio/buffered.ha b/bufio/buffered.ha
index 6e17eabb..982f481a 100644
--- a/bufio/buffered.ha
@@ -199,11 +199,13 @@ fn buffered_write(s: *io::stream, buf: const []u8) (size | io::error) = {
let buf = buf;
let doflush = false;
- for (let i = 0z; i < len(buf); i += 1) {
- for (let j = 0z; j < len(s.flush); j += 1) {
- if (buf[i] == s.flush[j]) {
- doflush = true;
- break;
+ if (len(s.flush) != 0) {
+ for (let i = 0z; i < len(buf); i += 1) :search {
+ for (let j = 0z; j < len(s.flush); j += 1) {
+ if (buf[i] == s.flush[j]) {
+ doflush = true;
+ break :search;
+ };
};
};
};
--
2.39.2
hare/patches: SUCCESS in 1m41s
[bufio: Fix excessive memmoves in buffered_read][0] from [Lassi Pulkkinen][1]
[0]: https://lists.sr.ht/~sircmpwn/hare-dev/patches/39355
[1]: mailto:lassi@pulk.fi
✓ #948473 SUCCESS hare/patches/alpine.yml https://builds.sr.ht/~sircmpwn/job/948473
✓ #948474 SUCCESS hare/patches/freebsd.yml https://builds.sr.ht/~sircmpwn/job/948474
Was this flagged as superseded by accident? This is the newest version.