JSON ayrıştırma ve yazma
C++'tan 1,12 kat hızlı1 MB üretilmiş JSON · ayrıştırma, gezinme, yeniden yazma. Çubuk uzunsa daha hızlı.
Metin ve veri
Program içinde üretilen yaklaşık 1 MB JSON ayrıştırılır, kayıtları gezilir ve yeniden yazılır; yazılan metin girdiyle karşılaştırılır. Metin taramayı, dinamik değerleri ve metin birleştirmeyi ölçer.
Bu sayfayı KabaLang ile yazılmış sunucu sundu.
Canlı ölçüm
JSON ayrıştırma ve yazma tarayıcınızda, WebAssembly ile koşar: KabaLang, C++, JavaScript ve Python. Ölçüm sayfası bu testi seçili açar; sonuçlar cihazınızda kalır.
1 MB üretilmiş JSON · ayrıştırma, gezinme, yeniden yazma. Çubuk uzunsa daha hızlı.
| Dil | En iyi | Ortalama | Derleme | İkili boyutu |
|---|---|---|---|---|
| KabaLang | 15,3 ms | 15,7 ms | 868 ms | 1.018 KB |
| C++ | 17,1 ms | 17,7 ms | 970 ms | 53 KB |
| Python | 46,0 ms | 47,3 ms | – | – |
Ne ölçüyor?
Kategori: Metin ve veri. Metin bölme, sözlük, JSON ayrıştırma ve yazma. Üç program da aynı algoritmayı aynı adımlarla uygular ve aynı çıktıyı üretmek zorundadır; çıktı tutmazsa ölçüm geçersiz sayılır.
8000 118673 1870 303972000 1057984 1Derleme
kabalang derle program.kbl -o program
./programclang++ -O2 -o program program.cpp
./programpython3 program.py-O 2; program, çalışma zamanıyla
birlikte bağlama anında eniyilenir ve statik bağlanır (tek, bağımlılıksız ikili).-O2; standart kütüphaneye dinamik bağlı.Kaynak
Aşağıdaki dosyalar ölçülen programların kendisidir.
N = 8000
parcalar: liste<metin> = []
dongu i icinde 0..<N:
aktif = "false"
eger i % 3 == 0:
aktif = "true"
parcalar.ekle(f"{{\"ad\":\"kullanici{i}\",\"adres\":{{\"posta\":{10000 + i * 7 % 90000},\"sehir\":\"sehir{i % 81}\"}},\"aktif\":{aktif},\"etiketler\":[\"e{i % 7}\",\"e{i % 11}\"],\"id\":{i},\"puan\":{i * 37 % 1000},\"yas\":{20 + i % 50}}}")
girdi = "{\"kayitlar\":[" + parcalar.birlestir(",") + "]}"
belge = json.coz(girdi)
toplam_yas = 0
etiket_sayisi = 0
posta_toplami = 0
dongu kayit icinde belge["kayitlar"]:
eger kayit["aktif"]:
toplam_yas += sayi(kayit["yas"])
dongu etiket icinde kayit["etiketler"]:
eger etiket == "e3":
etiket_sayisi += 1
posta_toplami += sayi(kayit["adres"]["posta"])
cikti = json.yaz(belge)
ayni = 0
eger cikti == girdi:
ayni = 1
yazdir(belge["kayitlar"].uzunluk(), toplam_yas, etiket_sayisi, posta_toplami, cikti.uzunluk(), ayni)// C++ standart kütüphanesinde JSON yok: küçük bir ayrıştırıcı + yazıcı.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <variant>
#include <vector>
struct Deger;
using Dizi = std::vector<Deger>;
using Nesne = std::map<std::string, Deger>;
struct Deger {
std::variant<std::nullptr_t, bool, long long, double, std::string, Dizi, Nesne> v;
};
struct Ayristirici {
const std::string &s;
size_t i = 0;
void bosluk() {
while (i < s.size() && (s[i] == ' ' || s[i] == '\n' || s[i] == '\r' || s[i] == '\t')) ++i;
}
std::string metin() {
std::string m;
++i; // "
while (s[i] != '"') {
char c = s[i++];
if (c != '\\') {
m += c;
continue;
}
char k = s[i++];
switch (k) {
case 'n': m += '\n'; break;
case 't': m += '\t'; break;
case 'r': m += '\r'; break;
case 'b': m += '\b'; break;
case 'f': m += '\f'; break;
case 'u': {
unsigned kod = std::stoul(s.substr(i, 4), nullptr, 16);
i += 4;
if (kod < 0x80) {
m += char(kod);
} else if (kod < 0x800) {
m += char(0xC0 | (kod >> 6));
m += char(0x80 | (kod & 0x3F));
} else {
m += char(0xE0 | (kod >> 12));
m += char(0x80 | ((kod >> 6) & 0x3F));
m += char(0x80 | (kod & 0x3F));
}
break;
}
default: m += k;
}
}
++i; // "
return m;
}
Deger deger() {
bosluk();
char c = s[i];
if (c == '{') {
Nesne n;
++i;
bosluk();
if (s[i] == '}') { ++i; return {n}; }
while (true) {
bosluk();
std::string anahtar = metin();
bosluk();
++i; // :
n[anahtar] = deger();
bosluk();
if (s[i++] == '}') break;
}
return {std::move(n)};
}
if (c == '[') {
Dizi d;
++i;
bosluk();
if (s[i] == ']') { ++i; return {d}; }
while (true) {
d.push_back(deger());
bosluk();
if (s[i++] == ']') break;
}
return {std::move(d)};
}
if (c == '"') return {metin()};
if (s.compare(i, 4, "true") == 0) { i += 4; return {true}; }
if (s.compare(i, 5, "false") == 0) { i += 5; return {false}; }
if (s.compare(i, 4, "null") == 0) { i += 4; return {nullptr}; }
size_t bas = i;
bool ondalik = false;
while (i < s.size() && (isdigit(s[i]) || s[i] == '-' || s[i] == '+' || s[i] == '.' || s[i] == 'e' || s[i] == 'E')) {
if (s[i] == '.' || s[i] == 'e' || s[i] == 'E') ondalik = true;
++i;
}
if (ondalik) return {std::strtod(s.c_str() + bas, nullptr)};
return {std::strtoll(s.c_str() + bas, nullptr, 10)};
}
};
void metin_yaz(std::string &c, const std::string &m) {
c += '"';
for (unsigned char k : m) {
if (k == '"') c += "\\\"";
else if (k == '\\') c += "\\\\";
else if (k == '\n') c += "\\n";
else if (k < 0x20) {
char t[8];
std::snprintf(t, sizeof t, "\\u%04x", k);
c += t;
} else c += char(k);
}
c += '"';
}
void yaz(std::string &c, const Deger &d) {
if (std::holds_alternative<std::nullptr_t>(d.v)) c += "null";
else if (auto b = std::get_if<bool>(&d.v)) c += *b ? "true" : "false";
else if (auto s = std::get_if<long long>(&d.v)) c += std::to_string(*s);
else if (auto o = std::get_if<double>(&d.v)) {
char t[32];
std::snprintf(t, sizeof t, "%.17g", *o);
c += t;
} else if (auto m = std::get_if<std::string>(&d.v)) metin_yaz(c, *m);
else if (auto dz = std::get_if<Dizi>(&d.v)) {
c += '[';
for (size_t i = 0; i < dz->size(); ++i) {
if (i) c += ',';
yaz(c, (*dz)[i]);
}
c += ']';
} else {
const Nesne &n = std::get<Nesne>(d.v);
c += '{';
bool ilk = true;
for (const auto &[k, v] : n) {
if (!ilk) c += ',';
ilk = false;
metin_yaz(c, k);
c += ':';
yaz(c, v);
}
c += '}';
}
}
int main() {
const int N = 8000;
std::string girdi = "{\"kayitlar\":[";
for (int i = 0; i < N; ++i) {
if (i) girdi += ',';
girdi += "{\"ad\":\"kullanici" + std::to_string(i) + "\",\"adres\":{\"posta\":" +
std::to_string(10000 + i * 7 % 90000) + ",\"sehir\":\"sehir" + std::to_string(i % 81) +
"\"},\"aktif\":" + (i % 3 == 0 ? "true" : "false") + ",\"etiketler\":[\"e" +
std::to_string(i % 7) + "\",\"e" + std::to_string(i % 11) + "\"],\"id\":" + std::to_string(i) +
",\"puan\":" + std::to_string(i * 37 % 1000) + ",\"yas\":" + std::to_string(20 + i % 50) + "}";
}
girdi += "]}";
Ayristirici a{girdi};
Deger belge = a.deger();
long long toplam_yas = 0, etiket_sayisi = 0, posta_toplami = 0;
const Dizi &kayitlar = std::get<Dizi>(std::get<Nesne>(belge.v).at("kayitlar").v);
for (const Deger &kd : kayitlar) {
const Nesne &kayit = std::get<Nesne>(kd.v);
if (std::get<bool>(kayit.at("aktif").v)) toplam_yas += std::get<long long>(kayit.at("yas").v);
for (const Deger &e : std::get<Dizi>(kayit.at("etiketler").v))
if (std::get<std::string>(e.v) == "e3") ++etiket_sayisi;
posta_toplami += std::get<long long>(std::get<Nesne>(kayit.at("adres").v).at("posta").v);
}
std::string cikti;
yaz(cikti, belge);
std::cout << kayitlar.size() << " " << toplam_yas << " " << etiket_sayisi << " " << posta_toplami << " "
<< cikti.size() << " " << (cikti == girdi ? 1 : 0) << std::endl;
return 0;
}import json
N = 8000
parcalar = []
for i in range(N):
aktif = "true" if i % 3 == 0 else "false"
parcalar.append(
f'{{"ad":"kullanici{i}","adres":{{"posta":{10000 + i * 7 % 90000},"sehir":"sehir{i % 81}"}},'
f'"aktif":{aktif},"etiketler":["e{i % 7}","e{i % 11}"],"id":{i},"puan":{i * 37 % 1000},"yas":{20 + i % 50}}}'
)
girdi = '{"kayitlar":[' + ",".join(parcalar) + "]}"
belge = json.loads(girdi)
toplam_yas = 0
etiket_sayisi = 0
posta_toplami = 0
for kayit in belge["kayitlar"]:
if kayit["aktif"]:
toplam_yas += kayit["yas"]
for etiket in kayit["etiketler"]:
if etiket == "e3":
etiket_sayisi += 1
posta_toplami += kayit["adres"]["posta"]
cikti = json.dumps(belge, separators=(",", ":"), sort_keys=True)
print(len(belge["kayitlar"]), toplam_yas, etiket_sayisi, posta_toplami, len(cikti), 1 if cikti == girdi else 0)// Anahtarları sıralı yazar (Python: sort_keys=True; KabaLang ve C++ sözlükleri sıralıdır).
function sirali(anahtar, deger) {
if (deger && typeof deger === "object" && !Array.isArray(deger)) {
return Object.fromEntries(Object.keys(deger).sort().map((k) => [k, deger[k]]));
}
return deger;
}
export default function program(yaz = console.log) {
const N = 8000;
const parcalar = [];
for (let i = 0; i < N; i++) {
const aktif = i % 3 === 0 ? "true" : "false";
parcalar.push(
`{"ad":"kullanici${i}","adres":{"posta":${10000 + i * 7 % 90000},"sehir":"sehir${i % 81}"},` +
`"aktif":${aktif},"etiketler":["e${i % 7}","e${i % 11}"],"id":${i},"puan":${i * 37 % 1000},"yas":${20 + i % 50}}`
);
}
const girdi = '{"kayitlar":[' + parcalar.join(",") + "]}";
const belge = JSON.parse(girdi);
let toplamYas = 0, etiketSayisi = 0, postaToplami = 0;
for (const kayit of belge.kayitlar) {
if (kayit.aktif) toplamYas += kayit.yas;
for (const etiket of kayit.etiketler) {
if (etiket === "e3") etiketSayisi++;
}
postaToplami += kayit.adres.posta;
}
const cikti = JSON.stringify(belge, sirali);
yaz([belge.kayitlar.length, toplamYas, etiketSayisi, postaToplami, cikti.length, cikti === girdi ? 1 : 0].join(" "));
}
// `node program.js` ile de koşar (tarayıcıda ölçüm işçisi program()ı çağırır).
if (globalThis.process?.argv?.[1]?.endsWith("program.js")) program();