[dbohdan] 2017-02-03: This benchmark compares the speed with which various [JSON] libraries for Tcl can extract a deeply nested string value from a http://mtgjson.com/%|%large JSON blob%|% (circa 18 MiB). The comparison may help you choose one out of a growing number of similar JSON-parsing libraries for Tcl, but, as any microbenchmark, it has a limited scope. Libraries may be faster or slower under different circumstances. ** How to run the benchmark ** Install [Git], [jq], Tcl 8.6, [Tcllib] and (optionally) [wiki-reaper]. Install the Tcl extensions [rl_json], SQLite with [JSON1], [tcl-duktape] and [yajl-tcl]. Then run the POSIX shell commands below. ======none mkdir jsonbench cd jsonbench git clone https://github.com/dbohdan/jimhttp curl -sf -o AllSets.json.zip https://mtgjson.com/json/AllSets.json.zip unzip AllSets.json.zip rm AllSets.json.zip # Instead of running the next command you can manually copy the code from the # "Code" section of this wiki page and save it as jsonbench.tcl. wiki-reaper 48500 3 | tee jsonbench.tcl tclsh jsonbench.tcl ====== ** Sample results ** These results are from running the benchmark on WSL on an a Phenom II X4 955 CPU with no heavy tasks running in the background. *** 5 iterations *** ======none Package versions: Tcllib json -- 1.1.2 duktape -- 0.3.0 jimhttp json -- 2.0.0 rl_json -- 0.9.6 sqlite3 -- 3.16.2 yajltcl -- 1.6.1 Running the benchmark with 5 iterations for each library jq: 987.6532 tcl-duktape: 1662.43 jimhttp JSON: 21084.0598 rl_json: 87.88680000000001 Tcllib JSON: 21791.257 SQLite JSON1: 60.934 yajl-tcl: 274.4032 ====== *** 20 iterations *** ======none Package versions: Tcllib json -- 1.1.2 duktape -- 0.3.0 jimhttp json -- 2.0.0 rl_json -- 0.9.6 sqlite3 -- 3.16.2 yajltcl -- 1.6.1 Found AllSets.json Running the benchmark with 20 iterations for each library jq: 985.70005 tcl-duktape: 1686.35365 jimhttp JSON: 21613.87105 rl_json: 25.7313 Tcllib JSON: 22730.7258 SQLite JSON1: 60.397800000000004 yajl-tcl: 276.35535 ====== ** Code ** ====== #! /usr/bin/env tclsh # version 0.3.0 package require fileutil puts {Package versions:} puts "Tcllib json -- [package require json]" source jimhttp/json.tcl puts "duktape -- [package require duktape]" package require duktape::oo puts "jimhttp json -- $::json::version" puts "rl_json -- [package require rl_json]" puts "sqlite3 -- [package require sqlite3]" puts "yajltcl -- [package require yajltcl]" puts {} proc ms timeResult { return [expr {[lindex $timeResult 0] / 1000}] } proc benchmark {command data times result} { return [ms [time { set actualResult [$command $data] if {$actualResult ne $result} {error "bad result: \"$actualResult\""} } $times]] } proc jq data { return [exec jq -r {.INV.cards[68].flavor} << $data] } proc duktape data { set j [::duktape::oo::JSON new $::duk $data] set result [$j get INV cards 68 flavor] $j destroy return $result } proc jimhttp-json data { return [dict get [::json::parse $data] INV cards 68 flavor] } proc rl_json data { return [::rl_json::json get $data INV cards 68 flavor] } proc tcllib-json data { return [dict get [lindex [dict get \ [::json::json2dict $data] INV cards] 68] flavor] } proc sqlite3-json1 data { set result [lindex [::sq3 eval { select json_extract($data, '$.INV.cards[68].flavor') }] 0] return $result } proc yajltcl data { return [dict get [lindex [dict get \ [::yajl::json2dict $data] INV cards] 68] flavor] } proc main {} { set times 5 set value {Children claim no two feathers are exactly the same color,\ then eagerly gather them for proof.} set sets [::fileutil::cat AllSets.json] puts "Running the benchmark with $times iterations for each library" puts "jq: [benchmark jq $sets $times $value]" set ::duk [::duktape::oo::Duktape new] puts "tcl-duktape: [benchmark duktape $sets $times $value]" $::duk destroy puts "jimhttp JSON: [benchmark tcllib-json $sets $times $value]" puts "rl_json: [benchmark rl_json $sets $times $value]" puts "Tcllib JSON: [benchmark tcllib-json $sets $times $value]" sqlite3 ::sq3 :memory: ::sq3 enable_load_extension 1 puts "SQLite JSON1: [benchmark sqlite3-json1 $sets $times $value]" ::sq3 close puts "yajl-tcl: [benchmark yajltcl $sets $times $value]" } main ====== <>Data Serialization Format | Performance