jsonBench.nim
1 import "../yaml", commonBench 2 3 from nimlets_yaml import objKind 4 5 import math, strutils, stopwatch, terminal, algorithm, random, json 6 7 proc cmp(left, right: clock): int = cmp(left.nanoseconds(), right.nanoseconds()) 8 9 type 10 ObjectKind = enum 11 otMap, otSequence 12 13 Level = tuple 14 kind: ObjectKind 15 len: int 16 17 proc genString(maxLen: int): string = 18 let len = random(maxLen) 19 result = "\"" 20 var i = 0 21 while i < len - 1: 22 let c = cast[char](random(127 - 32) + 32) 23 case c 24 of '"', '\\': 25 result.add('\\') 26 result.add(c) 27 i += 2 28 else: 29 result.add(c) 30 i += 1 31 result.add('\"') 32 33 proc genJsonString(size: int, maxStringLen: int): string = 34 ## Generates a random JSON string. 35 ## size is in KiB, mayStringLen in characters. 36 37 randomize(size * maxStringLen) 38 result = "{" 39 40 let targetSize = size * 1024 41 var 42 indentation = 2 43 levels = newSeq[Level]() 44 curSize = 1 45 justOpened = true 46 levels.add((kind: otMap, len: 0)) 47 48 while levels.len > 0: 49 let 50 objectCloseProbability = 51 float(levels[levels.high].len + levels.high) * 0.025 52 closeObject = random(1.0) <= objectCloseProbability 53 54 if (closeObject and levels.len > 1) or curSize > targetSize: 55 indentation -= 2 56 if justOpened: 57 justOpened = false 58 else: 59 result.add("\x0A") 60 result.add(repeat(' ', indentation)) 61 curSize += indentation + 1 62 case levels[levels.high].kind 63 of otMap: 64 result.add('}') 65 of otSequence: 66 result.add(']') 67 curSize += 1 68 discard levels.pop() 69 continue 70 71 levels[levels.high].len += 1 72 73 if justOpened: 74 justOpened = false 75 result.add("\x0A") 76 result.add(repeat(' ', indentation)) 77 curSize += indentation + 1 78 else: 79 result.add(",\x0A") 80 result.add(repeat(' ', indentation)) 81 curSize += indentation + 2 82 83 case levels[levels.high].kind 84 of otMap: 85 let key = genString(maxStringLen) 86 result.add(key) 87 result.add(": ") 88 curSize += key.len + 2 89 of otSequence: 90 discard 91 92 let 93 objectValueProbability = 94 0.8 / float(levels.len * levels.len) 95 generateObjectValue = random(1.0) <= objectValueProbability 96 97 if generateObjectValue: 98 let objectKind = if random(2) == 0: otMap else: otSequence 99 case objectKind 100 of otMap: 101 result.add('{') 102 of otSequence: 103 result.add('[') 104 curSize += 1 105 levels.add((kind: objectKind, len: 0)) 106 justOpened = true 107 indentation += 2 108 else: 109 var s: string 110 case random(11) 111 of 0..5: 112 s = genString(maxStringLen) 113 of 6..7: 114 s = $random(32000) 115 of 8..9: 116 s = $(random(424242.4242) - 212121.21) 117 of 10: 118 case random(3) 119 of 0: 120 s = "true" 121 of 1: 122 s = "false" 123 of 2: 124 s = "null" 125 else: 126 discard 127 else: 128 discard 129 130 result.add(s) 131 curSize += s.len 132 133 var 134 cYaml1k, cYaml10k, cYaml100k, cJson1k, cJson10k, cJson100k, 135 cLibYaml1k, cLibYaml10k, cLibYaml100k: int64 136 json1k = genJsonString(1, 32) 137 json10k = genJsonString(10, 32) 138 json100k = genJsonString(100, 32) 139 tagLib = initCoreTagLibrary() 140 parser = newYamlParser(initCoreTagLibrary()) 141 142 block: 143 multibench(cJson1k, 100): 144 let res = parseJson(json1k) 145 assert res.kind == JObject 146 147 block: 148 multibench(cJson10k, 100): 149 let res = parseJson(json10k) 150 assert res.kind == JObject 151 152 block: 153 multibench(cJson100k, 100): 154 let res = parseJson(json100k) 155 assert res.kind == JObject 156 157 block: 158 multibench(cYaml1k, 100): 159 let res = loadToJson(json1k) 160 assert res[0].kind == JObject 161 162 block: 163 multibench(cYaml10k, 100): 164 let res = loadToJson(json10k) 165 assert res[0].kind == JObject 166 167 block: 168 multibench(cYaml100k, 100): 169 let res = loadToJson(json100k) 170 assert res[0].kind == JObject 171 172 block: 173 multibench(cLibYaml1k, 100): 174 let res = nimlets_yaml.load(json1k) 175 assert res[0].objKind == nimlets_yaml.YamlObjKind.Map 176 177 block: 178 multibench(cLibYaml10k, 100): 179 let res = nimlets_yaml.load(json10k) 180 assert res[0].objKind == nimlets_yaml.YamlObjKind.Map 181 182 block: 183 multibench(cLibYaml100k, 100): 184 let res = nimlets_yaml.load(json100k) 185 assert res[0].objKind == nimlets_yaml.YamlObjKind.Map 186 187 proc writeResult(caption: string, num: int64) = 188 styledWriteLine(stdout, resetStyle, caption, fgGreen, $num, resetStyle, "μs") 189 190 setForegroundColor(fgWhite) 191 192 writeStyled "Benchmark: Processing JSON input\n" 193 writeStyled "================================\n" 194 writeStyled "1k input\n--------\n" 195 writeResult "NimYAML: ", cYaml1k div 1000 196 writeResult "JSON: ", cJson1k div 1000 197 writeResult "LibYAML: ", cLibYaml1k div 1000 198 setForegroundColor(fgWhite) 199 writeStyled "10k input\n---------\n" 200 writeResult "NimYAML: ", cYaml10k div 1000 201 writeResult "JSON: ", cJson10k div 1000 202 writeResult "LibYAML: ", cLibYaml10k div 1000 203 setForegroundColor(fgWhite) 204 writeStyled "100k input\n----------\n" 205 writeResult "NimYAML: ", cYaml100k div 1000 206 writeResult "JSON: ", cJson100k div 1000 207 writeResult "LibYAML: ", cLibYaml100k div 1000