Skip to content

Commit a3ccf8d

Browse files
committed
Improve ring buffer performance and add tests
1 parent 75d3102 commit a3ccf8d

File tree

5 files changed

+475
-224
lines changed

5 files changed

+475
-224
lines changed

example/main.go

+110-47
Original file line numberDiff line numberDiff line change
@@ -3,80 +3,143 @@ package main
33
import (
44
"fmt"
55

6-
"github.com/keithknott26/easyringbuffer"
6+
"github.com/keithknott26/easyringbuffer/ringbuffer"
77
)
88

99
type App struct {
10-
Info *easyringbuffer.StringRingBuffer
11-
Warn *easyringbuffer.StringRingBuffer
12-
Error *easyringbuffer.StringRingBuffer
13-
Fatal *easyringbuffer.StringRingBuffer
14-
Floats *easyringbuffer.Float64RingBuffer
10+
Info *ringbuffer.RingBuffer[string]
11+
Warn *ringbuffer.RingBuffer[string]
12+
Error *ringbuffer.RingBuffer[string]
13+
Fatal *ringbuffer.RingBuffer[string]
14+
Floats *ringbuffer.RingBuffer[float64]
1515
}
1616

1717
func NewApp() *App {
18+
// Initialize ring buffers with a capacity of 128 (must be a power of two)
19+
infoBuffer, _ := ringbuffer.NewRingBuffer
20+
warnBuffer, _ := ringbuffer.NewRingBuffer
21+
errorBuffer, _ := ringbuffer.NewRingBuffer
22+
fatalBuffer, _ := ringbuffer.NewRingBuffer
23+
floatBuffer, _ := ringbuffer.NewRingBuffer
24+
1825
return &App{
19-
//initialize the ring buffers with a length of 100
20-
Info: easyringbuffer.NewStringRingBuffer(100),
21-
Warn: easyringbuffer.NewStringRingBuffer(100),
22-
Error: easyringbuffer.NewStringRingBuffer(100),
23-
Fatal: easyringbuffer.NewStringRingBuffer(100),
24-
Floats: easyringbuffer.NewFloat64RingBuffer(100),
26+
Info: infoBuffer,
27+
Warn: warnBuffer,
28+
Error: errorBuffer,
29+
Fatal: fatalBuffer,
30+
Floats: floatBuffer,
2531
}
2632
}
2733

