Skip to content

Commit ee55c6f

Browse files
⚡ Bolt: Optimize Reader.Read* methods to avoid reflection
Replaced `binary.Read` with direct `io.ReadFull` into stack-allocated buffers in `pkg/dicomio/reader.go`. This avoids reflection overhead and reduces memory allocations. Performance impact: - BenchmarkParse/NoOptions/1.dcm-4: ~14% faster - BenchmarkParse/SkipPixelData/1.dcm-4: ~25% faster - Consistent improvements across all benchmarks.
1 parent 6357e3e commit ee55c6f

1 file changed

Lines changed: 35 additions & 21 deletions

File tree

pkg/dicomio/reader.go

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -77,51 +77,65 @@ func (r *Reader) Read(p []byte) (int, error) {
7777

7878
// ReadUInt8 reads an uint8 from the underlying *Reader.
7979
func (r *Reader) ReadUInt8() (uint8, error) {
80-
var out uint8
81-
err := binary.Read(r, r.bo, &out)
82-
return out, err
80+
var buf [1]byte
81+
if _, err := io.ReadFull(r, buf[:]); err != nil {
82+
return 0, err
83+
}
84+
return buf[0], nil
8385
}
8486

8587
// ReadUInt16 reads an uint16 from the underlying *Reader.
8688
func (r *Reader) ReadUInt16() (uint16, error) {
87-
var out uint16
88-
err := binary.Read(r, r.bo, &out)
89-
return out, err
89+
var buf [2]byte
90+
if _, err := io.ReadFull(r, buf[:]); err != nil {
91+
return 0, err
92+
}
93+
return r.bo.Uint16(buf[:]), nil
9094
}
9195

9296
// ReadUInt32 reads an uint32 from the underlying *Reader.
9397
func (r *Reader) ReadUInt32() (uint32, error) {
94-
var out uint32
95-
err := binary.Read(r, r.bo, &out)
96-
return out, err
98+
var buf [4]byte
99+
if _, err := io.ReadFull(r, buf[:]); err != nil {
100+
return 0, err
101+
}
102+
return r.bo.Uint32(buf[:]), nil
97103
}
98104

99105
// ReadInt16 reads an int16 from the underlying *Reader.
100106
func (r *Reader) ReadInt16() (int16, error) {
101-
var out int16
102-
err := binary.Read(r, r.bo, &out)
103-
return out, err
107+
var buf [2]byte
108+
if _, err := io.ReadFull(r, buf[:]); err != nil {
109+
return 0, err
110+
}
111+
return int16(r.bo.Uint16(buf[:])), nil
104112
}
105113

106114
// ReadInt32 reads an int32 from the underlying *Reader.
107115
func (r *Reader) ReadInt32() (int32, error) {
108-
var out int32
109-
err := binary.Read(r, r.bo, &out)
110-
return out, err
116+
var buf [4]byte
117+
if _, err := io.ReadFull(r, buf[:]); err != nil {
118+
return 0, err
119+
}
120+
return int32(r.bo.Uint32(buf[:])), nil
111121
}
112122

113123
// ReadFloat32 reads a float32 from the underlying *Reader.
114124
func (r *Reader) ReadFloat32() (float32, error) {
115-
var out float32
116-
err := binary.Read(r, r.bo, &out)
117-
return out, err
125+
var buf [4]byte
126+
if _, err := io.ReadFull(r, buf[:]); err != nil {
127+
return 0, err
128+
}
129+
return math.Float32frombits(r.bo.Uint32(buf[:])), nil
118130
}
119131

120132
// ReadFloat64 reads a float64 from the underlying *Reader.
121133
func (r *Reader) ReadFloat64() (float64, error) {
122-
var out float64
123-
err := binary.Read(r, r.bo, &out)
124-
return out, err
134+
var buf [8]byte
135+
if _, err := io.ReadFull(r, buf[:]); err != nil {
136+
return 0, err
137+
}
138+
return math.Float64frombits(r.bo.Uint64(buf[:])), nil
125139
}
126140

127141
func internalReadString(data []byte, d *encoding.Decoder) (string, error) {

0 commit comments

Comments
 (0)