I'm wondering why json serialization of structs containing large strings is slow in Crystal.
The following code performs rather poorly:
struct Page
include AutoJson
field :uri, String
field :html, String
end
page = Page.new(url, html) # html is a string containing ±128KB of html
page.to_json
Whereas the following code in Javascript (Node.js) or Go is pretty much instantaneous (like x10~x20 times faster):
Node.js
page = { url: url, html: html }
JSON.stringify(page)
Go
type Page struct {
Uri string `json="uri"`
Html string `json="html"`
}
page = Page{ uri, html }
json, _ = json.Marshal(page)
Considering Crystal is usually very fast (on par with Go and much faster than V8 Javascript) it kinda left me wondering what was going on here.
I've been experimenting with the Crystal code a little bit and it seems as if the incriminating bit here is the double-quote string escaping of large strings (which is obviously required when serializing json objects). But why would it take so long, I don't know (multiple allocations, copies?).
For the record, in these example, html
is a roughly 128KB html file loaded from disk using whatever synchronous method is available. File reading operations are obviously not taken into consideration when benchmarking these snippets.