2834
func main() {
29-
// simulate INFO, WARN, ERROR, FATAL log messages
30-
infoText := "INFO: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
35+
// Simulate INFO, WARN, ERROR, FATAL log messages
36+
infoText := "INFO: Lorem ipsum dolor sit amet..."
3137
warnText := "WARN: Application has bad references"
3238
errorText := "ERROR: Line count not found"
3339
fatalText := "FATAL: Application failed to compile"
34-
pi := 3.145926
40+
pi := 3.1415926
3541

36-
// initialize the string ring buffer
42+
// Initialize the app with ring buffers
3743
app := NewApp()
3844

39-
// add the log messages to the string ring buffer
40-
app.Info.Add(infoText)
41-
app.Warn.Add(warnText)
42-
app.Error.Add(errorText)
43-
app.Fatal.Add(fatalText)
45+
// Add the log messages to the ring buffers
46+
app.Info.Enqueue(infoText)
47+
app.Warn.Enqueue(warnText)
48+
app.Error.Enqueue(errorText)
49+
app.Fatal.Enqueue(fatalText)
4450

45-
// add the floats onto the float64 ring buffer
46-
for i := 0; i <= 300; i += 1 {
47-
app.Floats.Add(float64(i) + pi)
51+
// Add float values to the float64 ring buffer
52+
for i := 0; i <= 300; i++ {
53+
app.Floats.Enqueue(float64(i) + pi)
4854
}
4955

50-
// print out the last 10 string messages on the buffer
51-
info := fmt.Sprintf("Last 10 INFO Messages: %s", app.Info.Last(10))
52-
warn := fmt.Sprintf("Last 10 WARN Messages: %s", app.Warn.Last(10))
53-
error := fmt.Sprintf("Last 10 ERROR Messages: %s", app.Error.Last(10))
54-
fatal := fmt.Sprintf("Last 10 FATAL Messages: %s", app.Fatal.Last(10))
55-
fmt.Println(info)
56-
fmt.Println(warn)
57-
fmt.Println(error)
58-
fmt.Println(fatal)
56+
// Print out the last 10 INFO messages
57+
infoMessages := getLastN(app.Info, 10)
58+
fmt.Printf("Last %d INFO Messages: %v\n", len(infoMessages), infoMessages)
59+
60+
// Similarly for other log levels
61+
warnMessages := getLastN(app.Warn, 10)
62+
fmt.Printf("Last %d WARN Messages: %v\n", len(warnMessages), warnMessages)
63+
64+
errorMessages := getLastN(app.Error, 10)
65+
fmt.Printf("Last %d ERROR Messages: %v\n", len(errorMessages), errorMessages)
5966

60-
// print out the last 10 float64 values on the buffer
61-
float := fmt.Sprintf("Last 10 Floats: %v", app.Floats.Last(10))
62-
fmt.Println(float)
67+
fatalMessages := getLastN(app.Fatal, 10)
68+
fmt.Printf("Last %d FATAL Messages: %v\n", len(fatalMessages), fatalMessages)
6369

64-
// print the float64 buffer capacity
65-
fmt.Println(app.Floats.BufCapacity())
70+
// Print out the last 10 float64 values
71+
floatValues := getLastN(app.Floats, 10)
72+
fmt.Printf("Last %d Floats: %v\n", len(floatValues), floatValues)
6673

67-
// print the float64 buffer length
68-
fmt.Println(app.Floats.Len())
74+
// Print the float64 buffer capacity and size
75+
fmt.Printf("Float Buffer Capacity: %d\n", app.Floats.Capacity())
76+
fmt.Printf("Float Buffer Size: %d\n", app.Floats.Size())
6977

70-
// print all the buffer values
71-
fmt.Println(app.Floats.Values())
78+
// Print all buffer values (may be large)
79+
allFloats := getAllValues(app.Floats)
80+
fmt.Printf("All Floats: %v\n", allFloats)
7281

73-
// print all the buffer values between position 1 and 15
74-
fmt.Println(app.Floats.Slice(1, 15))
82+
// Print buffer values between positions 1 and 15
83+
slice1 := getSlice(app.Floats, 1, 15)
84+
fmt.Printf("Floats from position 1 to 15: %v\n", slice1)
7585

76-
// print all the buffer values between position 10 and 25
77-
fmt.Println(app.Floats.Position(10, 25))
86+
// Print buffer values between positions 10 and 25
87+
slice2 := getSlice(app.Floats, 10, 25)
88+
fmt.Printf("Floats from position 10 to 25: %v\n", slice2)
7889

79-
// clear all the buffer values
90+
// Clear all buffer values
8091
app.Floats.Reset()
92+
fmt.Println("Float buffer reset.")
93+
94+
// Ensure the buffer is empty
95+
if app.Floats.IsEmpty() {
96+
fmt.Println("Float buffer is now empty.")
97+
}
98+
}
99+
100+
// Helper functions to retrieve values from the ring buffer
101+
102+
// getLastN retrieves the last n items from the ring buffer
103+
func getLastN[T any](rb *ringbuffer.RingBuffer[T], n int) []T {
104+
size := int(rb.Size())
105+
if n > size {
106+
n = size
107+
}
108+
result := make([]T, 0, n)
109+
for i := size - n; i < size; i++ {
110+
item, _ := rb.GetAt(i)
111+
result = append(result, item)
112+
}
113+
return result
114+
}
115+
116+
// getAllValues retrieves all items from the ring buffer
117+
func getAllValues[T any](rb *ringbuffer.RingBuffer[T]) []T {
118+
size := int(rb.Size())
119+
result := make([]T, 0, size)
120+
for i := 0; i < size; i++ {
121+
item, _ := rb.GetAt(i)
122+
result = append(result, item)
123+
}
124+
return result
125+
}
81126

127+
// getSlice retrieves items between start and end positions
128+
func getSlice[T any](rb *ringbuffer.RingBuffer[T], start, end int) []T {
129+
size := int(rb.Size())
130+
if start < 0 {
131+
start = 0
132+
}
133+
if end > size {
134+
end = size
135+
}
136+
if start >= end {
137+
return []T{}
138+
}
139+
result := make([]T, 0, end-start)
140+
for i := start; i < end; i++ {
141+
item, _ := rb.GetAt(i)
142+
result = append(result, item)
143+
}
144+
return result
82145
}

go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/keithknott26/easyringbuffer
2+
3+
go 1.23.1

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/keithknott26/easyringbuffer v0.0.0-20200116011729-75d310231b7a h1:C891BKvHNI9raHlCJtjO0+imHnqVxB2NlMaEJ/RF5GM=
2+
github.com/keithknott26/easyringbuffer v0.0.0-20200116011729-75d310231b7a/go.mod h1:h01TcxJRGkXdpUt0B5xNVaWjMZQjcivnY6tG8yBgh68=

0 commit comments

Comments
 (0)