如何解决 Dart 解析大 Json 文件慢

2023-07-05 10:12:38 +08:00
 simman

最近在写 Flutter 应用,发现 Dart 解析比较大的 json 比较慢,会影响 UI 线程,使用 compute 的话,的确不影响 UI 线程了,但是解析起来更慢,想着可以使用 flutter rust bridge 做个 json 解析库,不过我用 rust 写个测试程序,发现解析 json 比 dart 快不了多少,各位有啥好意见没?

各语言测试:

time node index.js                           1.37s user 0.19s system 121% cpu 1.282 total
time go build && ./main                      1.59s user 0.02s system 80% cpu 2.002 total
time python3.9 main.py                       2.45s user 0.27s system 98% cpu 2.762 total
time cargo run --release                     2.46s user 0.42s system 97% cpu 2.972 total
time dart compile exe main.dart && bin/main  4.62s user 0.45s system 114% cpu 4.415 total

rust code:

use std::fs::File;
use std::io::{Read};

use serde_json::Value;

fn parse_json(contents: Vec<u8>) {
    let now = std::time::Instant::now();
    let _: Value = serde_json::from_slice(&contents).unwrap();
    let elapsed = now.elapsed();
    println!("elapsed: {:?}", elapsed);
}

fn main() {
    let contents = {
        let mut vec = Vec::new();
        // https://github.com/json-iterator/test-data/blob/master/large-file.json
        File::open("large-file.json").unwrap().read_to_end(&mut vec).unwrap();
        vec
    };
    for _ in 0..10 {
        parse_json(contents.clone());
    }
}

测试机器:MacBook Pro (16-inch, 2019) 2.3 GHz 八核 Intel Core i9 32 GB 2667 MHz DDR4

3654 次点击
所在节点    程序员
38 条回复
flyqie
2023-07-05 12:53:26 +08:00
json 真心不适合储存大量的数据。。

大量数据用 binary 比较好办。。
lysS
2023-07-05 13:44:02 +08:00
数据够大,调 ffi 有提升
honhon
2023-07-05 14:22:51 +08:00
数据量大 json 不适合
mxT52CRuqR6o5
2023-07-05 14:26:26 +08:00
如果结论没问题的话,应该就是 dartvm 比较菜了
janus77
2023-07-05 14:27:06 +08:00
如果是一次性,那么就一次解析完了重复使用
如果不是一次性,该考虑换 protobuf ,大数据用 json 本来就是不合理的选择,或者改需求了,在移动端设备上是否需要执行这种复杂逻辑
mxT52CRuqR6o5
2023-07-05 14:29:33 +08:00
还有一个问题,你说 dart 慢会「影响 UI 线程」,说明你在开发安卓
但 nodejs 等其他语言的测试应该都是直接跑在 mac 上的
这个性能是不太好直接比较的
Kaiv2
2023-07-05 15:28:43 +08:00
Mac Air M1 2020
Rust:
elapsed: 149.987542ms
elapsed: 107.580541ms
elapsed: 105.902334ms
elapsed: 105.940375ms
elapsed: 105.132084ms
elapsed: 105.841583ms
elapsed: 105.093ms
elapsed: 105.630708ms
elapsed: 105.344959ms
elapsed: 105.7735ms
Java:
elapsed: 263ms
elapsed: 189ms
elapsed: 44ms
elapsed: 50ms
elapsed: 41ms
elapsed: 56ms
elapsed: 39ms
elapsed: 53ms
elapsed: 39ms
elapsed: 39ms
Kaiv2
2023-07-05 15:29:50 +08:00
@Kaiv2 Java 使用的 jackson
ljsh093
2023-07-05 15:37:07 +08:00
@Kaiv2 #28 方便搞下 fastjson 吗
serco
2023-07-05 15:51:53 +08:00
@simman serde_json 浪费了不少时间在建 struct 上,不知道具体数据类型的话,还不如 json 这种 crate 快。

json parse 这种常规操作各个语言都有优化,差距不会特别大的,而且还要看具体做到了哪一步,是真的 parse 完建立了对应的类型,还是处在类似 pre-parsing 的状态临查询了才真的实例对应的类型。
Kaiv2
2023-07-05 15:52:21 +08:00
@ljsh093
Java: Fastjson 1.2.83
elapsed: 349ms
elapsed: 107ms
elapsed: 88ms
elapsed: 98ms
elapsed: 79ms
elapsed: 77ms
elapsed: 78ms
elapsed: 85ms
elapsed: 111ms
elapsed: 61ms
Java: Fastjson2 2.0.34
elapsed: 214ms
elapsed: 65ms
elapsed: 71ms
elapsed: 62ms
elapsed: 53ms
elapsed: 46ms
elapsed: 46ms
elapsed: 46ms
elapsed: 46ms
elapsed: 49ms
ljsh093
2023-07-05 16:39:02 +08:00
@Kaiv2 #31 这样一比确实 fast😅,不过 2 版本后还算可以
smirkcat
2023-07-05 16:41:45 +08:00
用字节的 ast 解析引擎
icyalala
2023-07-05 16:45:43 +08:00
@Kaiv2 再来个 C++ 的,也是 M1
simdjson:
18.44 ms
16.54 ms
16.05 ms
16.77 ms
16.41 ms
yyjson:
14.66 ms
14.37 ms
14.00 ms
13.89 ms
13.68 ms
rapidjson:
68.54 ms
67.82 ms
67.06 ms
67.04 ms
66.88 ms
GiantHard
2023-07-05 17:15:46 +08:00
@serco #30
说得对,crate json 要比 serde_json 快一倍( AMD Ryzen 7 5800U )

```rs
// build with cargo build -r
use std::fs::File;
use std::io::{Read};

use serde_json::Value;
use json;

fn parse_json(contents: &Vec<u8>) {
let now = std::time::Instant::now();
let _: Value = serde_json::from_slice(&contents).unwrap();
let elapsed = now.elapsed();
println!("serde_json: {:?}", elapsed);
}

fn parse_json2(contents: &str) {
let now = std::time::Instant::now();
let _ = json::parse(&contents).unwrap();
let elapsed = now.elapsed();
println!("json: {:?}", elapsed);
}

fn main() {
let contents = {
let mut vec = Vec::new();
// https://github.com/json-iterator/test-data/blob/master/large-file.json
File::open("large-file.json").unwrap().read_to_end(&mut vec).unwrap();
vec
};
for _ in 0..10 {
parse_json(&contents);
}
for _ in 0..10 {
// create json str from contents
let contents = String::from_utf8(contents.clone()).unwrap();
parse_json2(&contents);
}
}

```

```
serde_json: 182.566705ms
serde_json: 157.330185ms
serde_json: 151.551179ms
serde_json: 150.997928ms
serde_json: 158.290287ms
serde_json: 151.983899ms
serde_json: 152.493476ms
serde_json: 150.337436ms
serde_json: 151.174303ms
serde_json: 150.424319ms
json: 71.080736ms
json: 73.125015ms
json: 80.531158ms
json: 82.744729ms
json: 79.73645ms
json: 80.040878ms
json: 80.30521ms
json: 79.455428ms
json: 79.702968ms
json: 72.22127ms

________________________________________________________
Executed in 2.42 secs fish external
usr time 2.36 secs 0.00 micros 2.36 secs
sys time 0.06 secs 464.00 micros 0.06 secs
```

当然,你换个编程语言也可以比 serde_json 更快

```fs
/// build with dotnet build -c Release
open System.IO
open System.Text.Json
open System.Diagnostics

let json = File.ReadAllText("large-file.json")

for i in 1..10 do
let sw = Stopwatch.StartNew()
let jsonDocument = JsonDocument.Parse(json)
sw.Stop()
// print in ms
printfn "Elapsed: %dms" sw.ElapsedMilliseconds

printf "Done"
```

```
Elapsed: 185ms
Elapsed: 74ms
Elapsed: 73ms
Elapsed: 70ms
Elapsed: 75ms
Elapsed: 74ms
Elapsed: 67ms
Elapsed: 69ms
Elapsed: 73ms
Elapsed: 73ms
Done
________________________________________________________
Executed in 963.57 millis fish external
usr time 881.76 millis 0.00 micros 881.76 millis
sys time 86.87 millis 387.00 micros 86.48 millis
```
nuk
2023-07-05 17:32:12 +08:00
可以分块解析,或者自己做个匹配算法,理论上 json 解析只要不分配内存其实是很快的。那如果又要全部解析,又要快,那只能调用别的了,但是几百毫秒的这么做意义不大。
zibber
2023-07-06 00:07:04 +08:00
用 c++写个 api, 然后直接掉 c++的接口
kingzeus
2023-07-06 09:51:28 +08:00
1. 用 C++
2. dart 的话,可以考虑异步 Future/Isolate
3. 预处理,改成更加高效的数据格式

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/954190

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX