Last active
November 28, 2020 22:20
-
-
Save fantix/69647ef79a881b170acceba53f6416e4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.1.1/normalize.min.css" rel="stylesheet" | |
| type="text/css"/> | |
| <script charset="utf-8" src="https://d3js.org/d3.v3.js"></script> | |
| <style> | |
| html { | |
| background-color: #ffffff; | |
| } | |
| body { | |
| padding: 20px; | |
| } | |
| .axis path, .axis line { | |
| fill: none; | |
| stroke: #999; | |
| shape-rendering: crispEdges; | |
| } | |
| .axis.x2 path, .axis.x2 line { | |
| display: none; | |
| } | |
| .axis text, .legend text { | |
| font: 12px sans-serif; | |
| fill: #333; | |
| } | |
| .axis.x path { | |
| display: none; | |
| } | |
| .axis text { | |
| fill: #555; | |
| } | |
| .axis line, .axis path { | |
| stroke: #888; | |
| } | |
| .focus line { | |
| stroke: #900; | |
| } | |
| .focus text { | |
| fill: #900; | |
| font: 12px sans-serif; | |
| } | |
| table.results { | |
| width: 100%; | |
| border-collapse: collapse; | |
| } | |
| table.results td, table.results th { | |
| border: 1px solid #999; | |
| padding: 5px; | |
| } | |
| table.results tr.benchmark td { | |
| font-weight: bold; | |
| border-bottom: none; | |
| text-align: center; | |
| } | |
| table.results tr.metric td { | |
| border-top: none; | |
| border-bottom: none; | |
| text-align: right; | |
| } | |
| table.results tr.metric:last-child td { | |
| border-bottom: 1px solid #999; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <p><em>Sat Nov 28 13:10:02 2020</em></p> | |
| <h1>PostgreSQL Driver Performance Benchmark Report</h1> | |
| Below are the results of testing PostgreSQL client driver implementations. | |
| Each client is constrained to run in a single process. | |
| Test environment: Darwin 20.1.0 (None, x86_64) on i386. | |
| <h2>Overall Results</h2> | |
| <p>The charts below show the geometric average of all benchmark results.</p> | |
| <svg id="mean-bars" style="width: 80vw"></svg> | |
| <svg id="mean-lats" style="width: 80vw"></svg> | |
| <h2>Individual Benchmarks</h2> | |
| <h3>1-pg_type.json x10</h3> | |
| <h4>Test Setup</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">N/A</pre> | |
| <h4>Test Query</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">select typname, typnamespace, typowner, typlen, typbyval, typcategory, typispreferred, typisdefined, typdelim, typrelid, typelem, typarray from pg_type where typtypmod = $1 and typisdefined = $2</pre> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">Args: [-1, True]</pre> | |
| <svg id="query-bars-0" style="width: 80vw"></svg> | |
| <svg id="query-lats-0" style="width: 80vw"></svg> | |
| <h3>2-generate_series.json x10</h3> | |
| <h4>Test Setup</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">N/A</pre> | |
| <h4>Test Query</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">SELECT i FROM generate_series(1, $1) AS i</pre> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">Args: [1000]</pre> | |
| <svg id="query-bars-1" style="width: 80vw"></svg> | |
| <svg id="query-lats-1" style="width: 80vw"></svg> | |
| <h3>3-large_object.json x10</h3> | |
| <h4>Test Setup</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">CREATE TABLE _bytes(b bytea); INSERT INTO _bytes(b) (SELECT repeat('a', 1000)::bytea FROM generate_series(1, 100));</pre> | |
| <h4>Test Query</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">SELECT * FROM _bytes</pre> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">Args: []</pre> | |
| <svg id="query-bars-2" style="width: 80vw"></svg> | |
| <svg id="query-lats-2" style="width: 80vw"></svg> | |
| <h3>4-arrays.json x10</h3> | |
| <h4>Test Setup</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">CREATE TABLE _test(a int[]); INSERT INTO _test(a) (SELECT (SELECT array_agg(i) FROM generate_series(1, 100) as s(i)) FROM generate_series(1, 100));</pre> | |
| <h4>Test Query</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">SELECT * FROM _test</pre> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">Args: []</pre> | |
| <svg id="query-bars-3" style="width: 80vw"></svg> | |
| <svg id="query-lats-3" style="width: 80vw"></svg> | |
| <h3>5-copyfrom.json x10</h3> | |
| <h4>Test Setup</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">CREATE TABLE _test(a int, b int, c int, d text, e float, f int, g text);</pre> | |
| <h4>Test Query</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">COPY _test(a, b, c, d, e, f, g) FROM STDIN</pre> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">Args: [{'row': [10, 11, 10, 'TESTTESTTEST', 10.333, 12341234, '123412341234'], 'count': 10000}]</pre> | |
| <svg id="query-bars-4" style="width: 80vw"></svg> | |
| <svg id="query-lats-4" style="width: 80vw"></svg> | |
| <h3>6-batch.json x10</h3> | |
| <h4>Test Setup</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">CREATE TABLE _test(a int, b int, c int, d text, e float, f int, g text);</pre> | |
| <h4>Test Query</h4> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">INSERT INTO _test (a, b, c, d, e, f, g) VALUES ($1, $2, $3, $4, $5, $6, $7);</pre> | |
| <pre style="white-space: pre-wrap; | |
| margin-bottom: 10px; | |
| margin-left: 40px;">Args: [{'row': [10, 11, 10, 'TESTTESTTEST', 10.333, 12341234, '123412341234'], 'count': 1000}]</pre> | |
| <svg id="query-bars-5" style="width: 80vw"></svg> | |
| <svg id="query-lats-5" style="width: 80vw"></svg> | |
| <h2>Detailed Benchmark Data</h2> | |
| <table class="results"> | |
| <thead> | |
| <tr> | |
| <th></th> | |
| <th>Geometric mean</th> | |
| <th>1-pg_type.json x10</th> | |
| <th>2-generate_series.json x10</th> | |
| <th>3-large_object.json x10</th> | |
| <th>4-arrays.json x10</th> | |
| <th>5-copyfrom.json x10</th> | |
| <th>6-batch.json x10</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr class="benchmark"> | |
| <td>python-aiopg</td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Queries/sec</td> | |
| <td>265.1</td> | |
| <td>298.99</td> | |
| <td>521.46</td> | |
| <td>1836.58</td> | |
| <td>1062.41</td> | |
| <td>49.1</td> | |
| <td>23.24</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Rows/sec</td> | |
| <td>155608.79</td> | |
| <td>122285.69</td> | |
| <td>521463.08</td> | |
| <td>183658.12</td> | |
| <td>106241.42</td> | |
| <td>491002.88</td> | |
| <td>23239.0</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Min latency</td> | |
| <td>18.12ms</td> | |
| <td>9.78ms</td> | |
| <td>8.83ms</td> | |
| <td>4.3ms</td> | |
| <td>7.12ms</td> | |
| <td>35.85ms</td> | |
| <td>373.38ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Mean latency</td> | |
| <td>37.671ms</td> | |
| <td>33.416ms</td> | |
| <td>19.159ms</td> | |
| <td>5.439ms</td> | |
| <td>9.405ms</td> | |
| <td>203.137ms</td> | |
| <td>429.571ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Max latency</td> | |
| <td>69.3ms</td> | |
| <td>65.24ms</td> | |
| <td>36.43ms</td> | |
| <td>11.89ms</td> | |
| <td>20.08ms</td> | |
| <td>428.95ms</td> | |
| <td>455.07ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Latency variation</td> | |
| <td>3.341ms (8.87%)</td> | |
| <td>2.478ms (7.42%)</td> | |
| <td>2.672ms (13.94%)</td> | |
| <td>0.525ms (9.65%)</td> | |
| <td>0.612ms (6.51%)</td> | |
| <td>57.017ms (28.07%)</td> | |
| <td>11.457ms (2.67%)</td> | |
| </tr> | |
| <tr class="benchmark"> | |
| <td>python-aiopg-tuples</td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Queries/sec</td> | |
| <td>659.19</td> | |
| <td>2608.35</td> | |
| <td>6422.55</td> | |
| <td>3014.78</td> | |
| <td>1336.44</td> | |
| <td>50.65</td> | |
| <td>24.0</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Rows/sec</td> | |
| <td>386934.71</td> | |
| <td>1066813.8</td> | |
| <td>6422553.95</td> | |
| <td>301478.41</td> | |
| <td>133643.5</td> | |
| <td>506466.13</td> | |
| <td>24003.54</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Min latency</td> | |
| <td>8.185ms</td> | |
| <td>2.54ms</td> | |
| <td>0.83ms</td> | |
| <td>2.43ms</td> | |
| <td>5.93ms</td> | |
| <td>34.96ms</td> | |
| <td>283.03ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Mean latency</td> | |
| <td>15.141ms</td> | |
| <td>3.829ms</td> | |
| <td>1.554ms</td> | |
| <td>3.313ms</td> | |
| <td>7.476ms</td> | |
| <td>196.896ms</td> | |
| <td>415.178ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Max latency</td> | |
| <td>44.899ms</td> | |
| <td>18.26ms</td> | |
| <td>8.12ms</td> | |
| <td>13.57ms</td> | |
| <td>15.28ms</td> | |
| <td>559.7ms</td> | |
| <td>476.1ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Latency variation</td> | |
| <td>1.749ms (11.55%)</td> | |
| <td>0.574ms (15.0%)</td> | |
| <td>0.202ms (12.98%)</td> | |
| <td>0.442ms (13.35%)</td> | |
| <td>0.49ms (6.56%)</td> | |
| <td>50.269ms (25.53%)</td> | |
| <td>22.683ms (5.46%)</td> | |
| </tr> | |
| <tr class="benchmark"> | |
| <td>python-asyncpg 0.21</td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Queries/sec</td> | |
| <td>1538.49</td> | |
| <td>5790.69</td> | |
| <td>6389.53</td> | |
| <td>10414.82</td> | |
| <td>5159.42</td> | |
| <td>177.06</td> | |
| <td>37.67</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Rows/sec</td> | |
| <td>903053.68</td> | |
| <td>2368393.32</td> | |
| <td>6389527.09</td> | |
| <td>1041482.12</td> | |
| <td>515941.88</td> | |
| <td>1770566.96</td> | |
| <td>37669.85</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Min latency</td> | |
| <td>3.482ms</td> | |
| <td>1.1ms</td> | |
| <td>0.87ms</td> | |
| <td>0.57ms</td> | |
| <td>1.26ms</td> | |
| <td>15.17ms</td> | |
| <td>170.98ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Mean latency</td> | |
| <td>6.486ms</td> | |
| <td>1.724ms</td> | |
| <td>1.562ms</td> | |
| <td>0.957ms</td> | |
| <td>1.935ms</td> | |
| <td>56.421ms</td> | |
| <td>264.722ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Max latency</td> | |
| <td>34.725ms</td> | |
| <td>8.71ms</td> | |
| <td>15.93ms</td> | |
| <td>7.25ms</td> | |
| <td>11.37ms</td> | |
| <td>465.86ms</td> | |
| <td>329.03ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Latency variation</td> | |
| <td>1.446ms (22.28%)</td> | |
| <td>0.29ms (16.8%)</td> | |
| <td>1.17ms (74.88%)</td> | |
| <td>0.156ms (16.25%)</td> | |
| <td>0.287ms (14.83%)</td> | |
| <td>27.721ms (49.13%)</td> | |
| <td>21.743ms (8.21%)</td> | |
| </tr> | |
| <tr class="benchmark"> | |
| <td>python-asyncpg master (7c77c333)</td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Queries/sec</td> | |
| <td>2322.07</td> | |
| <td>6207.14</td> | |
| <td>6322.2</td> | |
| <td>10373.14</td> | |
| <td>4821.36</td> | |
| <td>180.55</td> | |
| <td>442.4</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Rows/sec</td> | |
| <td>1362999.99</td> | |
| <td>2538721.68</td> | |
| <td>6322195.11</td> | |
| <td>1037313.53</td> | |
| <td>482135.94</td> | |
| <td>1805496.5</td> | |
| <td>442400.83</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Min latency</td> | |
| <td>1.986ms</td> | |
| <td>1.16ms</td> | |
| <td>0.95ms</td> | |
| <td>0.53ms</td> | |
| <td>1.08ms</td> | |
| <td>15.25ms</td> | |
| <td>6.37ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Mean latency</td> | |
| <td>4.3ms</td> | |
| <td>1.608ms</td> | |
| <td>1.579ms</td> | |
| <td>0.962ms</td> | |
| <td>2.071ms</td> | |
| <td>55.328ms</td> | |
| <td>22.585ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Max latency</td> | |
| <td>35.922ms</td> | |
| <td>9.17ms</td> | |
| <td>13.72ms</td> | |
| <td>6.92ms</td> | |
| <td>20.96ms</td> | |
| <td>319.69ms</td> | |
| <td>368.3ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Latency variation</td> | |
| <td>1.235ms (28.71%)</td> | |
| <td>0.233ms (14.47%)</td> | |
| <td>1.145ms (72.53%)</td> | |
| <td>0.158ms (16.42%)</td> | |
| <td>0.394ms (19.04%)</td> | |
| <td>18.706ms (33.81%)</td> | |
| <td>11.394ms (50.45%)</td> | |
| </tr> | |
| <tr class="benchmark"> | |
| <td>golang-pgx</td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Queries/sec</td> | |
| <td>2264.58</td> | |
| <td>3398.5</td> | |
| <td>9071.54</td> | |
| <td>9321.6</td> | |
| <td>5837.41</td> | |
| <td>211.7</td> | |
| <td>379.77</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Rows/sec</td> | |
| <td>1329250.84</td> | |
| <td>1389986.63</td> | |
| <td>9071536.83</td> | |
| <td>932159.85</td> | |
| <td>583741.24</td> | |
| <td>2116996.15</td> | |
| <td>379768.84</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Min latency</td> | |
| <td>1.012ms</td> | |
| <td>0.33ms</td> | |
| <td>0.19ms</td> | |
| <td>0.11ms</td> | |
| <td>0.81ms</td> | |
| <td>23.6ms</td> | |
| <td>8.13ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Mean latency</td> | |
| <td>4.392ms</td> | |
| <td>2.936ms</td> | |
| <td>1.097ms</td> | |
| <td>1.067ms</td> | |
| <td>1.707ms</td> | |
| <td>46.617ms</td> | |
| <td>26.236ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Max latency</td> | |
| <td>40.853ms</td> | |
| <td>15.56ms</td> | |
| <td>7.16ms</td> | |
| <td>40.03ms</td> | |
| <td>8.16ms</td> | |
| <td>557.78ms</td> | |
| <td>229.02ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Latency variation</td> | |
| <td>2.148ms (48.92%)</td> | |
| <td>1.698ms (57.82%)</td> | |
| <td>0.579ms (52.82%)</td> | |
| <td>0.654ms (61.32%)</td> | |
| <td>0.624ms (36.56%)</td> | |
| <td>27.071ms (58.07%)</td> | |
| <td>9.045ms (34.47%)</td> | |
| </tr> | |
| <tr class="benchmark"> | |
| <td>golang-libpq</td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Queries/sec</td> | |
| <td>1252.66</td> | |
| <td>2462.46</td> | |
| <td>5592.42</td> | |
| <td>2579.34</td> | |
| <td>8574.6</td> | |
| <td>85.31</td> | |
| <td>148.7</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Rows/sec</td> | |
| <td>735289.1</td> | |
| <td>1007144.45</td> | |
| <td>5592418.58</td> | |
| <td>257933.93</td> | |
| <td>857459.64</td> | |
| <td>853124.7</td> | |
| <td>148704.0</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Min latency</td> | |
| <td>1.944ms</td> | |
| <td>0.74ms</td> | |
| <td>0.34ms</td> | |
| <td>0.34ms</td> | |
| <td>0.42ms</td> | |
| <td>28.48ms</td> | |
| <td>52.68ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Mean latency</td> | |
| <td>7.964ms</td> | |
| <td>4.055ms</td> | |
| <td>1.782ms</td> | |
| <td>3.871ms</td> | |
| <td>1.161ms</td> | |
| <td>117.033ms</td> | |
| <td>67.153ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Max latency</td> | |
| <td>52.373ms</td> | |
| <td>12.62ms</td> | |
| <td>50.55ms</td> | |
| <td>36.56ms</td> | |
| <td>19.88ms</td> | |
| <td>340.99ms</td> | |
| <td>130.53ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Latency variation</td> | |
| <td>2.698ms (33.88%)</td> | |
| <td>1.412ms (34.83%)</td> | |
| <td>1.611ms (90.36%)</td> | |
| <td>2.739ms (70.75%)</td> | |
| <td>0.399ms (34.39%)</td> | |
| <td>23.955ms (20.47%)</td> | |
| <td>6.476ms (9.64%)</td> | |
| </tr> | |
| <tr class="benchmark"> | |
| <td>nodejs-ts-postgres</td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Queries/sec</td> | |
| <td>1440.77</td> | |
| <td>1974.71</td> | |
| <td>5896.3</td> | |
| <td>6485.18</td> | |
| <td>3398.84</td> | |
| <td>N/A</td> | |
| <td>24.19</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Rows/sec</td> | |
| <td>480383.69</td> | |
| <td>807655.73</td> | |
| <td>5896297.66</td> | |
| <td>648517.78</td> | |
| <td>339884.02</td> | |
| <td>N/A</td> | |
| <td>24371.54</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Min latency</td> | |
| <td>0.967ms</td> | |
| <td>3.73ms</td> | |
| <td>0.77ms</td> | |
| <td>1.07ms</td> | |
| <td>2.12ms</td> | |
| <td>N/A</td> | |
| <td>0.13ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Mean latency</td> | |
| <td>1.74ms</td> | |
| <td>5.062ms</td> | |
| <td>1.695ms</td> | |
| <td>1.541ms</td> | |
| <td>2.941ms</td> | |
| <td>N/A</td> | |
| <td>0.41ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Max latency</td> | |
| <td>19.948ms</td> | |
| <td>19.14ms</td> | |
| <td>17.88ms</td> | |
| <td>15.03ms</td> | |
| <td>15.0ms</td> | |
| <td>N/A</td> | |
| <td>40.94ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Latency variation</td> | |
| <td>0.615ms (35.34%)</td> | |
| <td>0.934ms (18.44%)</td> | |
| <td>0.635ms (37.47%)</td> | |
| <td>0.5ms (32.41%)</td> | |
| <td>0.856ms (29.12%)</td> | |
| <td>N/A</td> | |
| <td>0.347ms (84.58%)</td> | |
| </tr> | |
| <tr class="benchmark"> | |
| <td>nodejs-pg-native</td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| <td></td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Queries/sec</td> | |
| <td>568.68</td> | |
| <td>761.99</td> | |
| <td>3007.24</td> | |
| <td>1547.37</td> | |
| <td>533.85</td> | |
| <td>N/A</td> | |
| <td>31.42</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Rows/sec</td> | |
| <td>189512.34</td> | |
| <td>311654.17</td> | |
| <td>3007236.37</td> | |
| <td>154736.9</td> | |
| <td>53385.26</td> | |
| <td>N/A</td> | |
| <td>31574.15</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Min latency</td> | |
| <td>1.748ms</td> | |
| <td>7.53ms</td> | |
| <td>1.45ms</td> | |
| <td>3.51ms</td> | |
| <td>5.33ms</td> | |
| <td>N/A</td> | |
| <td>0.08ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Mean latency</td> | |
| <td>4.411ms</td> | |
| <td>13.116ms</td> | |
| <td>3.324ms</td> | |
| <td>6.458ms</td> | |
| <td>18.717ms</td> | |
| <td>N/A</td> | |
| <td>0.317ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Max latency</td> | |
| <td>61.588ms</td> | |
| <td>37.24ms</td> | |
| <td>15.4ms</td> | |
| <td>147.24ms</td> | |
| <td>154.93ms</td> | |
| <td>N/A</td> | |
| <td>67.73ms</td> | |
| </tr> | |
| <tr class="metric"> | |
| <td>Latency variation</td> | |
| <td>2.137ms (48.46%)</td> | |
| <td>2.466ms (18.8%)</td> | |
| <td>1.07ms (32.2%)</td> | |
| <td>3.522ms (54.55%)</td> | |
| <td>8.253ms (44.1%)</td> | |
| <td>N/A</td> | |
| <td>0.581ms (183.5%)</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <script> | |
| var DEFAULT_COLORS = [ | |
| "#98abc5", "#6b486b", "#ff8c00", "#8a89a6", "#7b6888", "#a05d56", "#d0743c" | |
| ]; | |
| function _humanFileSize(bytes, si) { | |
| var thresh = si ? 1000 : 1024; | |
| if (Math.abs(bytes) < thresh) { | |
| return bytes + ' B'; | |
| } | |
| var units = si | |
| ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] | |
| : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']; | |
| var u = -1; | |
| do { | |
| bytes /= thresh; | |
| ++u; | |
| } while (Math.abs(bytes) >= thresh && u < units.length - 1); | |
| return bytes.toFixed(0) + ' ' + units[u]; | |
| } | |
| function _drawLegend(chart, width, sizes) { | |
| var legend = chart.selectAll('legend') | |
| .data(sizes) | |
| .enter() | |
| .append("g") | |
| .attr('class', 'legend') | |
| .attr("transform", "translate(" + width + ", 20)"); | |
| legend.append('circle') | |
| .style('fill', function (d, i) { | |
| return DEFAULT_COLORS[i] | |
| }) | |
| .attr('cx', 0) | |
| .attr('cy', function (d, i) { | |
| return i * 20 | |
| }) | |
| .attr('r', 5); | |
| legend.append('text') | |
| .attr('x', 7) | |
| .attr('y', function (d, i) { | |
| return i * 20 | |
| }) | |
| .attr('alignment-baseline', 'central') | |
| .text(function (d) { | |
| return d; | |
| }); | |
| } | |
| function drawBars(elSelector, data, options) { | |
| 'use strict'; | |
| options = options || {}; | |
| // geometry | |
| var fullWidth = (options.width || 1000), | |
| fullHeight = (options.height || 370), | |
| margin = {top: 10, right: 100, bottom: 55, left: 100}, | |
| width = fullWidth - margin.left - margin.right, | |
| height = fullHeight - margin.top - margin.bottom, | |
| benchmarks = data; | |
| // data reshape | |
| var maxRps = 0; | |
| benchmarks.forEach(function (bench) { | |
| if (bench.data.rps > maxRps) { | |
| maxRps = bench.data.rps | |
| } | |
| }); | |
| var names = benchmarks.map(function (d) { | |
| return d.name | |
| }); | |
| // charting | |
| var color = d3.scale.ordinal() | |
| .range(DEFAULT_COLORS); | |
| var x0 = d3.scale.ordinal() | |
| .rangeRoundBands([0, width], .2) | |
| .domain(names); | |
| var y = d3.scale.linear() | |
| .range([height, 0]) | |
| .domain([0, maxRps]); | |
| var xAxis = d3.svg.axis() | |
| .scale(x0) | |
| .orient("bottom") | |
| .tickFormat(function (d) { | |
| return d.split('-')[0] | |
| }); | |
| var xAxis2 = d3.svg.axis() | |
| .scale(x0) | |
| .orient("bottom") | |
| .tickFormat(function (d) { | |
| return d.split('-')[1] | |
| }); | |
| var xAxis3 = d3.svg.axis() | |
| .scale(x0) | |
| .orient("bottom") | |
| .tickFormat(function (d) { | |
| return d.split('-')[2] | |
| }); | |
| var yAxis = d3.svg.axis() | |
| .scale(y) | |
| .orient("left"); | |
| var chart = d3.select(elSelector) | |
| .attr('viewBox', '0 0 ' + fullWidth + ' ' + fullHeight) | |
| .append("g") | |
| .attr("transform", | |
| "translate(" + margin.left + "," + margin.top + ")"); | |
| chart.append("g") | |
| .attr("class", "x axis") | |
| .attr("transform", "translate(0," + height + ")") | |
| .call(options.showBenchmarkType ? xAxis : xAxis2); | |
| chart.append("g") | |
| .attr("class", "x axis x2") | |
| .attr("transform", "translate(0," + (height + 14) + ")") | |
| .call(options.showBenchmarkType ? xAxis2 : xAxis3); | |
| if (options.showBenchmarkType) { | |
| chart.append("g") | |
| .attr("class", "x axis x2") | |
| .attr("transform", "translate(0," + (height + 28) + ")") | |
| .call(xAxis3); | |
| } | |
| chart.append("g") | |
| .attr("class", "y axis") | |
| .call(yAxis) | |
| .append("text") | |
| .attr("transform", "rotate(-90)") | |
| .attr("y", 6) | |
| .attr("dy", ".71em") | |
| .style("text-anchor", "end") | |
| .text("Rows / sec"); | |
| chart.selectAll("rect") | |
| .data(benchmarks) | |
| .enter().append("rect") | |
| .style("fill", function (d, i) { | |
| return color(0); | |
| }) | |
| .attr("width", x0.rangeBand()) | |
| .attr("x", function (d, i) { | |
| return x0(d.name); | |
| }) | |
| .attr("y", function (d) { | |
| return y(d.data.rps); | |
| }) | |
| .attr("height", function (d) { | |
| return height - y(d.data.rps); | |
| }) | |
| .on("mouseover", function (d, i) { | |
| focusRect | |
| .attr('y', y(d.data.rps) - 9); | |
| focusLine | |
| .attr('y1', y(d.data.rps)) | |
| .attr('y2', y(d.data.rps)); | |
| focusText | |
| .attr('y', y(d.data.rps)) | |
| .text(d3.format("0,000")(Math.round(d.data.rps))); | |
| focus.style("display", null); | |
| }) | |
| .on("mouseout", function () { | |
| focus.style("display", 'none'); | |
| }); | |
| var focus = chart.append('g') | |
| .attr('class', 'focus') | |
| .style('display', 'none'); | |
| var focusRect = focus.append('rect') | |
| .attr('x', -margin.left) | |
| .attr('width', margin.left - 6) | |
| .attr('y', 0) | |
| .attr('height', 18) | |
| .attr('fill', 'rgba(255, 255, 255, 0.9)'); | |
| var focusLine = focus.append('line') | |
| .attr('x1', -6) | |
| .attr('x2', width - 20) | |
| .attr('y1', 0) | |
| .attr('y2', 0) | |
| .style("stroke-dasharray", "2,2"); | |
| var focusText = focus.append('text') | |
| .attr('y', 0) | |
| .attr('x', -9) | |
| .attr('text-anchor', 'end') | |
| .attr('alignment-baseline', 'middle'); | |
| }; | |
| function drawLats(elSelector, data) { | |
| 'use strict'; | |
| options = options || {}; | |
| // geometry | |
| var fullWidth = (options.width || 1000), | |
| fullHeight = (options.height || 370), | |
| margin = {top: 10, right: 65, bottom: 55, left: 65}, | |
| width = fullWidth - margin.left - margin.right, | |
| height = fullHeight - margin.top - margin.bottom, | |
| benchmarks = data; | |
| // data reshape | |
| var maxLat = 0; | |
| benchmarks.forEach(function (bench) { | |
| if (bench.data.latency_percentiles[4][1] > maxLat) { | |
| maxLat = bench.data.latency_percentiles[4][1]; | |
| } | |
| }); | |
| var names = benchmarks.map(function (d) { | |
| return d.name | |
| }); | |
| // charting | |
| var color = d3.scale.ordinal() | |
| .range(DEFAULT_COLORS); | |
| var x0 = d3.scale.ordinal() | |
| .rangeRoundBands([0, width], .2) | |
| .domain(names); | |
| var y = d3.scale.linear() | |
| .range([height, 0]) | |
| .domain([0, maxLat]); | |
| var xAxis = d3.svg.axis() | |
| .scale(x0) | |
| .orient("bottom") | |
| .tickFormat(function (d) { | |
| return d.split('-')[0] | |
| }); | |
| var xAxis2 = d3.svg.axis() | |
| .scale(x0) | |
| .orient("bottom") | |
| .tickFormat(function (d) { | |
| return d.split('-')[1] | |
| }); | |
| var xAxis3 = d3.svg.axis() | |
| .scale(x0) | |
| .orient("bottom") | |
| .tickFormat(function (d) { | |
| return d.split('-')[2] | |
| }); | |
| var yAxis = d3.svg.axis() | |
| .scale(y) | |
| .orient("left"); | |
| var chart = d3.select(elSelector) | |
| .attr('viewBox', '0 0 ' + fullWidth + ' ' + fullHeight) | |
| .append("g") | |
| .attr("transform", | |
| "translate(" + margin.left + "," + margin.top + ")"); | |
| chart.append("g") | |
| .attr("class", "x axis") | |
| .attr("transform", "translate(0," + height + ")") | |
| .call(options.showBenchmarkType ? xAxis : xAxis2); | |
| chart.append("g") | |
| .attr("class", "x axis x2") | |
| .attr("transform", "translate(0," + (height + 14) + ")") | |
| .call(options.showBenchmarkType ? xAxis2 : xAxis3); | |
| if (options.showBenchmarkType) { | |
| chart.append("g") | |
| .attr("class", "x axis x2") | |
| .attr("transform", "translate(0," + (height + 28) + ")") | |
| .call(xAxis3); | |
| } | |
| chart.append("g") | |
| .attr("class", "y axis") | |
| .call(yAxis) | |
| .append("text") | |
| .attr("transform", "rotate(-90)") | |
| .attr("y", 6) | |
| .attr("dy", ".71em") | |
| .style("text-anchor", "end") | |
| .text("Latency (msec)"); | |
| var g = chart.selectAll("rect") | |
| .data(benchmarks) | |
| .enter().append("g") | |
| .attr('class', 'sub'); | |
| g.append('line') | |
| .attr('y1', function (d) { | |
| return y(d.data.latency_percentiles[4][1]); | |
| }) | |
| .attr('y2', function (d) { | |
| return y(d.data.latency_percentiles[4][1]); | |
| }) | |
| .attr('x1', function (d, i) { | |
| return x0(d.name); | |
| }) | |
| .attr('x2', function (d, i) { | |
| return x0(d.name) + x0.rangeBand(); | |
| }) | |
| .style("stroke", function (d, i) { | |
| return color(0); | |
| }); | |
| g.append('line') | |
| .attr('y1', function (d) { | |
| return y(d.data.latency_min); | |
| }) | |
| .attr('y2', function (d) { | |
| return y(d.data.latency_min); | |
| }) | |
| .attr('x1', function (d, i) { | |
| return x0(d.name); | |
| }) | |
| .attr('x2', function (d, i) { | |
| return x0(d.name) + x0.rangeBand(); | |
| }) | |
| .style("stroke", function (d, i) { | |
| return color(0); | |
| }); | |
| g.append('line') | |
| .attr('y1', function (d) { | |
| return y(d.data.latency_percentiles[1][1]); | |
| }) | |
| .attr('y2', function (d) { | |
| return y(d.data.latency_percentiles[1][1]); | |
| }) | |
| .attr('x1', function (d, i) { | |
| return x0(d.name); | |
| }) | |
| .attr('x2', function (d, i) { | |
| return x0(d.name) + x0.rangeBand(); | |
| }) | |
| .style("stroke", function (d, i) { | |
| return color(0); | |
| }); | |
| g.append('line') | |
| .attr('y1', function (d) { | |
| return y(d.data.latency_min); | |
| }) | |
| .attr('y2', function (d) { | |
| return y(d.data.latency_percentiles[0][1]) | |
| }) | |
| .attr('x1', function (d, i) { | |
| return x0(d.name) + x0.rangeBand() / 2; | |
| }) | |
| .attr('x2', function (d, i) { | |
| return x0(d.name) + x0.rangeBand() / 2; | |
| }) | |
| .style("stroke", function (d, i) { | |
| return color(0); | |
| }) | |
| .style("stroke-dasharray", "2,2"); | |
| g.append('line') | |
| .attr('y1', function (d) { | |
| return y(d.data.latency_percentiles[4][1]); | |
| }) | |
| .attr('y2', function (d) { | |
| return y(d.data.latency_percentiles[2][1]) | |
| }) | |
| .attr('x1', function (d, i) { | |
| return x0(d.name) + x0.rangeBand() / 2; | |
| }) | |
| .attr('x2', function (d, i) { | |
| return x0(d.name) + x0.rangeBand() / 2; | |
| }) | |
| .style("stroke", function (d, i) { | |
| return color(0); | |
| }) | |
| .style("stroke-dasharray", "2,2"); | |
| g.append('rect') | |
| .attr('y', function (d) { | |
| return y(d.data.latency_percentiles[2][1]); | |
| }) | |
| .attr('x', function (d, i) { | |
| return x0(d.name); | |
| }) | |
| .attr("width", x0.rangeBand()) | |
| .attr('height', function (d) { | |
| return Math.abs(y(d.data.latency_percentiles[2][1]) - y(d.data.latency_percentiles[0][1])) | |
| }) | |
| .style("stroke", function (d, i) { | |
| return color(0); | |
| }) | |
| .style("fill", 'rgba(0, 0, 0, 0)'); | |
| g.append('rect') | |
| .attr('y', 0) | |
| .attr('height', height) | |
| .attr('x', function (d, i) { | |
| return x0(d.name); | |
| }) | |
| .attr('width', function (d) { | |
| return x0.rangeBand(); | |
| }) | |
| .style('fill', 'rgba(0, 0, 0, 0)') | |
| .on("mouseout", function (d, i) { | |
| d3.select(this).style('fill', 'rgba(0, 0, 0, 0)'); | |
| focus.style('display', 'none'); | |
| }) | |
| .on("mouseover", function (d, i) { | |
| d3.select(this).style('fill', 'rgba(0, 0, 0, 0.04)'); | |
| var yMedian = y(d.data.latency_percentiles[1][1]); | |
| focus | |
| .style('display', null); | |
| focusLine | |
| .attr('y1', yMedian) | |
| .attr('y2', yMedian); | |
| focusRect | |
| .attr('y', yMedian - 9); | |
| focusLine | |
| .attr('y1', yMedian) | |
| .attr('y2', yMedian); | |
| focusText | |
| .attr('y', yMedian) | |
| .text(d3.format(".2f")(d.data.latency_percentiles[1][1])); | |
| }); | |
| var focus = chart.append('g') | |
| .attr('class', 'focus') | |
| .style('display', 'none'); | |
| var focusRect = focus.append('rect') | |
| .attr('x', -margin.left) | |
| .attr('width', margin.left - 6) | |
| .attr('y', 0) | |
| .attr('height', 18) | |
| .attr('fill', 'rgba(255, 255, 255, 0.9)'); | |
| var focusLine = focus.append('line') | |
| .attr('x1', -6) | |
| .attr('x2', width - 20) | |
| .attr('y1', 0) | |
| .attr('y2', 0) | |
| .style("stroke-dasharray", "2,2"); | |
| var focusText = focus.append('text') | |
| .attr('y', 0) | |
| .attr('x', -9) | |
| .attr('text-anchor', 'end') | |
| .attr('alignment-baseline', 'middle'); | |
| }; | |
| var data = { | |
| "date": "%Y-%m-%dT%H:%M:%S%z", | |
| "duration": 30, | |
| "platform": {"cpu": "i386", "arch": "x86_64", "system": "Darwin 20.1.0", "distribution": null}, | |
| "concurrency_levels": [10], | |
| "querynames": ["1-pg_type.json", "2-generate_series.json", "3-large_object.json", "4-arrays.json", "5-copyfrom.json", "6-batch.json"], | |
| "queries": [{ | |
| "query": "select typname, typnamespace, typowner, typlen, typbyval, typcategory, typispreferred, typisdefined, typdelim, typrelid, typelem, typarray from pg_type where typtypmod = $1 and typisdefined = $2", | |
| "args": [-1, true] | |
| }, { | |
| "query": "SELECT i FROM generate_series(1, $1) AS i", | |
| "args": [1000] | |
| }, { | |
| "setup": "CREATE TABLE _bytes(b bytea); INSERT INTO _bytes(b) (SELECT repeat('a', 1000)::bytea FROM generate_series(1, 100));", | |
| "teardown": "DROP TABLE _bytes;", | |
| "query": "SELECT * FROM _bytes", | |
| "args": [] | |
| }, { | |
| "setup": "CREATE TABLE _test(a int[]); INSERT INTO _test(a) (SELECT (SELECT array_agg(i) FROM generate_series(1, 100) as s(i)) FROM generate_series(1, 100));", | |
| "teardown": "DROP TABLE _test;", | |
| "query": "SELECT * FROM _test", | |
| "args": [] | |
| }, { | |
| "setup": "CREATE TABLE _test(a int, b int, c int, d text, e float, f int, g text);", | |
| "teardown": "DROP TABLE _test;", | |
| "query": "COPY _test(a, b, c, d, e, f, g) FROM STDIN", | |
| "args": [{"row": [10, 11, 10, "TESTTESTTEST", 10.333, 12341234, "123412341234"], "count": 10000}] | |
| }, { | |
| "setup": "CREATE TABLE _test(a int, b int, c int, d text, e float, f int, g text);", | |
| "teardown": "DROP TABLE _test;", | |
| "query": "INSERT INTO _test (a, b, c, d, e, f, g) VALUES ($1, $2, $3, $4, $5, $6, $7);", | |
| "args": [{"row": [10, 11, 10, "TESTTESTTEST", 10.333, 12341234, "123412341234"], "count": 1000}] | |
| }], | |
| "benchmarks": [ | |
| { | |
| "name": "python-aiopg", | |
| "variations": [{ | |
| "duration": 30.03, | |
| "queries": 8978, | |
| "qps": 298.99, | |
| "rps": 122285.69, | |
| "latency_min": 9.78, | |
| "latency_mean": 33.416, | |
| "latency_max": 65.24, | |
| "latency_std": 2.478, | |
| "latency_cv": 7.42, | |
| "latency_percentiles": [[25, 31.359], [50, 33.233], [75, 34.624], [90, 36.458], [99, 41.024], [99.99, 65.232]] | |
| }, { | |
| "duration": 30.02, | |
| "queries": 15652, | |
| "qps": 521.46, | |
| "rps": 521463.08, | |
| "latency_min": 8.83, | |
| "latency_mean": 19.159, | |
| "latency_max": 36.43, | |
| "latency_std": 2.672, | |
| "latency_cv": 13.94, | |
| "latency_percentiles": [[25, 17.438], [50, 18.495], [75, 19.571], [90, 21.949], [99, 30.855], [99.99, 36.419]] | |
| }, { | |
| "duration": 30.0, | |
| "queries": 55106, | |
| "qps": 1836.58, | |
| "rps": 183658.12, | |
| "latency_min": 4.3, | |
| "latency_mean": 5.439, | |
| "latency_max": 11.89, | |
| "latency_std": 0.525, | |
| "latency_cv": 9.65, | |
| "latency_percentiles": [[25, 5.161], [50, 5.267], [75, 5.515], [90, 6.134], [99, 7.324], [99.99, 11.07]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 31881, | |
| "qps": 1062.41, | |
| "rps": 106241.42, | |
| "latency_min": 7.12, | |
| "latency_mean": 9.405, | |
| "latency_max": 20.08, | |
| "latency_std": 0.612, | |
| "latency_cv": 6.51, | |
| "latency_percentiles": [[25, 9.042], [50, 9.233], [75, 9.561], [90, 10.146], [99, 11.644], [99.99, 19.316]] | |
| }, { | |
| "duration": 30.04, | |
| "queries": 1475, | |
| "qps": 49.1, | |
| "rps": 491002.88, | |
| "latency_min": 35.85, | |
| "latency_mean": 203.137, | |
| "latency_max": 428.95, | |
| "latency_std": 57.017, | |
| "latency_cv": 28.07, | |
| "latency_percentiles": [[25, 170.395], [50, 201.21], [75, 235.975], [90, 276.98], [99, 344.315], [99.99, 428.957]] | |
| }, { | |
| "duration": 30.12, | |
| "queries": 700, | |
| "qps": 23.24, | |
| "rps": 23239.0, | |
| "latency_min": 373.38, | |
| "latency_mean": 429.571, | |
| "latency_max": 455.07, | |
| "latency_std": 11.457, | |
| "latency_cv": 2.67, | |
| "latency_percentiles": [[25, 425.11], [50, 431.28], [75, 436.65], [90, 442.34], [99, 449.55], [99.99, 455.079]] | |
| }], | |
| "mean": { | |
| "duration": 30.04, | |
| "queries": 7962.73, | |
| "qps": 265.1, | |
| "rps": 155608.79, | |
| "latency_min": 18.12, | |
| "latency_mean": 37.671, | |
| "latency_max": 69.3, | |
| "latency_std": 3.341, | |
| "latency_cv": 8.87, | |
| "latency_percentiles": [[25, 35.032], [50, 37.067], [75, 39.295], [90, 42.747], [99, 50.562], [99.99, 68.034]] | |
| } | |
| }, { | |
| "name": "python-aiopg-tuples", | |
| "variations": [{ | |
| "duration": 30.0, | |
| "queries": 78257, | |
| "qps": 2608.35, | |
| "rps": 1066813.8, | |
| "latency_min": 2.54, | |
| "latency_mean": 3.829, | |
| "latency_max": 18.26, | |
| "latency_std": 0.574, | |
| "latency_cv": 15.0, | |
| "latency_percentiles": [[25, 3.559], [50, 3.72], [75, 3.926], [90, 4.266], [99, 5.829], [99.99, 16.243]] | |
| }, { | |
| "duration": 30.0, | |
| "queries": 192683, | |
| "qps": 6422.55, | |
| "rps": 6422553.95, | |
| "latency_min": 0.83, | |
| "latency_mean": 1.554, | |
| "latency_max": 8.12, | |
| "latency_std": 0.202, | |
| "latency_cv": 12.98, | |
| "latency_percentiles": [[25, 1.439], [50, 1.502], [75, 1.595], [90, 1.744], [99, 2.217], [99.99, 7.295]] | |
| }, { | |
| "duration": 30.0, | |
| "queries": 90451, | |
| "qps": 3014.78, | |
| "rps": 301478.41, | |
| "latency_min": 2.43, | |
| "latency_mean": 3.313, | |
| "latency_max": 13.57, | |
| "latency_std": 0.442, | |
| "latency_cv": 13.35, | |
| "latency_percentiles": [[25, 3.094], [50, 3.192], [75, 3.365], [90, 3.72], [99, 5.0], [99.99, 9.879]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 40102, | |
| "qps": 1336.44, | |
| "rps": 133643.5, | |
| "latency_min": 5.93, | |
| "latency_mean": 7.476, | |
| "latency_max": 15.28, | |
| "latency_std": 0.49, | |
| "latency_cv": 6.56, | |
| "latency_percentiles": [[25, 7.192], [50, 7.346], [75, 7.588], [90, 8.019], [99, 9.285], [99.99, 13.05]] | |
| }, { | |
| "duration": 30.03, | |
| "queries": 1521, | |
| "qps": 50.65, | |
| "rps": 506466.13, | |
| "latency_min": 34.96, | |
| "latency_mean": 196.896, | |
| "latency_max": 559.7, | |
| "latency_std": 50.269, | |
| "latency_cv": 25.53, | |
| "latency_percentiles": [[25, 170.675], [50, 194.81], [75, 218.775], [90, 250.218], [99, 321.046], [99.99, 559.707]] | |
| }, { | |
| "duration": 30.2, | |
| "queries": 725, | |
| "qps": 24.0, | |
| "rps": 24003.54, | |
| "latency_min": 283.03, | |
| "latency_mean": 415.178, | |
| "latency_max": 476.1, | |
| "latency_std": 22.683, | |
| "latency_cv": 5.46, | |
| "latency_percentiles": [[25, 409.972], [50, 416.9], [75, 422.735], [90, 444.7], [99, 472.185], [99.99, 476.109]] | |
| }], | |
| "mean": { | |
| "duration": 30.04, | |
| "queries": 19803.21, | |
| "qps": 659.19, | |
| "rps": 386934.71, | |
| "latency_min": 8.185, | |
| "latency_mean": 15.141, | |
| "latency_max": 44.899, | |
| "latency_std": 1.749, | |
| "latency_cv": 11.55, | |
| "latency_percentiles": [[25, 14.135], [50, 14.831], [75, 15.667], [90, 17.065], [99, 21.206], [99.99, 39.959]] | |
| } | |
| }, { | |
| "name": "python-asyncpg 0.21", | |
| "variations": [{ | |
| "duration": 30.0, | |
| "queries": 173727, | |
| "qps": 5790.69, | |
| "rps": 2368393.32, | |
| "latency_min": 1.1, | |
| "latency_mean": 1.724, | |
| "latency_max": 8.71, | |
| "latency_std": 0.29, | |
| "latency_cv": 16.8, | |
| "latency_percentiles": [[25, 1.565], [50, 1.635], [75, 1.777], [90, 1.999], [99, 2.865], [99.99, 7.306]] | |
| }, { | |
| "duration": 30.0, | |
| "queries": 191691, | |
| "qps": 6389.53, | |
| "rps": 6389527.09, | |
| "latency_min": 0.87, | |
| "latency_mean": 1.562, | |
| "latency_max": 15.93, | |
| "latency_std": 1.17, | |
| "latency_cv": 74.88, | |
| "latency_percentiles": [[25, 1.204], [50, 1.298], [75, 1.418], [90, 1.661], [99, 6.926], [99.99, 15.207]] | |
| }, { | |
| "duration": 30.0, | |
| "queries": 312451, | |
| "qps": 10414.82, | |
| "rps": 1041482.12, | |
| "latency_min": 0.57, | |
| "latency_mean": 0.957, | |
| "latency_max": 7.25, | |
| "latency_std": 0.156, | |
| "latency_cv": 16.25, | |
| "latency_percentiles": [[25, 0.897], [50, 0.912], [75, 0.941], [90, 1.069], [99, 1.642], [99.99, 3.833]] | |
| }, { | |
| "duration": 30.0, | |
| "queries": 154788, | |
| "qps": 5159.42, | |
| "rps": 515941.88, | |
| "latency_min": 1.26, | |
| "latency_mean": 1.935, | |
| "latency_max": 11.37, | |
| "latency_std": 0.287, | |
| "latency_cv": 14.83, | |
| "latency_percentiles": [[25, 1.8], [50, 1.85], [75, 1.943], [90, 2.181], [99, 3.072], [99.99, 7.77]] | |
| }, { | |
| "duration": 30.02, | |
| "queries": 5315, | |
| "qps": 177.06, | |
| "rps": 1770566.96, | |
| "latency_min": 15.17, | |
| "latency_mean": 56.421, | |
| "latency_max": 465.86, | |
| "latency_std": 27.721, | |
| "latency_cv": 49.13, | |
| "latency_percentiles": [[25, 46.401], [50, 53.09], [75, 60.732], [90, 68.737], [99, 216.617], [99.99, 465.859]] | |
| }, { | |
| "duration": 30.18, | |
| "queries": 1137, | |
| "qps": 37.67, | |
| "rps": 37669.85, | |
| "latency_min": 170.98, | |
| "latency_mean": 264.722, | |
| "latency_max": 329.03, | |
| "latency_std": 21.743, | |
| "latency_cv": 8.21, | |
| "latency_percentiles": [[25, 263.095], [50, 270.458], [75, 275.908], [90, 280.996], [99, 298.543], [99.99, 329.038]] | |
| }], | |
| "mean": { | |
| "duration": 30.03, | |
| "queries": 46207.09, | |
| "qps": 1538.49, | |
| "rps": 903053.68, | |
| "latency_min": 3.482, | |
| "latency_mean": 6.486, | |
| "latency_max": 34.725, | |
| "latency_std": 1.446, | |
| "latency_cv": 22.28, | |
| "latency_percentiles": [[25, 5.776], [50, 6.098], [75, 6.525], [90, 7.285], [99, 13.652], [99.99, 28.24]] | |
| } | |
| }, { | |
| "name": "python-asyncpg master", | |
| "variations": [{ | |
| "duration": 30.0, | |
| "queries": 186221, | |
| "qps": 6207.14, | |
| "rps": 2538721.68, | |
| "latency_min": 1.16, | |
| "latency_mean": 1.608, | |
| "latency_max": 9.17, | |
| "latency_std": 0.233, | |
| "latency_cv": 14.47, | |
| "latency_percentiles": [[25, 1.494], [50, 1.557], [75, 1.641], [90, 1.802], [99, 2.485], [99.99, 7.013]] | |
| }, { | |
| "duration": 30.0, | |
| "queries": 189682, | |
| "qps": 6322.2, | |
| "rps": 6322195.11, | |
| "latency_min": 0.95, | |
| "latency_mean": 1.579, | |
| "latency_max": 13.72, | |
| "latency_std": 1.145, | |
| "latency_cv": 72.53, | |
| "latency_percentiles": [[25, 1.231], [50, 1.322], [75, 1.437], [90, 1.655], [99, 6.796], [99.99, 13.151]] | |
| }, { | |
| "duration": 30.0, | |
| "queries": 311199, | |
| "qps": 10373.14, | |
| "rps": 1037313.53, | |
| "latency_min": 0.53, | |
| "latency_mean": 0.962, | |
| "latency_max": 6.92, | |
| "latency_std": 0.158, | |
| "latency_cv": 16.42, | |
| "latency_percentiles": [[25, 0.9], [50, 0.919], [75, 0.944], [90, 1.077], [99, 1.675], [99.99, 3.429]] | |
| }, { | |
| "duration": 30.0, | |
| "queries": 144646, | |
| "qps": 4821.36, | |
| "rps": 482135.94, | |
| "latency_min": 1.08, | |
| "latency_mean": 2.071, | |
| "latency_max": 20.96, | |
| "latency_std": 0.394, | |
| "latency_cv": 19.04, | |
| "latency_percentiles": [[25, 1.918], [50, 1.957], [75, 2.055], [90, 2.39], [99, 3.47], [99.99, 12.935]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 5418, | |
| "qps": 180.55, | |
| "rps": 1805496.5, | |
| "latency_min": 15.25, | |
| "latency_mean": 55.328, | |
| "latency_max": 319.69, | |
| "latency_std": 18.706, | |
| "latency_cv": 33.81, | |
| "latency_percentiles": [[25, 46.07], [50, 52.874], [75, 61.21], [90, 71.622], [99, 106.606], [99.99, 319.689]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 13276, | |
| "qps": 442.4, | |
| "rps": 442400.83, | |
| "latency_min": 6.37, | |
| "latency_mean": 22.585, | |
| "latency_max": 368.3, | |
| "latency_std": 11.394, | |
| "latency_cv": 50.45, | |
| "latency_percentiles": [[25, 20.238], [50, 21.836], [75, 23.709], [90, 25.609], [99, 32.425], [99.99, 365.813]] | |
| }], | |
| "mean": { | |
| "duration": 30.0, | |
| "queries": 69670.82, | |
| "qps": 2322.07, | |
| "rps": 1362999.99, | |
| "latency_min": 1.986, | |
| "latency_mean": 4.3, | |
| "latency_max": 35.922, | |
| "latency_std": 1.235, | |
| "latency_cv": 28.71, | |
| "latency_percentiles": [[25, 3.789], [50, 4.028], [75, 4.335], [90, 4.914], [99, 8.351], [99.99, 27.966]] | |
| } | |
| }, { | |
| "name": "golang-pgx", | |
| "variations": [{ | |
| "duration": 30.01, | |
| "queries": 101988, | |
| "qps": 3398.5, | |
| "rps": 1389986.63, | |
| "latency_min": 0.33, | |
| "latency_mean": 2.936, | |
| "latency_max": 15.56, | |
| "latency_std": 1.698, | |
| "latency_cv": 57.82, | |
| "latency_percentiles": [[25, 1.666], [50, 2.846], [75, 3.815], [90, 4.811], [99, 8.342], [99.99, 12.746]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 272223, | |
| "qps": 9071.54, | |
| "rps": 9071536.83, | |
| "latency_min": 0.19, | |
| "latency_mean": 1.097, | |
| "latency_max": 7.16, | |
| "latency_std": 0.579, | |
| "latency_cv": 52.82, | |
| "latency_percentiles": [[25, 0.62], [50, 1.048], [75, 1.562], [90, 1.778], [99, 2.529], [99.99, 4.493]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 279695, | |
| "qps": 9321.6, | |
| "rps": 932159.85, | |
| "latency_min": 0.11, | |
| "latency_mean": 1.067, | |
| "latency_max": 40.03, | |
| "latency_std": 0.654, | |
| "latency_cv": 61.32, | |
| "latency_percentiles": [[25, 0.774], [50, 0.949], [75, 1.142], [90, 1.485], [99, 3.13], [99.99, 23.291]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 175167, | |
| "qps": 5837.41, | |
| "rps": 583741.24, | |
| "latency_min": 0.81, | |
| "latency_mean": 1.707, | |
| "latency_max": 8.16, | |
| "latency_std": 0.624, | |
| "latency_cv": 36.56, | |
| "latency_percentiles": [[25, 1.307], [50, 1.502], [75, 1.858], [90, 2.519], [99, 3.862], [99.99, 5.77]] | |
| }, { | |
| "duration": 30.18, | |
| "queries": 6390, | |
| "qps": 211.7, | |
| "rps": 2116996.15, | |
| "latency_min": 23.6, | |
| "latency_mean": 46.617, | |
| "latency_max": 557.78, | |
| "latency_std": 27.071, | |
| "latency_cv": 58.07, | |
| "latency_percentiles": [[25, 38.261], [50, 41.523], [75, 47.73], [90, 57.026], [99, 115.922], [99.99, 557.777]] | |
| }, { | |
| "duration": 30.11, | |
| "queries": 11436, | |
| "qps": 379.77, | |
| "rps": 379768.84, | |
| "latency_min": 8.13, | |
| "latency_mean": 26.236, | |
| "latency_max": 229.02, | |
| "latency_std": 9.045, | |
| "latency_cv": 34.47, | |
| "latency_percentiles": [[25, 22.467], [50, 25.18], [75, 28.426], [90, 32.316], [99, 47.593], [99.99, 222.917]] | |
| }], | |
| "mean": { | |
| "duration": 30.05, | |
| "queries": 68060.89, | |
| "qps": 2264.58, | |
| "rps": 1329250.84, | |
| "latency_min": 1.012, | |
| "latency_mean": 4.392, | |
| "latency_max": 40.853, | |
| "latency_std": 2.148, | |
| "latency_cv": 48.92, | |
| "latency_percentiles": [[25, 3.106], [50, 4.055], [75, 5.078], [90, 6.239], [99, 10.586], [99.99, 31.392]] | |
| } | |
| }, { | |
| "name": "golang-libpq", | |
| "variations": [{ | |
| "duration": 30.01, | |
| "queries": 73895, | |
| "qps": 2462.46, | |
| "rps": 1007144.45, | |
| "latency_min": 0.74, | |
| "latency_mean": 4.055, | |
| "latency_max": 12.62, | |
| "latency_std": 1.412, | |
| "latency_cv": 34.83, | |
| "latency_percentiles": [[25, 2.788], [50, 4.175], [75, 5.005], [90, 5.738], [99, 7.629], [99.99, 11.342]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 167807, | |
| "qps": 5592.42, | |
| "rps": 5592418.58, | |
| "latency_min": 0.34, | |
| "latency_mean": 1.782, | |
| "latency_max": 50.55, | |
| "latency_std": 1.611, | |
| "latency_cv": 90.36, | |
| "latency_percentiles": [[25, 0.997], [50, 1.749], [75, 1.993], [90, 2.42], [99, 6.42], [99.99, 40.924]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 77402, | |
| "qps": 2579.34, | |
| "rps": 257933.93, | |
| "latency_min": 0.34, | |
| "latency_mean": 3.871, | |
| "latency_max": 36.56, | |
| "latency_std": 2.739, | |
| "latency_cv": 70.75, | |
| "latency_percentiles": [[25, 2.06], [50, 3.123], [75, 5.006], [90, 7.447], [99, 13.419], [99.99, 25.215]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 257281, | |
| "qps": 8574.6, | |
| "rps": 857459.64, | |
| "latency_min": 0.42, | |
| "latency_mean": 1.161, | |
| "latency_max": 19.88, | |
| "latency_std": 0.399, | |
| "latency_cv": 34.39, | |
| "latency_percentiles": [[25, 0.915], [50, 1.073], [75, 1.294], [90, 1.574], [99, 2.686], [99.99, 7.955]] | |
| }, { | |
| "duration": 30.18, | |
| "queries": 2575, | |
| "qps": 85.31, | |
| "rps": 853124.7, | |
| "latency_min": 28.48, | |
| "latency_mean": 117.033, | |
| "latency_max": 340.99, | |
| "latency_std": 23.955, | |
| "latency_cv": 20.47, | |
| "latency_percentiles": [[25, 105.145], [50, 112.75], [75, 123.278], [90, 134.66], [99, 255.725], [99.99, 340.995]] | |
| }, { | |
| "duration": 30.11, | |
| "queries": 4478, | |
| "qps": 148.7, | |
| "rps": 148704.0, | |
| "latency_min": 52.68, | |
| "latency_mean": 67.153, | |
| "latency_max": 130.53, | |
| "latency_std": 6.476, | |
| "latency_cv": 9.64, | |
| "latency_percentiles": [[25, 63.525], [50, 66.087], [75, 69.32], [90, 73.147], [99, 94.444], [99.99, 130.531]] | |
| }], | |
| "mean": { | |
| "duration": 30.05, | |
| "queries": 37647.93, | |
| "qps": 1252.66, | |
| "rps": 735289.1, | |
| "latency_min": 1.944, | |
| "latency_mean": 7.964, | |
| "latency_max": 52.373, | |
| "latency_std": 2.698, | |
| "latency_cv": 33.88, | |
| "latency_percentiles": [[25, 5.719], [50, 7.53], [75, 9.058], [90, 10.818], [99, 18.691], [99.99, 40.078]] | |
| } | |
| }, { | |
| "name": "nodejs-ts-postgres", | |
| "variations": [{ | |
| "duration": 30.01, | |
| "queries": 59267, | |
| "qps": 1974.71, | |
| "rps": 807655.73, | |
| "latency_min": 3.73, | |
| "latency_mean": 5.062, | |
| "latency_max": 19.14, | |
| "latency_std": 0.934, | |
| "latency_cv": 18.44, | |
| "latency_percentiles": [[25, 4.475], [50, 4.884], [75, 5.278], [90, 5.978], [99, 8.785], [99.99, 17.521]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 176951, | |
| "qps": 5896.3, | |
| "rps": 5896297.66, | |
| "latency_min": 0.77, | |
| "latency_mean": 1.695, | |
| "latency_max": 17.88, | |
| "latency_std": 0.635, | |
| "latency_cv": 37.47, | |
| "latency_percentiles": [[25, 1.302], [50, 1.537], [75, 1.894], [90, 2.354], [99, 3.958], [99.99, 13.336]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 194623, | |
| "qps": 6485.18, | |
| "rps": 648517.78, | |
| "latency_min": 1.07, | |
| "latency_mean": 1.541, | |
| "latency_max": 15.03, | |
| "latency_std": 0.5, | |
| "latency_cv": 32.41, | |
| "latency_percentiles": [[25, 1.237], [50, 1.343], [75, 1.716], [90, 2.107], [99, 3.396], [99.99, 9.461]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 102015, | |
| "qps": 3398.84, | |
| "rps": 339884.02, | |
| "latency_min": 2.12, | |
| "latency_mean": 2.941, | |
| "latency_max": 15.0, | |
| "latency_std": 0.856, | |
| "latency_cv": 29.12, | |
| "latency_percentiles": [[25, 2.352], [50, 2.596], [75, 3.211], [90, 4.108], [99, 6.04], [99.99, 10.198]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 0, | |
| "qps": 0, | |
| "rps": 0, | |
| "latency_min": 0, | |
| "latency_mean": 0, | |
| "latency_max": 0, | |
| "latency_std": 0, | |
| "latency_cv": 0, | |
| "latency_percentiles": [[25, 0], [50, 0], [75, 0], [90, 0], [99, 0], [99.99, 0]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 726, | |
| "qps": 24.19, | |
| "rps": 24371.54, | |
| "latency_min": 0.13, | |
| "latency_mean": 0.41, | |
| "latency_max": 40.94, | |
| "latency_std": 0.347, | |
| "latency_cv": 84.58, | |
| "latency_percentiles": [[25, 0.324], [50, 0.381], [75, 0.449], [90, 0.537], [99, 0.904], [99.99, 21.317]] | |
| }], | |
| "mean": { | |
| "duration": 30.01, | |
| "queries": 43240.64, | |
| "qps": 1440.77, | |
| "rps": 480383.69, | |
| "latency_min": 0.967, | |
| "latency_mean": 1.74, | |
| "latency_max": 19.948, | |
| "latency_std": 0.615, | |
| "latency_cv": 35.34, | |
| "latency_percentiles": [[25, 1.406], [50, 1.584], [75, 1.9], [90, 2.307], [99, 3.647], [99.99, 13.688]] | |
| } | |
| }, { | |
| "name": "nodejs-pg-native", | |
| "variations": [{ | |
| "duration": 30.02, | |
| "queries": 22877, | |
| "qps": 761.99, | |
| "rps": 311654.17, | |
| "latency_min": 7.53, | |
| "latency_mean": 13.116, | |
| "latency_max": 37.24, | |
| "latency_std": 2.466, | |
| "latency_cv": 18.8, | |
| "latency_percentiles": [[25, 11.349], [50, 12.581], [75, 14.586], [90, 16.602], [99, 20.128], [99.99, 33.214]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 90257, | |
| "qps": 3007.24, | |
| "rps": 3007236.37, | |
| "latency_min": 1.45, | |
| "latency_mean": 3.324, | |
| "latency_max": 15.4, | |
| "latency_std": 1.07, | |
| "latency_cv": 32.2, | |
| "latency_percentiles": [[25, 2.619], [50, 2.843], [75, 3.485], [90, 5.271], [99, 6.256], [99.99, 8.699]] | |
| }, { | |
| "duration": 30.03, | |
| "queries": 46467, | |
| "qps": 1547.37, | |
| "rps": 154736.9, | |
| "latency_min": 3.51, | |
| "latency_mean": 6.458, | |
| "latency_max": 147.24, | |
| "latency_std": 3.522, | |
| "latency_cv": 54.55, | |
| "latency_percentiles": [[25, 4.99], [50, 5.859], [75, 7.23], [90, 8.688], [99, 13.099], [99.99, 119.267]] | |
| }, { | |
| "duration": 30.03, | |
| "queries": 16029, | |
| "qps": 533.85, | |
| "rps": 53385.26, | |
| "latency_min": 5.33, | |
| "latency_mean": 18.717, | |
| "latency_max": 154.93, | |
| "latency_std": 8.253, | |
| "latency_cv": 44.1, | |
| "latency_percentiles": [[25, 13.866], [50, 17.334], [75, 21.919], [90, 25.216], [99, 45.564], [99.99, 146.778]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 0, | |
| "qps": 0, | |
| "rps": 0, | |
| "latency_min": 0, | |
| "latency_mean": 0, | |
| "latency_max": 0, | |
| "latency_std": 0, | |
| "latency_cv": 0, | |
| "latency_percentiles": [[25, 0], [50, 0], [75, 0], [90, 0], [99, 0], [99.99, 0]] | |
| }, { | |
| "duration": 30.01, | |
| "queries": 943, | |
| "qps": 31.42, | |
| "rps": 31574.15, | |
| "latency_min": 0.08, | |
| "latency_mean": 0.317, | |
| "latency_max": 67.73, | |
| "latency_std": 0.581, | |
| "latency_cv": 183.5, | |
| "latency_percentiles": [[25, 0.228], [50, 0.28], [75, 0.341], [90, 0.419], [99, 0.769], [99.99, 26.572]] | |
| }], | |
| "mean": { | |
| "duration": 30.02, | |
| "queries": 17072.16, | |
| "qps": 568.68, | |
| "rps": 189512.34, | |
| "latency_min": 1.748, | |
| "latency_mean": 4.411, | |
| "latency_max": 61.588, | |
| "latency_std": 2.137, | |
| "latency_cv": 48.46, | |
| "latency_percentiles": [[25, 3.421], [50, 3.995], [75, 4.873], [90, 6.039], [99, 8.961], [99.99, 42.236]] | |
| } | |
| } | |
| ] | |
| }; | |
| var options = { | |
| width: 800, | |
| height: 300, | |
| showBenchmarkType: true | |
| } | |
| var meanData = []; | |
| var order = {}; | |
| for (var i = 0; i < data.benchmarks.length; i += 1) { | |
| var benchmark = data.benchmarks[i]; | |
| meanData.push({ | |
| 'name': benchmark['name'], | |
| 'data': benchmark['mean'] | |
| }); | |
| } | |
| meanData.sort(function (e1, e2) { | |
| return d3.ascending(e1.data.rps, e2.data.rps); | |
| }) | |
| for (var i = 0; i < meanData.length; i += 1) { | |
| order[meanData[i].name] = i; | |
| } | |
| drawBars('#mean-bars', meanData, options); | |
| drawLats('#mean-lats', meanData, options); | |
| var queriesSection = document.getElementById("queries"); | |
| var nqueries = data.querynames.length; | |
| for (var i = 0; i < data.concurrency_levels.length; i += 1) { | |
| for (var j = 0; j < data.querynames.length; j += 1) { | |
| var queryData = []; | |
| var offset = i * nqueries + j; | |
| for (var k = 0; k < data.benchmarks.length; k += 1) { | |
| var benchmark = data.benchmarks[k]; | |
| queryData.push({ | |
| 'name': benchmark['name'], | |
| 'data': benchmark['variations'][offset] | |
| }); | |
| } | |
| queryData.sort(function (e1, e2) { | |
| return d3.ascending(order[e1.name], order[e2.name]); | |
| }); | |
| drawBars('#query-bars-' + offset, queryData, options); | |
| drawLats('#query-lats-' + offset, queryData, options); | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment