-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathio_writer_vs_buffered_io_writer.go
139 lines (112 loc) · 2.89 KB
/
io_writer_vs_buffered_io_writer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package main
import (
"fmt"
"os"
"time"
)
const (
SOME_TEXT = "SOME TEXTTT"
)
type BufferedWriter struct {
file *os.File
buffer []byte
bufferEndIndex int
}
// Option function to modify BufferedWriter
type Option func(*BufferedWriter)
func NewBufferedWriter(options ...Option) *BufferedWriter {
bw := &BufferedWriter{
buffer: make([]byte, 4096),
bufferEndIndex: 0,
}
for _, opt := range options {
opt(bw)
}
return bw
}
// WithFile, option to set file for BufferedWriter
func WithFile(file *os.File) Option {
return func(bw *BufferedWriter) {
bw.file = file
}
}
// WithBufferSize, option to set buffer size for BufferedWriter
func WithBufferSize(size int) Option {
return func(bw *BufferedWriter) {
bw.buffer = make([]byte, size)
}
}
func (w *BufferedWriter) Write(content []byte) {
if len(content) >= len(w.buffer) {
// Write directly into file since buffer size is not enough for content
// Write current buffered content into file
w.Flush()
// Write the entire content into file first
w.file.Write(content)
} else {
if w.bufferEndIndex+len(content) > len(w.buffer) {
// Write current buffered content into file since buffer size is not enough for current buffered + incoming content
w.Flush()
}
// Copy incoming content into buffer
copy(w.buffer[w.bufferEndIndex:], content)
// Update buffer end index
w.bufferEndIndex += len(content)
}
}
func (w *BufferedWriter) Flush() {
// Write into file and update end index to 0
w.file.Write(w.buffer[0:w.bufferEndIndex])
w.bufferEndIndex = 0
}
func (w *BufferedWriter) WriteString(content string) {
w.Write([]byte(content))
}
func WriteNormally(filePath string, isLongContent bool) {
outputFile, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil {
panic(err)
}
defer outputFile.Close()
if isLongContent {
for i := 0; i < 999999; i++ {
outputFile.WriteString(SOME_TEXT)
}
} else {
outputFile.WriteString(SOME_TEXT)
}
}
func WriteUsingBuffer(filePath string, isLongContent bool) {
outputFile, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil {
panic(err)
}
defer outputFile.Close()
writer := NewBufferedWriter(
WithFile(outputFile),
WithBufferSize(8192),
)
defer writer.Flush()
if isLongContent {
for i := 0; i < 999999; i++ {
writer.WriteString(SOME_TEXT)
}
} else {
writer.WriteString(SOME_TEXT)
}
}
func main() {
normalFilePath := "normal_write.txt"
bufferedFilePath := "buffered_write.txt"
start := time.Now()
WriteNormally(normalFilePath, true)
elapsed := time.Since(start)
fmt.Printf("WriteNormally took %s\n", elapsed)
os.Remove(normalFilePath)
start = time.Now()
WriteUsingBuffer(bufferedFilePath, true)
elapsed = time.Since(start)
fmt.Printf("WriteUsingBuffer took %s\n", elapsed)
os.Remove(bufferedFilePath)
fmt.Println("Using Buffer Reduced Unnecessary I/O Time!!!")
}