10 |
10 |
11 import numpy as np |
11 import numpy as np |
12 |
12 |
13 |
13 |
14 class RingBuffer(object): |
14 class RingBuffer(object): |
15 def __init__(self, width=None, size=65536, padding=None): |
15 def __init__(self, width=None, size=131072, padding=None): |
16 self.size = size |
16 self.size = size |
17 self.padding = size if padding is None else padding |
17 self.padding = size if padding is None else padding |
18 shape = (self.size+self.padding,) |
18 shape = (self.size+self.padding,) |
19 if width : |
19 if width : |
20 shape += (width,) |
20 shape += (width,) |
21 self.buffer = np.zeros(shape) |
21 self.buffer = np.zeros(shape) |
22 self.counter = 0 |
22 self.cursor = 0 |
23 self.full = False |
|
24 |
23 |
25 def append(self, data): |
24 def append(self, data): |
26 """this is an O(n) operation""" |
25 """this is an O(n) operation""" |
27 data = data[-self.padding:] |
26 data = data[-self.size:] |
28 n = len(data) |
27 n = len(data) |
29 if self.remaining < n: self.compact() |
28 if self.size + self.padding - self.cursor < n: |
30 self.buffer[self.counter+self.size:][:n] = data |
29 self.compact() |
31 self.counter += n |
30 self.buffer[self.cursor:][:n] = data |
|
31 self.cursor += n |
32 |
32 |
33 @property |
33 @property |
34 def count(self): |
34 def count(self): |
35 return self.counter if not self.full else self.size |
35 return min(self.size, self.cursor) |
36 |
|
37 @property |
|
38 def remaining(self): |
|
39 return self.padding-self.counter |
|
40 |
36 |
41 @property |
37 @property |
42 def view(self): |
38 def view(self): |
43 """this is always an O(1) operation""" |
39 """this is always an O(1) operation""" |
44 return self.buffer[self.counter:][:self.size] |
40 return self.buffer[max(0, self.cursor - self.size):][:self.count] |
45 |
41 |
46 def compact(self): |
42 def compact(self): |
47 """ |
43 """ |
48 note: only when this function is called, is an O(size) performance hit incurred, |
44 note: only when this function is called, is an O(size) performance hit incurred, |
49 and this cost is amortized over the whole padding space |
45 and this cost is amortized over the whole padding space |
50 """ |
46 """ |
51 print 'compacting' |
47 print 'compacting' |
52 self.buffer[:self.size] = self.view |
48 self.buffer[:self.count] = self.view |
53 self.counter = 0 |
49 self.cursor -= self.size |
54 self.full = True |
|
55 |
50 |