gpt4 book ai didi

json - Crystal : slow json serialization of structs containing large strings

转载 作者:IT王子 更新时间:2023-10-29 01:41:11 26 4
gpt4 key购买 nike

我想知道为什么在 Crystal 中包含大字符串的结构的 json 序列化速度很慢。

下面的代码执行得相当差:

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

而以下 Javascript (Node.js) 或 Go 中的代码几乎是瞬时的(快 x10~x20 倍):

Node .js

page = { url: url, html: html }
JSON.stringify(page)

开始

type Page struct {
Uri string `json="uri"`
Html string `json="html"`
}

page = Page{ uri, html }

json, _ = json.Marshal(page)

考虑到 Crystal 通常非常快(与 Go 相当并且比 V8 Javascript 快得多)这让我有点想知道这里发生了什么。

我已经对 Crystal 代码进行了一些试验,似乎这里的罪魁祸首是大字符串的双引号字符串转义(这在序列化 json 对象时显然是必需的)。但是为什么要花这么长时间,我不知道(多次分配,副本?)。

请注意,在这些示例中,html 是一个大约 128KB 的 html 文件,使用任何可用的同步方法从磁盘加载。在对这些片段进行基准测试时,显然没有考虑文件读取操作。

最佳答案

我在 macOS x86_64 上用 crystal 0.25.1 (LLVM 6.0.1)、go 1.10.3、node.js v8.11.2 测试了这个。

所有示例都将一个 161 KB 的 html 文件读入一个字符串,打开一个临时文件并进行 10.000 次序列化页面对象迭代并将其写入文件。

这会生成大约 1.5 GB 的 JSON,系统具有非常快的 PCIe SSD,因此 IO 吞吐量不是瓶颈。

我选择将数据实际写入文件,以确保编译器无法优化函数调用。

Crystal

require "json"
require "tempfile"
url = "http://www.example.org"
html = File.read("index.html")

record(Page, uri : String, html : String) do
include JSON::Serializable
end

Tempfile.open("foo") do |io|
10_000.times do
page = Page.new(url, html)
page.to_json(io)
end
end

开始

package main

import (
"encoding/json"
"io/ioutil"
"log"
"os"
)

type Page struct {
Uri string `json="uri"`
Html string `json="html"`
}

func main() {
buf, err := ioutil.ReadFile("index.html")
if err != nil {
log.Fatal(err)
}
uri := "http://www.example.org"
html := string(buf)
file, err := ioutil.TempFile(os.TempDir(), "foo")
if err != nil {
log.Fatal(err)
}
defer os.Remove(file.Name())
for i := 0; i < 10000; i++ {
page := Page{uri, html}
json, err := json.Marshal(page)
if err != nil {
log.Fatal(err)
}
_, err = file.Write(json)
if err != nil {
log.Fatal(err)
}
}
}

Node.js

const fs = require('fs')
const tmp = require('tmp')
const uri = 'http://www.example.org'
const html = fs.readFileSync('index.html')

tmp.file((err, path, fd) => {
if (err) throw err;

for(let i = 0; i < 10000; i++) {
const page = { uri, html }
const json = JSON.stringify(page)
fs.writeSync(fd, json)
}
})

结果

  • 进行:10.88 秒,8.5 MB RAM
  • crystal:12.62 秒,2 MB RAM,慢 1.16 倍
  • node.js:101.82 秒,75 MB RAM,慢 9.36 倍

请注意,我使用 --release 编译了 Crystal 示例并更新了 0.25.1 的代码。

Node.js 示例使用 v8 而不是 v10,因为 v10 与我用于临时文件的 node-tmp npm 模块不兼容。

基准测试是在配备 i7-5557U CPU、16 GB RAM 和 1 TB PCIe SSD 的 2015 年初 13"Retina MacBook Pro 上完成的。

关于json - Crystal : slow json serialization of structs containing large strings,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47952457/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com