Skip to content

Commit 0fb4f5a

Browse files
committed
go: Reduce memory usage and improve speed of Decode by 26%
Use handwritten version of strings.Map. This avoids having to dynamically allocate and resize the byte slice, and allows the compiler to fully remove memory allocations from the operation. As a result, the time spent in StripCode is almost completely removed.
1 parent 83986da commit 0fb4f5a

2 files changed

Lines changed: 18 additions & 17 deletions

File tree

go/decode.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ func Decode(code string) (CodeArea, error) {
3131
}
3232
// Strip out separator character, padding characters and convert to upper
3333
// case.
34-
code = StripCode(code)
35-
codeLen := len(code)
34+
codeBytes := StripCode(code)
35+
codeLen := len(codeBytes)
3636
if codeLen < 2 {
3737
return area, errors.New("code too short")
3838
}
@@ -50,8 +50,8 @@ func Decode(code string) (CodeArea, error) {
5050
lng *= encBase
5151
height *= encBase
5252
if i < codeLen {
53-
lat += int64(strings.IndexByte(Alphabet, code[i]))
54-
lng += int64(strings.IndexByte(Alphabet, code[i+1]))
53+
lat += int64(strings.IndexByte(Alphabet, codeBytes[i]))
54+
lng += int64(strings.IndexByte(Alphabet, codeBytes[i+1]))
5555
height = 1
5656
}
5757
}
@@ -64,7 +64,7 @@ func Decode(code string) (CodeArea, error) {
6464
lng *= gridCols
6565
width *= gridCols
6666
if i < codeLen {
67-
dval := int64(strings.IndexByte(Alphabet, code[i]))
67+
dval := int64(strings.IndexByte(Alphabet, codeBytes[i]))
6868
lat += dval / gridCols
6969
lng += dval % gridCols
7070
height = 1

go/olc.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,19 +187,20 @@ func upper(b byte) byte {
187187
//
188188
// The code is truncated to the first 15 digits, as Decode won't use more,
189189
// to avoid underflow errors.
190-
func StripCode(code string) string {
191-
code = strings.Map(
192-
func(r rune) rune {
193-
if r == Separator || r == Padding {
194-
return -1
195-
}
196-
return rune(upper(byte(r)))
197-
},
198-
code)
199-
if len(code) > maxCodeLen {
200-
return code[:maxCodeLen]
190+
func StripCode(code string) []byte {
191+
result := make([]byte, maxCodeLen)
192+
pos := 0
193+
for _, r := range code {
194+
if r == Separator || r == Padding {
195+
continue
196+
}
197+
result[pos] = upper(byte(r))
198+
pos++
199+
if pos >= maxCodeLen {
200+
break
201+
}
201202
}
202-
return code
203+
return result[:pos]
203204
}
204205

205206
// Because the OLC codes are an area, they can't start at 180 degrees, because they would then have something > 180 as their upper bound.

0 commit comments

Comments
 (0)