authorgravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2019-11-11 00:26:40+11:00
committergravatar for quae@daurnimator.comdaurnimator <quae@daurnimator.com> 2019-11-25 09:26:32+11:00
loge810f485ab6395357febc85b65afddae5b061955
treedc56ad17efb5b9c032e5cc0feb86b1a3fd3b368c
parent01b2a56225038537f525f52b0d9c821ffa77b90b
signaturelock-open Commit is signed but in an unrecognized format.

std: add optimization to fifo if size is power of two


1 files changed, 30 insertions(+), 7 deletions(-)

lib/std/fifo.zig+30-7
...@@ -12,6 +12,8 @@ const testing = std.testing;...@@ -12,6 +12,8 @@ const testing = std.testing;
12pub fn FixedSizeFifo(comptime T: type) type {12pub fn FixedSizeFifo(comptime T: type) type {
13 const autoalign = false;13 const autoalign = false;
1414
15 const powers_of_two = true;
16
15 return struct {17 return struct {
16 allocator: *Allocator,18 allocator: *Allocator,
17 buf: []T,19 buf: []T,
...@@ -68,10 +70,10 @@ pub fn FixedSizeFifo(comptime T: type) type {...@@ -68,10 +70,10 @@ pub fn FixedSizeFifo(comptime T: type) type {
68 }70 }
6971
70 /// Ensure that the buffer can fit at least `size` items72 /// Ensure that the buffer can fit at least `size` items
71 pub fn ensureCapacity(self: *Self, size: usize) error{OutOfMemory}!void {73 pub fn ensureCapacity(self: *Self, size: usize) !void {
72 if (self.buf.len >= size) return;74 if (self.buf.len >= size) return;
73 self.realign();75 self.realign();
74 const new_size = math.ceilPowerOfTwo(usize, size) catch return error.OutOfMemory;76 const new_size = if (powers_of_two) math.ceilPowerOfTwo(usize, size) catch return error.OutOfMemory else size;
75 self.buf = try self.allocator.realloc(self.buf, new_size);77 self.buf = try self.allocator.realloc(self.buf, new_size);
76 }78 }
7779
...@@ -124,10 +126,19 @@ pub fn FixedSizeFifo(comptime T: type) type {...@@ -124,10 +126,19 @@ pub fn FixedSizeFifo(comptime T: type) type {
124 @memset(unused2.ptr, undefined, unused2.len);126 @memset(unused2.ptr, undefined, unused2.len);
125 }127 }
126 }128 }
127 self.head = (self.head + count) % self.buf.len;129 if (autoalign and self.count == count) {
128 self.count -= count;
129 if (autoalign and self.count == 0)
130 self.head = 0;130 self.head = 0;
131 self.count = 0;
132 } else {
133 var head = self.head + count;
134 if (powers_of_two) {
135 head &= self.buf.len - 1;
136 } else {
137 head %= self.buf.len;
138 }
139 self.head = head;
140 self.count -= count;
141 }
131 }142 }
132143
133 /// Read the next item from the fifo144 /// Read the next item from the fifo
...@@ -225,7 +236,13 @@ pub fn FixedSizeFifo(comptime T: type) type {...@@ -225,7 +236,13 @@ pub fn FixedSizeFifo(comptime T: type) type {
225 fn rewind(self: *Self, size: usize) void {236 fn rewind(self: *Self, size: usize) void {
226 assert(self.writableLength() >= size);237 assert(self.writableLength() >= size);
227238
228 self.head = (self.head + (self.buf.len - size)) % self.buf.len;239 var head = self.head + (self.buf.len - size);
240 if (powers_of_two) {
241 head &= self.buf.len - 1;
242 } else {
243 head %= self.buf.len;
244 }
245 self.head = head;
229 self.count += size;246 self.count += size;
230 }247 }
231248
...@@ -246,7 +263,13 @@ pub fn FixedSizeFifo(comptime T: type) type {...@@ -246,7 +263,13 @@ pub fn FixedSizeFifo(comptime T: type) type {
246 if (offset >= self.count)263 if (offset >= self.count)
247 return error.EndOfStream;264 return error.EndOfStream;
248265
249 return self.buf[(self.head + offset) % self.buf.len];266 var index = self.head + offset;
267 if (powers_of_two) {
268 index &= self.buf.len - 1;
269 } else {
270 index %= self.buf.len;
271 }
272 return self.buf[index];
250 }273 }
251 };274 };
252}275}