Skip to content

Commit d9aecff

Browse files
authored
Improve marshal speed (#47)
* Add fast case for non-escaped inputs. * Add specialized float printing. ``` benchmark old ns/op new ns/op delta BenchmarkIter_MarshalJSONBuffer/apache_builds-32 287323 148202 -48.42% BenchmarkIter_MarshalJSONBuffer/canada-32 13529136 10290900 -23.94% BenchmarkIter_MarshalJSONBuffer/citm_catalog-32 1727759 1231152 -28.74% BenchmarkIter_MarshalJSONBuffer/github_events-32 147846 72801 -50.76% BenchmarkIter_MarshalJSONBuffer/gsoc-2018-32 7302709 3186714 -56.36% BenchmarkIter_MarshalJSONBuffer/instruments-32 405617 249186 -38.57% BenchmarkIter_MarshalJSONBuffer/numbers-32 1114819 803988 -27.88% BenchmarkIter_MarshalJSONBuffer/marine_ik-32 15554551 13492569 -13.26% BenchmarkIter_MarshalJSONBuffer/mesh-32 4519934 3556764 -21.31% BenchmarkIter_MarshalJSONBuffer/mesh.pretty-32 4542054 3540605 -22.05% BenchmarkIter_MarshalJSONBuffer/twitterescaped-32 1361729 653521 -52.01% BenchmarkIter_MarshalJSONBuffer/twitter-32 1361365 635662 -53.31% BenchmarkIter_MarshalJSONBuffer/random-32 1593711 927722 -41.79% BenchmarkIter_MarshalJSONBuffer/update-center-32 1599886 778478 -51.34% benchmark old MB/s new MB/s speedup BenchmarkIter_MarshalJSONBuffer/apache_builds-32 329.43 638.68 1.94x BenchmarkIter_MarshalJSONBuffer/canada-32 154.50 203.11 1.31x BenchmarkIter_MarshalJSONBuffer/citm_catalog-32 289.57 406.37 1.40x BenchmarkIter_MarshalJSONBuffer/github_events-32 360.71 732.54 2.03x BenchmarkIter_MarshalJSONBuffer/gsoc-2018-32 420.40 963.39 2.29x BenchmarkIter_MarshalJSONBuffer/instruments-32 267.03 434.67 1.63x BenchmarkIter_MarshalJSONBuffer/numbers-32 134.66 186.72 1.39x BenchmarkIter_MarshalJSONBuffer/marine_ik-32 117.59 135.56 1.15x BenchmarkIter_MarshalJSONBuffer/mesh-32 142.19 180.70 1.27x BenchmarkIter_MarshalJSONBuffer/mesh.pretty-32 141.50 181.52 1.28x BenchmarkIter_MarshalJSONBuffer/twitterescaped-32 342.88 714.45 2.08x BenchmarkIter_MarshalJSONBuffer/twitter-32 342.97 734.52 2.14x BenchmarkIter_MarshalJSONBuffer/random-32 289.55 497.42 1.72x BenchmarkIter_MarshalJSONBuffer/update-center-32 333.12 684.62 2.06x ```
1 parent ebc09ef commit d9aecff

4 files changed

Lines changed: 1235 additions & 22 deletions

File tree

appendfloat_f.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright 2009 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Modified for 'f' format with inlined variables.
6+
7+
package simdjson
8+
9+
import "math"
10+
11+
func appendFloatF(dst []byte, val float64) []byte {
12+
var prec int
13+
var bits uint64
14+
bits = math.Float64bits(val)
15+
//var float64info = floatInfo{mantbits: 52, expbits: 11, bias: -1023}
16+
const mantbits = 52
17+
const expbits = 11
18+
const bias = -1023
19+
//flt = &float64info
20+
21+
neg := bits>>(expbits+mantbits) != 0
22+
exp := int(bits>>mantbits) & (1<<expbits - 1)
23+
mant := bits & (uint64(1)<<mantbits - 1)
24+
25+
switch exp {
26+
case 0:
27+
// denormalized
28+
exp++
29+
30+
default:
31+
// add implicit top bit
32+
mant |= uint64(1) << mantbits
33+
}
34+
exp += bias
35+
36+
var digs decimalSlice
37+
// Use Ryu algorithm.
38+
var buf [32]byte
39+
digs.d = buf[:]
40+
ryuFtoaShortest(&digs, mant, exp-mantbits)
41+
// Precision for shortest representation mode.
42+
43+
prec = max(digs.nd-digs.dp, 0)
44+
return fmtF(dst, neg, digs, prec)
45+
}
46+
47+
type decimalSlice struct {
48+
d []byte
49+
nd, dp int
50+
neg bool
51+
}
52+
53+
// %f: -ddddddd.ddddd
54+
func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte {
55+
// sign
56+
if neg {
57+
dst = append(dst, '-')
58+
}
59+
60+
// integer, padded with zeros as needed.
61+
if d.dp > 0 {
62+
m := min(d.nd, d.dp)
63+
dst = append(dst, d.d[:m]...)
64+
for ; m < d.dp; m++ {
65+
dst = append(dst, '0')
66+
}
67+
} else {
68+
dst = append(dst, '0')
69+
}
70+
71+
// fraction
72+
if prec > 0 {
73+
dst = append(dst, '.')
74+
for i := 0; i < prec; i++ {
75+
ch := byte('0')
76+
if j := d.dp + i; 0 <= j && j < d.nd {
77+
ch = d.d[j]
78+
}
79+
dst = append(dst, ch)
80+
}
81+
}
82+
83+
return dst
84+
}
85+
86+
func min(a, b int) int {
87+
if a < b {
88+
return a
89+
}
90+
return b
91+
}
92+
93+
func max(a, b int) int {
94+
if a > b {
95+
return a
96+
}
97+
return b
98+
}

0 commit comments

Comments
 (0)