Skip to content

Commit ae1d9f3

Browse files
committed
Make HTTP JSON response encoding more efficient
Currently we use a fast JSON encoder to encode results. Then put that in a map, and run json.Marshal on that map. This PR changes that to generate the JSON response in a similar way to how fast encoder works, i.e. by operating on a bytes.Buffer directly.
1 parent d71ecc8 commit ae1d9f3

File tree

2 files changed

+26
-18
lines changed

2 files changed

+26
-18
lines changed

dgraph/cmd/alpha/http.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package alpha
1818

1919
import (
20+
"bytes"
2021
"context"
2122
"encoding/json"
2223
"fmt"
@@ -117,13 +118,27 @@ func queryHandler(w http.ResponseWriter, r *http.Request) {
117118
return
118119
}
119120

120-
response := map[string]interface{}{}
121+
var out bytes.Buffer
122+
writeEntry := func(key string, js []byte) {
123+
out.WriteRune('"')
124+
out.WriteString(key)
125+
out.WriteRune('"')
126+
out.WriteRune(':')
127+
out.Write(js)
128+
}
121129

122130
e := query.Extensions{
123131
Txn: resp.Txn,
124132
Latency: resp.Latency,
125133
}
126-
response["extensions"] = e
134+
js, err := json.Marshal(e)
135+
if err != nil {
136+
x.SetStatusWithData(w, x.Error, err.Error())
137+
return
138+
}
139+
out.WriteRune('{')
140+
writeEntry("extensions", js)
141+
out.WriteRune(',')
127142

128143
// User can either ask for schema or have a query.
129144
if len(resp.Schema) > 0 {
@@ -135,18 +150,16 @@ func queryHandler(w http.ResponseWriter, r *http.Request) {
135150
x.SetStatusWithData(w, x.Error, "Unable to marshal schema")
136151
return
137152
}
138-
mp := map[string]interface{}{}
139-
mp["schema"] = json.RawMessage(string(js))
140-
response["data"] = mp
141-
} else {
142-
response["data"] = json.RawMessage(string(resp.Json))
143-
}
144153

145-
if js, err := json.Marshal(response); err == nil {
146-
w.Write(js)
154+
writeEntry("data", nil)
155+
out.WriteRune('{')
156+
writeEntry("schema", js)
157+
out.WriteRune('}')
147158
} else {
148-
x.SetStatusWithData(w, x.Error, "Unable to marshal response")
159+
writeEntry("data", resp.Json)
149160
}
161+
out.WriteRune('}')
162+
w.Write(out.Bytes())
150163
}
151164

152165
func mutationHandler(w http.ResponseWriter, r *http.Request) {

query/outputnode.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"errors"
2222
"fmt"
2323
"sort"
24-
"strconv"
2524
"strings"
2625
"time"
2726

@@ -145,10 +144,8 @@ func (fj *fastJsonNode) IsEmpty() bool {
145144

146145
func valToBytes(v types.Val) ([]byte, error) {
147146
switch v.Tid {
148-
case types.BinaryID:
149-
// Encode to base64 and add "" around the value.
150-
b := fmt.Sprintf("%q", v.Value.([]byte))
151-
return []byte(b), nil
147+
case types.BinaryID, types.StringID, types.DefaultID:
148+
return []byte(fmt.Sprintf("%q", v.Value)), nil
152149
case types.IntID:
153150
return []byte(fmt.Sprintf("%d", v.Value)), nil
154151
case types.FloatID:
@@ -158,8 +155,6 @@ func valToBytes(v types.Val) ([]byte, error) {
158155
return []byte("true"), nil
159156
}
160157
return []byte("false"), nil
161-
case types.StringID, types.DefaultID:
162-
return []byte(strconv.Quote(v.Value.(string))), nil
163158
case types.DateTimeID:
164159
return v.Value.(time.Time).MarshalJSON()
165160
case types.GeoID:

0 commit comments

Comments
 (0)