├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── benchmark-pipeline.png ├── benchmark.png ├── benchmark_alloc.png ├── benchmark_latency.png ├── concurrency-pipeline.png ├── concurrency.png ├── concurrency_alloc.png ├── concurrency_latency.png ├── cpubound_benchmark.png ├── cpubound_concurrency.png ├── docker-test.sh ├── go.mod ├── go.sum ├── libs.sh ├── manifest.json ├── pipeline.lua ├── pow.go ├── server.go ├── test-all.sh ├── test-latency-nonkeepalive.sh ├── test-latency.sh ├── test-pipelining.sh ├── test.sh └── testresults ├── benchmark.gnu ├── benchmark_alloc.gnu ├── benchmark_latency.gnu ├── benchmark_pipeline.gnu ├── concurrency-pipeline.csv ├── concurrency.csv ├── concurrency.gnu ├── concurrency_alloc.csv ├── concurrency_alloc.gnu ├── concurrency_latency.csv ├── concurrency_latency.gnu ├── concurrency_pipeline.gnu ├── cpubound-concurrency.csv ├── cpubound.csv ├── cpubound_benchmark.gnu ├── cpubound_concurrency.gnu ├── plot.sh ├── plot_mac.sh ├── processtime-pipeline.csv ├── processtime.csv ├── processtime_alloc.csv ├── processtime_latency.csv ├── transpose.sh └── tst.awk /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | target 10 | 11 | 12 | # Architecture specific extensions/prefixes 13 | *.[568vq] 14 | [568vq].out 15 | 16 | *.cgo1.go 17 | *.cgo2.c 18 | _cgo_defun.c 19 | _cgo_gotypes.go 20 | _cgo_export.* 21 | 22 | _testmain.go 23 | 24 | *.exe 25 | *.test 26 | *.prof 27 | gowebbenchmark 28 | go-web-framework-benchmark 29 | 30 | #ide 31 | .vscode 32 | .idea 33 | 34 | *.log 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - tip 5 | - 1.18.x 6 | 7 | before_script: 8 | - go mod download 9 | 10 | script: 11 | - go build . 12 | 13 | notifications: 14 | email: 15 | recipients: smallnest@gmail.com 16 | on_success: change 17 | on_failure: always 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.14.3-alpine3.11 as builder 2 | 3 | MAINTAINER smallnest 4 | 5 | RUN echo "@community http://mirrors.ustc.edu.cn/alpine/edge/community" >> /etc/apk/repositories \ 6 | && echo "@main http://mirrors.ustc.edu.cn/alpine/edge/main" >> /etc/apk/repositories \ 7 | && sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \ 8 | && apk add git \ 9 | && apk update \ 10 | bash git bash@main 11 | 12 | ENV GOPROXY=https://goproxy.cn,direct 13 | ENV GO111MODULE=on 14 | 15 | RUN mkdir -p $GOPATH/src/github.com/smallnest \ 16 | && cd $GOPATH/src/github.com/smallnest \ 17 | && git clone --depth=1 https://github.com/smallnest/go-web-framework-benchmark.git \ 18 | && cd $GOPATH/src/github.com/smallnest/go-web-framework-benchmark \ 19 | && GO111MODULE=on go mod download \ 20 | && go build -o gowebbenchmark . 21 | 22 | FROM alpine:3.11 23 | 24 | MAINTAINER smallnest 25 | 26 | RUN echo "@community http://mirrors.ustc.edu.cn/alpine/edge/community" >> /etc/apk/repositories \ 27 | && echo "@main http://mirrors.ustc.edu.cn/alpine/edge/main" >> /etc/apk/repositories \ 28 | && sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \ 29 | && apk add \ 30 | bash bash@main libressl3.0-libcrypto@main libressl3.0-libssl@main wrk@community gnuplot@community \ 31 | ttf-dejavu ttf-droid ttf-freefont ttf-liberation ttf-ubuntu-font-family 32 | 33 | VOLUME ["/data"] 34 | 35 | COPY --from=builder /go/src/github.com/smallnest/go-web-framework-benchmark /go-web-framework-benchmark 36 | 37 | WORKDIR /go-web-framework-benchmark 38 | 39 | CMD ["/bin/sh","./docker-test.sh"] 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-web-framework-benchmark 2 | This benchmark suite aims to compare the performance of Go web frameworks. It is inspired by [Go HTTP Router Benchmark](https://github.com/julienschmidt/go-http-routing-benchmark) but this benchmark suite is different with that. Go HTTP Router Benchmark suit aims to compare the performance of **routers** but this Benchmark suit aims to compare whole HTTP request processing. 3 | 4 | **Last Test Updated:** 2020-05 5 | 6 | *test environment* 7 | 8 | * CPU: KVM Virtual CPU version(2 GHz, 4 cores) 9 | * Memory: 16G 10 | * Go: go1.18.5 linux/amd64 11 | * OS: Ubuntu 22.04.1 LTS with Kernel 5.15.0-41-generic 12 | 13 | 14 | ## Tested web frameworks (in alphabetical order) 15 | 16 | **Only test those webframeworks which are stable** 17 | 18 | * [atreugo](https://github.com/savsgio/atreugo) 19 | * [baa](https://github.com/go-baa/baa) 20 | * [beego](https://github.com/astaxie/beego) 21 | * [bone](https://github.com/go-zoo/bone) 22 | * [chi](https://github.com/go-chi/chi) 23 | * [clevergo](https://github.com/clevergo/clevergo) 24 | * [default http](https://golang.org/pkg/net/http/) 25 | * [denco](https://github.com/naoina/denco) 26 | * [don](https://github.com/abemedia/go-don) 27 | * [echo](https://github.com/labstack/echo) 28 | * [fasthttp-routing](https://github.com/qiangxue/fasthttp-routing) 29 | * [fasthttp/router](https://github.com/fasthttp/router) 30 | * [fasthttp](https://github.com/valyala/fasthttp) 31 | * [fiber](https://gofiber.io/) 32 | * [gear](http://github.com/teambition/gear) 33 | * [gearbox](https://github.com/gogearbox/gearbox) 34 | * [gem](https://github.com/go-gem/gem) 35 | * [gin](https://github.com/gin-gonic/gin) 36 | * [goframe](https://github.com/gogf/gf) 37 | * [go-ozzo](https://github.com/go-ozzo/ozzo-routing) 38 | * [go-restful](https://github.com/emicklei/go-restful) 39 | * [go-tigertonic](https://github.com/rcrowley/go-tigertonic) 40 | * [goji](https://github.com/zenazn/goji/web) 41 | * [goji](http://goji.io) 42 | * [golf](https://github.com/dinever/golf) 43 | * [gorilla](https://github.com/gorilla/mux) 44 | * [gorouter](https://github.com/vardius/gorouter) 45 | * [goyave](https://github.com/System-Glitch/goyave) 46 | * [httprouter](https://github.com/julienschmidt/httprouter) 47 | * [httptreemux](https://github.com/dimfeld/httptreemux) 48 | * [httpz](https://github.com/aeilang/httpz) 49 | * [indigo](https://github.com/indigo-web/indigo) 50 | * [lars](https://github.com/go-playground/lars) 51 | * [lion](https://github.com/celrenheit/lion) 52 | * [macaron](https://github.com/Unknwon/macaron) 53 | * [muxie](https://github.com/kataras/muxie) 54 | * [negroni](https://github.com/urfave/negroni) 55 | * [pat](https://github.com/bmizerany/pat) 56 | * [pulse](https://github.com/gopulse/pulse) 57 | * [pure](https://github.com/go-playground/pure) 58 | * [r2router](https://github.com/vanng822/r2router) 59 | * [tango](https://github.com/lunny/tango) 60 | * [tinyrouter](https://github.com/go101/tinyrouter) 61 | * [treemux](https://github.com/vmihailenco/treemux) 62 | * [violetear](https://github.com/nbari/violetear) 63 | * [vulcan](https://github.com/mailgun/route) 64 | * [webgo](https://github.com/bnkamalesh/webgo) 65 | 66 | **some libs have not been maintained and the test code has removed them** 67 | 68 | ## Motivation 69 | When I investigated performance of Go web frameworks, I found [Go HTTP Router Benchmark](https://github.com/julienschmidt/go-http-routing-benchmark), created by Julien Schmidt. He also developed a high performance http router: [httprouter](https://github.com/julienschmidt/httprouter). I had thought I got the performance result until I created a piece of codes to mock the real business logics: 70 | 71 | ```go 72 | api.Get("/rest/hello", func(c *XXXXX.Context) { 73 | sleepTime := strconv.Atoi(os.Args[1]) //10ms 74 | if sleepTime > 0 { 75 | time.Sleep(time.Duration(sleepTime) * time.Millisecond) 76 | } 77 | 78 | c.Text("Hello world") 79 | }) 80 | ``` 81 | 82 | When I use the above codes to test those web frameworks, the token time of route selection is not so important in the whole http request processing, although performance of route selection of web frameworks are very different. 83 | 84 | So I create this project to compare performance of web frameworks including connection, route selection, handler processing. It mocks business logics and can set a special processing time. 85 | 86 | Then you can get some interesting results if you use it to test. 87 | 88 | ## Implementation 89 | When you test a web framework, this test suit will starts a simple http server implemented by this web framework. It is a real http server and only contains GET url: "/hello". 90 | 91 | When this server processes this url, it will sleep n milliseconds in this handler. It mocks the business logics such as: 92 | * read data from sockets 93 | * write data to disk 94 | * access databases 95 | * access cache servers 96 | * invoke other microservices 97 | * …… 98 | 99 | It contains a test.sh that can do those tests automatically. 100 | 101 | It uses [wrk](https://github.com/wg/wrk/) to test. 102 | 103 | ## Basic Test 104 | The first test case is to mock 0 ms, 10 ms, 100 ms, 500 ms processing time in handlers. 105 | 106 | ![Benchmark (Round 3)](benchmark.png) 107 | the concurrency clients are 5000. 108 | 109 | ![Latency (Round 3)](benchmark_latency.png) 110 | Latency is the time of real processing time by web servers. The smaller is the better. 111 | 112 | ![Allocs (Round 3)](benchmark_alloc.png) 113 | Allocs is the heap allocations by web servers when test is running. The unit is MB. The smaller is the better. 114 | 115 | 116 | If we enable http pipelining, test result as below: 117 | 118 | ![benchmark pipelining (Round 2)](benchmark-pipeline.png) 119 | 120 | ## Concurrency Test 121 | In 30 ms processing time, the test result for 100, 1000, 5000 clients is: 122 | 123 | ![concurrency (Round 3)](concurrency.png) 124 | 125 | ![Latency (Round 3)](concurrency_latency.png) 126 | 127 | ![Latency (Round 3)](concurrency_alloc.png) 128 | 129 | 130 | If we enable http pipelining, test result as below: 131 | 132 | ![concurrency pipelining(Round 2)](concurrency-pipeline.png) 133 | 134 | 135 | ## cpu-bound case Test 136 | 137 | ![cpu-bound (5000 concurrency)](cpubound_benchmark.png) 138 | 139 | ## Usage 140 | You should install this package first if you want to run this test. 141 | 142 | ``` 143 | go get github.com/smallnest/go-web-framework-benchmark 144 | ``` 145 | 146 | It takes a while to install a large number of dependencies that need to be downloaded. Once that command completes, you can run: 147 | 148 | ``` 149 | cd $GOPATH/src/github.com/smallnest/go-web-framework-benchmark 150 | go build -o gowebbenchmark . 151 | ./test.sh 152 | ``` 153 | 154 | It will generate test results in processtime.csv and concurrency.csv. You can modify test.sh to execute your customized test cases. 155 | 156 | 157 | * If you also want to generate latency data and allocation data, you can run the script: 158 | ``` 159 | ./test-latency.sh 160 | ``` 161 | 162 | * If you don't want use keepalive, you can run: 163 | ``` 164 | ./test-latency-nonkeepalive.sh 165 | ``` 166 | 167 | * If you want to test http pipelining, you can run: 168 | ``` 169 | ./test-pipelining.sh 170 | ``` 171 | 172 | * If you want to test some of web frameworks, you can modify the test script and only keep your selected web frameworks: 173 | ``` 174 | …… 175 | web_frameworks=("default" "atreugo" "beego" "bone" "chi" "denco" "don" "echo" "fasthttp" "fasthttp-routing" "fasthttp/router" "fiber" "gear" "gearbox" "gin" "goframe" "goji" "gorestful" "gorilla" "gorouter" "gorouterfasthttp" "go-ozzo" "goyave" "httprouter" "httptreemux" "indigo" "lars" "lion" "muxie" "negroni" "pat" "pulse" "pure" "r2router" "tango" "tiger" "tinyrouter" "violetear" "vulcan" "webgo") 176 | …… 177 | ``` 178 | * If you want to test all cases, you can run: 179 | 180 | ``` 181 | ./test-all.sh 182 | ``` 183 | 184 | NOTE: comparing 2 webframeworks consumes approx. 11-13 minutes (doesn't depend on the machine). Just `test.sh` with all 185 | the webframeworks enabled will take a couple of hours to run. 186 | 187 | ## Plot 188 | All the graphs are generated automatically as the `./test.sh` finishes. However, if the run was interrupted, you can 189 | generate them manually of partial data by executing `plot.sh` in testresults directory. 190 | 191 | ### Add new web framework 192 | Welcome to add new Go web frameworks. You can follow the below steps and send me a pull request. 193 | 194 | 1. add your web framework link in README 195 | 2. add a hello implementation in server.go 196 | 3. add your webframework in libs.sh 197 | 198 | Please add your web framework alphabetically. 199 | -------------------------------------------------------------------------------- /benchmark-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/benchmark-pipeline.png -------------------------------------------------------------------------------- /benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/benchmark.png -------------------------------------------------------------------------------- /benchmark_alloc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/benchmark_alloc.png -------------------------------------------------------------------------------- /benchmark_latency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/benchmark_latency.png -------------------------------------------------------------------------------- /concurrency-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/concurrency-pipeline.png -------------------------------------------------------------------------------- /concurrency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/concurrency.png -------------------------------------------------------------------------------- /concurrency_alloc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/concurrency_alloc.png -------------------------------------------------------------------------------- /concurrency_latency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/concurrency_latency.png -------------------------------------------------------------------------------- /cpubound_benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/cpubound_benchmark.png -------------------------------------------------------------------------------- /cpubound_concurrency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallnest/go-web-framework-benchmark/93e9b1b101dffc7338ad6928ecc2f2164a31041e/cpubound_concurrency.png -------------------------------------------------------------------------------- /docker-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | chmod +x *.sh 4 | 5 | ./test-latency.sh 6 | ./test-pipelining.sh 7 | cd testresults 8 | ./plot.sh 9 | cd .. 10 | cp -R testresults /data/testresults 11 | cp *.png /data/testresults -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/smallnest/go-web-framework-benchmark 2 | 3 | go 1.23.3 4 | 5 | require ( 6 | github.com/abemedia/go-don v0.2.1 7 | github.com/aeilang/httpz v1.1.2 8 | github.com/ant0ine/go-json-rest v3.3.2+incompatible 9 | github.com/astaxie/beego v1.12.3 10 | github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f 11 | github.com/bnkamalesh/webgo/v7 v7.0.0 12 | github.com/claygod/Bxog v0.0.0-20220907175109-bec75fbdd5e7 13 | github.com/dimfeld/httptreemux v5.0.1+incompatible 14 | github.com/dinever/golf v0.3.0 15 | github.com/emicklei/go-restful v2.16.0+incompatible 16 | github.com/fasthttp/router v1.4.22 17 | github.com/gin-gonic/gin v1.9.1 18 | github.com/go-chi/chi/v5 v5.0.10 19 | github.com/go-ozzo/ozzo-routing v2.1.4+incompatible 20 | github.com/go-playground/lars v4.0.1+incompatible 21 | github.com/go-playground/pure v4.2.0+incompatible 22 | github.com/go-zoo/bone v1.3.0 23 | github.com/gocraft/web v0.0.0-20190207150652-9707327fb69b 24 | github.com/gofiber/fiber/v2 v2.51.0 25 | github.com/gogearbox/gearbox v1.2.4 26 | github.com/gogf/gf/v2 v2.5.7 27 | github.com/gopulse/pulse v1.1.0 28 | github.com/gorilla/mux v1.8.1 29 | github.com/indigo-web/indigo v0.15.8 30 | github.com/julienschmidt/httprouter v1.3.0 31 | github.com/kataras/muxie v1.1.2 32 | github.com/labstack/echo/v4 v4.11.3 33 | github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de 34 | github.com/lunny/tango v0.5.6 35 | github.com/mailgun/route v0.0.0-20191025171320-daa4df6c711a 36 | github.com/naoina/denco v0.0.0-20180930074809-8475105a6b4c 37 | github.com/nbari/violetear v0.0.0-20210524103009-ce83b52538c9 38 | github.com/qiangxue/fasthttp-routing v0.0.0-20160225050629-6ccdc2a18d87 39 | github.com/rcrowley/go-tigertonic v0.0.0-20170420123839-fe6b9f080eb7 40 | github.com/savsgio/atreugo/v11 v11.12.0 41 | github.com/teambition/gear v1.27.3 42 | github.com/urfave/negroni v1.0.0 43 | github.com/valyala/fasthttp v1.51.0 44 | github.com/vanng822/r2router v0.0.0-20150523112421-1023140a4f30 45 | github.com/vardius/gorouter/v4 v4.5.1 46 | go101.org/tinyrouter v1.0.1 47 | goji.io v2.0.2+incompatible 48 | golang.org/x/net v0.19.0 49 | gopkg.in/baa.v1 v1.2.32 50 | gopkg.in/celrenheit/lion.v1 v1.0.0-20161101201550-7c6ce5d22d64 51 | goyave.dev/goyave/v4 v4.4.11 52 | ) 53 | 54 | require ( 55 | gitea.com/lunny/log v0.0.0-20190322053110-01b5df579c4e // indirect 56 | github.com/BurntSushi/toml v1.3.2 // indirect 57 | github.com/Code-Hex/uniseg v0.2.0 // indirect 58 | github.com/abemedia/fasthttpfs v0.0.0-20220405193636-731805b0c723 // indirect 59 | github.com/abemedia/httprouter v0.0.0-20230505023925-232e0e5a4b1b // indirect 60 | github.com/andybalholm/brotli v1.0.6 // indirect 61 | github.com/beorn7/perks v1.0.1 // indirect 62 | github.com/bytedance/sonic v1.10.2 // indirect 63 | github.com/celrenheit/htest v0.0.0-20170621160705-e34d50431e7f // indirect 64 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 65 | github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect 66 | github.com/chenzhuoyu/iasm v0.9.1 // indirect 67 | github.com/clbanning/mxj/v2 v2.7.0 // indirect 68 | github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect 69 | github.com/davecgh/go-spew v1.1.1 // indirect 70 | github.com/fatih/color v1.16.0 // indirect 71 | github.com/fsnotify/fsnotify v1.7.0 // indirect 72 | github.com/gabriel-vasile/mimetype v1.4.3 // indirect 73 | github.com/gin-contrib/sse v0.1.0 // indirect 74 | github.com/go-http-utils/cookie v1.3.1 // indirect 75 | github.com/go-http-utils/negotiator v1.0.0 // indirect 76 | github.com/go-logr/logr v1.3.0 // indirect 77 | github.com/go-logr/stdr v1.2.2 // indirect 78 | github.com/go-playground/form v3.1.4+incompatible // indirect 79 | github.com/go-playground/locales v0.14.1 // indirect 80 | github.com/go-playground/universal-translator v0.18.1 // indirect 81 | github.com/go-playground/validator/v10 v10.16.0 // indirect 82 | github.com/goccy/go-json v0.10.2 // indirect 83 | github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f // indirect 84 | github.com/google/uuid v1.4.0 // indirect 85 | github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect 86 | github.com/gorilla/websocket v1.5.1 // indirect 87 | github.com/gravitational/trace v1.3.1 // indirect 88 | github.com/grokify/html-strip-tags-go v0.1.0 // indirect 89 | github.com/hashicorp/golang-lru v1.0.2 // indirect 90 | github.com/imdario/mergo v0.3.16 // indirect 91 | github.com/indigo-web/chunkedbody v0.1.0 // indirect 92 | github.com/indigo-web/iter v0.1.0 // indirect 93 | github.com/indigo-web/utils v0.6.1 // indirect 94 | github.com/jinzhu/inflection v1.0.0 // indirect 95 | github.com/jinzhu/now v1.1.5 // indirect 96 | github.com/jonboulle/clockwork v0.4.0 // indirect 97 | github.com/json-iterator/go v1.1.12 // indirect 98 | github.com/klauspost/compress v1.17.4 // indirect 99 | github.com/klauspost/cpuid/v2 v2.2.6 // indirect 100 | github.com/labstack/gommon v0.4.1 // indirect 101 | github.com/leodido/go-urn v1.2.4 // indirect 102 | github.com/magiconair/properties v1.8.7 // indirect 103 | github.com/mattn/go-colorable v0.1.13 // indirect 104 | github.com/mattn/go-isatty v0.0.20 // indirect 105 | github.com/mattn/go-runewidth v0.0.15 // indirect 106 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect 107 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 108 | github.com/modern-go/reflect2 v1.0.2 // indirect 109 | github.com/olekukonko/tablewriter v0.0.5 // indirect 110 | github.com/pelletier/go-toml/v2 v2.1.0 // indirect 111 | github.com/pmezard/go-difflib v1.0.0 // indirect 112 | github.com/prometheus/client_golang v1.17.0 // indirect 113 | github.com/prometheus/client_model v0.5.0 // indirect 114 | github.com/prometheus/common v0.45.0 // indirect 115 | github.com/prometheus/procfs v0.12.0 // indirect 116 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect 117 | github.com/rivo/uniseg v0.4.4 // indirect 118 | github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect 119 | github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect 120 | github.com/sirupsen/logrus v1.9.3 // indirect 121 | github.com/smartystreets/assertions v1.0.1 // indirect 122 | github.com/smartystreets/goconvey v1.6.4 // indirect 123 | github.com/stretchr/testify v1.10.0 // indirect 124 | github.com/teambition/trie-mux v1.5.2 // indirect 125 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 126 | github.com/ugorji/go/codec v1.2.12 // indirect 127 | github.com/valyala/bytebufferpool v1.0.0 // indirect 128 | github.com/valyala/fasttemplate v1.2.2 // indirect 129 | github.com/valyala/tcplisten v1.0.0 // indirect 130 | github.com/vulcand/predicate v1.2.0 // indirect 131 | go.opentelemetry.io/otel v1.21.0 // indirect 132 | go.opentelemetry.io/otel/metric v1.21.0 // indirect 133 | go.opentelemetry.io/otel/sdk v1.21.0 // indirect 134 | go.opentelemetry.io/otel/trace v1.21.0 // indirect 135 | golang.org/x/arch v0.6.0 // indirect 136 | golang.org/x/crypto v0.17.0 // indirect 137 | golang.org/x/sys v0.15.0 // indirect 138 | golang.org/x/term v0.15.0 // indirect 139 | golang.org/x/text v0.14.0 // indirect 140 | google.golang.org/protobuf v1.31.0 // indirect 141 | gopkg.in/go-playground/assert.v1 v1.2.1 // indirect 142 | gopkg.in/yaml.v2 v2.4.0 // indirect 143 | gopkg.in/yaml.v3 v3.0.1 // indirect 144 | gorm.io/gorm v1.25.5 // indirect 145 | ) 146 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | gitea.com/lunny/log v0.0.0-20190322053110-01b5df579c4e h1:r1en/D7xJmcY24VkHkjkcJFa+7ZWubVWPBrvsHkmHxk= 5 | gitea.com/lunny/log v0.0.0-20190322053110-01b5df579c4e/go.mod h1:uJEsN4LQpeGYRCjuPXPZBClU7N5pWzGuyF4uqLpE/e0= 6 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 7 | github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= 8 | github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= 9 | github.com/Code-Hex/uniseg v0.2.0 h1:QB/2UJFvEuRLSZqe+Sb1XQBTWjqGVbZoC6oSWzQRKws= 10 | github.com/Code-Hex/uniseg v0.2.0/go.mod h1:/ndS2tP+X1lk2HUOcXWGtVTxVq0lWilwgMa4CbzdRsg= 11 | github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= 12 | github.com/abemedia/fasthttpfs v0.0.0-20220321013016-a7e6ad30856d/go.mod h1:Q7fRPwbRn+E/hqQEU2ZnMbp9juhSZBcSl3/aQrr+apQ= 13 | github.com/abemedia/fasthttpfs v0.0.0-20220405193636-731805b0c723 h1:gq2jKsEsHvR+R0InqnbxLQ5/L2bRTfXieNLAMhQir3I= 14 | github.com/abemedia/fasthttpfs v0.0.0-20220405193636-731805b0c723/go.mod h1:Q7fRPwbRn+E/hqQEU2ZnMbp9juhSZBcSl3/aQrr+apQ= 15 | github.com/abemedia/go-don v0.2.1 h1:h/7gDjPtZZ6gcIEM0+RRfw7nVTpCdgdk1osAC042oLY= 16 | github.com/abemedia/go-don v0.2.1/go.mod h1:vNEBqEPwuftAoR1DncTyo+v6OpDpuHaefvd1HCJZ1rU= 17 | github.com/abemedia/httprouter v0.0.0-20230505023925-232e0e5a4b1b h1:/0hlaEP0jHdeE/SxFO0fT6AdHUtaQp0rbOkxydJ2Bsc= 18 | github.com/abemedia/httprouter v0.0.0-20230505023925-232e0e5a4b1b/go.mod h1:jMATPO/ttg245+tl+jaLzgZs03RS9coyM87qNPzk594= 19 | github.com/aeilang/httpz v1.1.2 h1:qauRPrRyARQS6pPYsr7hH9nj746iHo80GXG0LGSXkec= 20 | github.com/aeilang/httpz v1.1.2/go.mod h1:TGIqnz0Xv+8a6357GxNXW4E4mPZf7Eit+tO2YOoA9Pw= 21 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 22 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 23 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 24 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 25 | github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= 26 | github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= 27 | github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 28 | github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 29 | github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 30 | github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 31 | github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= 32 | github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 33 | github.com/ant0ine/go-json-rest v3.3.2+incompatible h1:nBixrkLFiDNAW0hauKDLc8yJI6XfrQumWvytE1Hk14E= 34 | github.com/ant0ine/go-json-rest v3.3.2+incompatible/go.mod h1:q6aCt0GfU6LhpBsnZ/2U+mwe+0XB5WStbmwyoPfc+sk= 35 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 36 | github.com/astaxie/beego v1.12.3 h1:SAQkdD2ePye+v8Gn1r4X6IKZM1wd28EyUOVQ3PDSOOQ= 37 | github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA= 38 | github.com/atreugo/mock v0.0.0-20200601091009-13c275b330b0 h1:IVqe9WnancrkICl5HqEfGjrnkQ4+VsU5fodcuFVoG/A= 39 | github.com/atreugo/mock v0.0.0-20200601091009-13c275b330b0/go.mod h1:HTHAc8RoZXMVTr6wZQN7Jjm3mYMnbfkqqKdnQgSoe9o= 40 | github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= 41 | github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU= 42 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 43 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 44 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 45 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 46 | github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f h1:gOO/tNZMjjvTKZWpY7YnXC72ULNLErRtp94LountVE8= 47 | github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= 48 | github.com/bnkamalesh/webgo/v7 v7.0.0 h1:Kdr32fx45IlSKmJfUeFipLKXxV+ETgynKpFV1/fCtmU= 49 | github.com/bnkamalesh/webgo/v7 v7.0.0/go.mod h1:zS1pR4L5TSKja095la5nbv2yZ59/c4PoSungO93E8UQ= 50 | github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= 51 | github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= 52 | github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= 53 | github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= 54 | github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= 55 | github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= 56 | github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE= 57 | github.com/celrenheit/htest v0.0.0-20170621160705-e34d50431e7f h1:sy5oFuyOJ5P2g/KEwew4rHQKER3Uywg2bYcl6YnJ87w= 58 | github.com/celrenheit/htest v0.0.0-20170621160705-e34d50431e7f/go.mod h1:0zX1O1sXFhadsmZnArP5n6duBGwZRP0fI7SVUAyekkk= 59 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 60 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 61 | github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= 62 | github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 63 | github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= 64 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= 65 | github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= 66 | github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= 67 | github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= 68 | github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= 69 | github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= 70 | github.com/claygod/Bxog v0.0.0-20220907175109-bec75fbdd5e7 h1:oEn59JJnyYvuaWHZQnDVM+hsEL9HHHJo7OWXppaBjDk= 71 | github.com/claygod/Bxog v0.0.0-20220907175109-bec75fbdd5e7/go.mod h1:GuK03YiV7WAMMshUm3QfWeSIJKB1HXMkNJxdK6O+m/c= 72 | github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= 73 | github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= 74 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 75 | github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= 76 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 77 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 78 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 79 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 80 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 81 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 82 | github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ= 83 | github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= 84 | github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U= 85 | github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= 86 | github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= 87 | github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY= 88 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 89 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 90 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 91 | github.com/dchest/uniuri v1.2.0 h1:koIcOUdrTIivZgSLhHQvKgqdWZq5d7KdMEWF1Ud6+5g= 92 | github.com/dchest/uniuri v1.2.0/go.mod h1:fSzm4SLHzNZvWLvWJew423PhAzkpNQYq+uNLq4kxhkY= 93 | github.com/dimfeld/httptreemux v5.0.1+incompatible h1:Qj3gVcDNoOthBAqftuD596rm4wg/adLLz5xh5CmpiCA= 94 | github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0= 95 | github.com/dinever/golf v0.3.0 h1:IfJWVKNo+ZUS5+IY+SvGBuIB3W5eDs84iMMGG56l9xg= 96 | github.com/dinever/golf v0.3.0/go.mod h1:s2Uat88hzITpOsCJqribLtyLvAP+b4jyZxVNzXvsnY4= 97 | github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= 98 | github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI= 99 | github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= 100 | github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= 101 | github.com/emicklei/go-restful v2.16.0+incompatible h1:rgqiKNjTnFQA6kkhFe16D8epTksy9HQ1MyrbDXSdYhM= 102 | github.com/emicklei/go-restful v2.16.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 103 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 104 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 105 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 106 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 107 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 108 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 109 | github.com/fasthttp/router v1.4.22 h1:qwWcYBbndVDwts4dKaz+A2ehsnbKilmiP6pUhXBfYKo= 110 | github.com/fasthttp/router v1.4.22/go.mod h1:KeMvHLqhlB9vyDWD5TSvTccl9qeWrjSSiTJrJALHKV0= 111 | github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= 112 | github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= 113 | github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 114 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 115 | github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= 116 | github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= 117 | github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= 118 | github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= 119 | github.com/garyburd/redigo v1.1.1-0.20170914051019-70e1b1943d4f/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= 120 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 121 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 122 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 123 | github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= 124 | github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= 125 | github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw= 126 | github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= 127 | github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= 128 | github.com/go-http-utils/cookie v1.3.1 h1:GCdTeqVV5vDcjP7LrgYpH8pbt3dOYKS+Wrs7Jo3/k/w= 129 | github.com/go-http-utils/cookie v1.3.1/go.mod h1:ATl4rfG3bEemjiVa+8WIfgNcBUWdYBTasfXKjJ3Avt8= 130 | github.com/go-http-utils/negotiator v1.0.0 h1:Qp1zofD6Nw7KXApXa3pAjehP06Js0ILguEBCnHhZeVA= 131 | github.com/go-http-utils/negotiator v1.0.0/go.mod h1:mTQe1sH0XhdFkeDiWpCY3QSk7Apo5jwOlIwLWJbJe2c= 132 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 133 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 134 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 135 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 136 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 137 | github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= 138 | github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 139 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 140 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 141 | github.com/go-ozzo/ozzo-routing v2.1.4+incompatible h1:gQmNyAwMnBHr53Nma2gPTfVVc6i2BuAwCWPam2hIvKI= 142 | github.com/go-ozzo/ozzo-routing v2.1.4+incompatible/go.mod h1:hvoxy5M9SJaY0viZvcCsODidtUm5CzRbYKEWuQpr+2A= 143 | github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= 144 | github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 145 | github.com/go-playground/form v3.1.4+incompatible h1:lvKiHVxE2WvzDIoyMnWcjyiBxKt2+uFJyZcPYWsLnjI= 146 | github.com/go-playground/form v3.1.4+incompatible/go.mod h1:lhcKXfTuhRtIZCIKUeJ0b5F207aeQCPbZU09ScKjwWg= 147 | github.com/go-playground/lars v4.0.1+incompatible h1:d0q8YUzAggHd1iiWgIJKLpHMa2VLEc5a/oCIJLxjHgY= 148 | github.com/go-playground/lars v4.0.1+incompatible/go.mod h1:N3/k870eeSGPNoqbBzTb/PUpQ3uI5ag39Gt8TquOoEo= 149 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= 150 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 151 | github.com/go-playground/pure v4.2.0+incompatible h1:fwvKudP25N9ilfdxSwvFtO8fxdJyYgddcHQOq7v8qlA= 152 | github.com/go-playground/pure v4.2.0+incompatible/go.mod h1:k2eRJXw80qTBI0vn3rVf3CcZRLtdbPb0FPV7sDZGk5o= 153 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= 154 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= 155 | github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= 156 | github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= 157 | github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= 158 | github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 159 | github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= 160 | github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= 161 | github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 162 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 163 | github.com/go-zoo/bone v1.3.0 h1:PY6sHq37FnQhj+4ZyqFIzJQHvrrGx0GEc3vTZZC/OsI= 164 | github.com/go-zoo/bone v1.3.0/go.mod h1:HI3Lhb7G3UQcAwEhOJ2WyNcsFtQX1WYHa0Hl4OBbhW8= 165 | github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= 166 | github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= 167 | github.com/gocraft/web v0.0.0-20190207150652-9707327fb69b h1:g2Qcs0B+vOQE1L3a7WQ/JUUSzJnHbTz14qkJSqEWcF4= 168 | github.com/gocraft/web v0.0.0-20190207150652-9707327fb69b/go.mod h1:Ag7UMbZNGrnHwaXPJOUKJIVgx4QOWMOWZngrvsN6qak= 169 | github.com/gofiber/fiber/v2 v2.51.0 h1:JNACcZy5e2tGApWB2QrRpenTWn0fq0hkFm6k0C86gKQ= 170 | github.com/gofiber/fiber/v2 v2.51.0/go.mod h1:xaQRZQJGqnKOQnbQw+ltvku3/h8QxvNi8o6JiJ7Ll0U= 171 | github.com/gogearbox/gearbox v1.2.4 h1:h7GNxGRltV63UCGl0smFWKAhScMkFlc5dCZi9k/fFqo= 172 | github.com/gogearbox/gearbox v1.2.4/go.mod h1:IIUyEDzcMVjnA8bkUM7etHHrgzVj70naUDlE2QZk/QU= 173 | github.com/gogf/gf/v2 v2.5.7 h1:h+JSoD6z3d2q0uGszvtahrSm4DiM2ECyNjyTwKIo8wE= 174 | github.com/gogf/gf/v2 v2.5.7/go.mod h1:x2XONYcI4hRQ/4gMNbWHmZrNzSEIg20s2NULbzom5k0= 175 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 176 | github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f h1:16RtHeWGkJMc80Etb8RPCcKevXGldr57+LOyZt8zOlg= 177 | github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f/go.mod h1:ijRvpgDJDI262hYq/IQVYgf8hd8IHUs93Ol0kvMBAx4= 178 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 179 | github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= 180 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 181 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 182 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 183 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 184 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 185 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 186 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 187 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 188 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 189 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 190 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 191 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 192 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 193 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 194 | github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 195 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 196 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 197 | github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= 198 | github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 199 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 200 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 201 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 202 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 203 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 204 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 205 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 206 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 207 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 208 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 209 | github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= 210 | github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 211 | github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= 212 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 213 | github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= 214 | github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 215 | github.com/gopulse/pulse v1.1.0 h1:llH5RJLPpLuHcIBTZfzEQarNN2q+X1hMWx1i9oEtMIE= 216 | github.com/gopulse/pulse v1.1.0/go.mod h1:yY85fBCgKLqXbhV/nlEcfYE3qT4Dr+IQ9gDCYmj6OCg= 217 | github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= 218 | github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= 219 | github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= 220 | github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= 221 | github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf/go.mod h1:zXqxTI6jXDdKnlf8s+nT+3c8LrwUEy3yNpO4XJL90lA= 222 | github.com/gravitational/trace v1.3.1 h1:jwZEuRtCYpLhUtqHo+JH+lu2qM0LB98UagqHtvdKuLI= 223 | github.com/gravitational/trace v1.3.1/go.mod h1:E61mn73aro7Zg9gZheZaeUsK6gjUMbCLazY76xuYAVA= 224 | github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 225 | github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= 226 | github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= 227 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 228 | github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 229 | github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= 230 | github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 231 | github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= 232 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 233 | github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= 234 | github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= 235 | github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= 236 | github.com/indigo-web/chunkedbody v0.1.0 h1:fZerB4rS9aufemrNTPPKOMSWsgnImfuW4g1lxnWISHI= 237 | github.com/indigo-web/chunkedbody v0.1.0/go.mod h1:E3IVH0uH1ePqQO4n76M2EVPplGyqZTP88MpR3kRj/mE= 238 | github.com/indigo-web/indigo v0.15.8 h1:p62vDAetvT+UelgVsAzXR3Y0s40OCu4FFeYbbtO7X/M= 239 | github.com/indigo-web/indigo v0.15.8/go.mod h1:+UcymCBzgMcmZQh2od09GC9aTm4akrOZxlgVbXqMjes= 240 | github.com/indigo-web/iter v0.1.0 h1:3LJG319EytEULerDX6meT4xW/lqncIqTnZewsMtiPT4= 241 | github.com/indigo-web/iter v0.1.0/go.mod h1:hftmhzfi4hpWc715PmXsfMjE1K0FLwznr+iyLxM7wyQ= 242 | github.com/indigo-web/utils v0.6.1 h1:WWvqTchkwQU/RdOyEeSuEf6Cy/XMItllftbnCQM1Z/g= 243 | github.com/indigo-web/utils v0.6.1/go.mod h1:Q+voOJjIRN7DV+ifWozy6RY6cDF10Ev0NPDjsuOAXfQ= 244 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 245 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 246 | github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= 247 | github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 248 | github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= 249 | github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= 250 | github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= 251 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 252 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 253 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 254 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 255 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 256 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 257 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 258 | github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= 259 | github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 260 | github.com/kataras/muxie v1.1.2 h1:adKtuNVFwT7TlGG2eIfhNYyRMK5CyjXw0F31HAv6POE= 261 | github.com/kataras/muxie v1.1.2/go.mod h1:xvAGGV93oksm/i9OBHyHqbiwUk1OenPd5CllnuO5lNU= 262 | github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= 263 | github.com/klauspost/compress v1.10.11/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= 264 | github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 265 | github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 266 | github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 267 | github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 268 | github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= 269 | github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= 270 | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 271 | github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= 272 | github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= 273 | github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= 274 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 275 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 276 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 277 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 278 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 279 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 280 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 281 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 282 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 283 | github.com/labstack/echo/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM= 284 | github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws= 285 | github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk= 286 | github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM= 287 | github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ= 288 | github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= 289 | github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= 290 | github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 291 | github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de h1:nyxwRdWHAVxpFcDThedEgQ07DbcRc5xgNObtbTp76fk= 292 | github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ= 293 | github.com/lunny/tango v0.5.6 h1:QeUe+2ksZ3LScC+SKhDbS1wbS/ctuyRnZ3fAsL10J4M= 294 | github.com/lunny/tango v0.5.6/go.mod h1:qW1SakbmM67DdOHN6mipeYWhB1Uu6lYsgU3u6fQmu5o= 295 | github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 296 | github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= 297 | github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= 298 | github.com/mailgun/route v0.0.0-20191025171320-daa4df6c711a h1:3ZDkgSvdDLq/cZY4bfvKrza446kw2MY54l9kuKLrjeE= 299 | github.com/mailgun/route v0.0.0-20191025171320-daa4df6c711a/go.mod h1:iitUOLTydv/b+q12z6vQ163uUDAZmUa5O2i/fOo7P7M= 300 | github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 301 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 302 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 303 | github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 304 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 305 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 306 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 307 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 308 | github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= 309 | github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 310 | github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 311 | github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= 312 | github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 313 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 314 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= 315 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 316 | github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 317 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 318 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 319 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 320 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 321 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 322 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 323 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 324 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 325 | github.com/naoina/denco v0.0.0-20180930074809-8475105a6b4c h1:OuYPoLEOYbguEn/ihiCTfWM0cjzY5R77CA2vzmx2M8Y= 326 | github.com/naoina/denco v0.0.0-20180930074809-8475105a6b4c/go.mod h1:rJwHqj5scxcViM0kq4dh/d1E9sLBeI1snvkNVX4mQGY= 327 | github.com/nbari/violetear v0.0.0-20210524103009-ce83b52538c9 h1:L5+NHqJtAZ/BBVY3A3YkAeiPp5q8bXuufST62E2Skpo= 328 | github.com/nbari/violetear v0.0.0-20210524103009-ce83b52538c9/go.mod h1:DZERM3bJoILVxK77tZRrEyLyAoQdgFEM2uYtwWMUjPU= 329 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 330 | github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= 331 | github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 332 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 333 | github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= 334 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 335 | github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 336 | github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 337 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 338 | github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= 339 | github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= 340 | github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= 341 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 342 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 343 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 344 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 345 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 346 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 347 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 348 | github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= 349 | github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= 350 | github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= 351 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 352 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 353 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 354 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 355 | github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= 356 | github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= 357 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 358 | github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= 359 | github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= 360 | github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= 361 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 362 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 363 | github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= 364 | github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= 365 | github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= 366 | github.com/qiangxue/fasthttp-routing v0.0.0-20160225050629-6ccdc2a18d87 h1:u7uCM+HS2caoEKSPtSFQvvUDXQtqZdu3MYtF+QEw7vA= 367 | github.com/qiangxue/fasthttp-routing v0.0.0-20160225050629-6ccdc2a18d87/go.mod h1:zwr0xP4ZJxwCS/g2d+AUOUwfq/j2NC7a1rK3F0ZbVYM= 368 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= 369 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= 370 | github.com/rcrowley/go-tigertonic v0.0.0-20170420123839-fe6b9f080eb7 h1:IF6au04LnXfITvXy4gwKKcka4zKYp73RXCEGUACqC/Y= 371 | github.com/rcrowley/go-tigertonic v0.0.0-20170420123839-fe6b9f080eb7/go.mod h1:iFmRpXEuybfivhzfxebaHxO63V+ye2AFJMBk12tZPck= 372 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 373 | github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= 374 | github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 375 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 376 | github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= 377 | github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= 378 | github.com/savsgio/atreugo/v11 v11.12.0 h1:xZ39cfYUM2SB7duE68KYs50Rjg4SlvvQKgzIvelI2JU= 379 | github.com/savsgio/atreugo/v11 v11.12.0/go.mod h1:nyk6RRgpAGFesIc07SqSaNT/vGQD8ajgpcwFNbr02Ms= 380 | github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk= 381 | github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= 382 | github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= 383 | github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 h1:v9ezJDHA1XGxViAUSIoO/Id7Fl63u6d0YmsAm+/p2hs= 384 | github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02/go.mod h1:RF16/A3L0xSa0oSERcnhd8Pu3IXSDZSK2gmGIMsttFE= 385 | github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= 386 | github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s= 387 | github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA= 388 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 389 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 390 | github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 391 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 392 | github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= 393 | github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 394 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 395 | github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= 396 | github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= 397 | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= 398 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 399 | github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 400 | github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= 401 | github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 402 | github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 403 | github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= 404 | github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE= 405 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 406 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 407 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 408 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 409 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 410 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 411 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 412 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 413 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 414 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 415 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 416 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 417 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 418 | github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 419 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 420 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 421 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 422 | github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= 423 | github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= 424 | github.com/teambition/gear v1.27.3 h1:iWUOJYdBwxU+SZP5aZ2ZYR5FnRGmdgrMbbSpOCZo0go= 425 | github.com/teambition/gear v1.27.3/go.mod h1:d3Nmr6rRPnH5lYSK33W9IDhsaxp/8n14vRrUZu9dP9c= 426 | github.com/teambition/trie-mux v1.5.2 h1:ALTagFwKZXkn1vfSRlODlmoZg+NMeWAm4dyBPQI6a8w= 427 | github.com/teambition/trie-mux v1.5.2/go.mod h1:0Woh4KOHSN9bkJ66eWmLs8ltrEKw+fnZbFaHFfbMrtc= 428 | github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= 429 | github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= 430 | github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= 431 | github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= 432 | github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= 433 | github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= 434 | github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= 435 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 436 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 437 | github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= 438 | github.com/valyala/fasthttp v1.31.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= 439 | github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0= 440 | github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= 441 | github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= 442 | github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= 443 | github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= 444 | github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= 445 | github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= 446 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 447 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 448 | github.com/vanng822/r2router v0.0.0-20150523112421-1023140a4f30 h1:fCYIzI798sOjtO9fMZaqF0ldAoYEsMLt2EwX7HdXzu4= 449 | github.com/vanng822/r2router v0.0.0-20150523112421-1023140a4f30/go.mod h1:1BVq8p2jVr55Ost2PkZWDrG86PiJ/0lxqcXoAcGxvWU= 450 | github.com/vardius/gorouter/v4 v4.5.1 h1:G4z0s/UFobopcA9zQFGqBBYFxG0PFk/w7x3ZVktXLEw= 451 | github.com/vardius/gorouter/v4 v4.5.1/go.mod h1:HUZmv8K/yhBG1WHDlIRSWo3WPjK1MYyOFDXSyC8wehg= 452 | github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50= 453 | github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= 454 | github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc= 455 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 456 | github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU= 457 | go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= 458 | go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= 459 | go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= 460 | go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= 461 | go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= 462 | go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= 463 | go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= 464 | go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= 465 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 466 | go101.org/tinyrouter v1.0.1 h1:87pqYNRompDgs8B2Eo7uaKHKFUaO0jlbboofJZXbW1A= 467 | go101.org/tinyrouter v1.0.1/go.mod h1:YBdGKABkja09pNOpnSfLf+QrW4O2w75CV1P1ffM93go= 468 | goji.io v2.0.2+incompatible h1:uIssv/elbKRLznFUy3Xj4+2Mz/qKhek/9aZQDUMae7c= 469 | goji.io v2.0.2+incompatible/go.mod h1:sbqFwrtqZACxLBTQcdgVjFh54yGVCvwq8+w49MVMMIk= 470 | golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= 471 | golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc= 472 | golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= 473 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 474 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 475 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 476 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 477 | golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 478 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 479 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 480 | golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 481 | golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= 482 | golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= 483 | golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= 484 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 485 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 486 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 487 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 488 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 489 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 490 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 491 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 492 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 493 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 494 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 495 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 496 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 497 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 498 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 499 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 500 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 501 | golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 502 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 503 | golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 504 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 505 | golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 506 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 507 | golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 508 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 509 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 510 | golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= 511 | golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= 512 | golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= 513 | golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 514 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 515 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 516 | golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 517 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 518 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 519 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 520 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 521 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 522 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 523 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 524 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 525 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 526 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 527 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 528 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 529 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 530 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 531 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 532 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 533 | golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 534 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 535 | golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 536 | golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 537 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 538 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 539 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 540 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 541 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 542 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 543 | golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 544 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 545 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 546 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 547 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 548 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 549 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 550 | golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= 551 | golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 552 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 553 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 554 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 555 | golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= 556 | golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= 557 | golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= 558 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 559 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 560 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 561 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 562 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 563 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 564 | golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 565 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 566 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 567 | golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 568 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 569 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 570 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 571 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 572 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 573 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 574 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 575 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 576 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 577 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 578 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 579 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 580 | google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 581 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 582 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 583 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 584 | google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 585 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 586 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 587 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 588 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 589 | google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 590 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 591 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 592 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 593 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 594 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 595 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 596 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 597 | google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 598 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 599 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 600 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 601 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 602 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 603 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 604 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 605 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 606 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 607 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 608 | google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= 609 | google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 610 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 611 | gopkg.in/baa.v1 v1.2.32 h1:Ogunc5RjgAkrmd9SYlUh5RxnbuPg4VuXLi0U7ta2W38= 612 | gopkg.in/baa.v1 v1.2.32/go.mod h1:aumtvV4jl+vwW6KUQ0i+dGEfr6j4w0VfN8D48OrZ8eE= 613 | gopkg.in/celrenheit/lion.v1 v1.0.0-20161101201550-7c6ce5d22d64 h1:Q07jkzClDIVhxRuKfVYNtYsxl8HdOkq2AopX2lztngY= 614 | gopkg.in/celrenheit/lion.v1 v1.0.0-20161101201550-7c6ce5d22d64/go.mod h1:fxZnKRsIhG7QA87ALGLJUvnXZC+KQ8Xq1tjZb0QwWe0= 615 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 616 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 617 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 618 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 619 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 620 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 621 | gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= 622 | gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= 623 | gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= 624 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 625 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 626 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 627 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 628 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 629 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 630 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 631 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 632 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 633 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 634 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 635 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 636 | gorm.io/driver/mysql v1.5.0 h1:6hSAT5QcyIaty0jfnff0z0CLDjyRgZ8mlMHLqSt7uXM= 637 | gorm.io/driver/mysql v1.5.0/go.mod h1:FFla/fJuCvyTi7rJQd27qlNX2v3L6deTR1GgTjSOLPo= 638 | gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= 639 | gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= 640 | goyave.dev/goyave/v4 v4.4.11 h1:HdJJ82ZWrkB7sBsituVRgQhcDvmAavfVbd6xynaUN8Y= 641 | goyave.dev/goyave/v4 v4.4.11/go.mod h1:kMbB3bf7ZhUD4Cq1Zy6nM4fHBHYO5mPSkTF6WStf4ik= 642 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 643 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 644 | nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= 645 | rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 646 | -------------------------------------------------------------------------------- /libs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | web_frameworks=("default" "atreugo" "beego" "bone" "chi" "denco" "don" "echo" "fasthttp" \ 4 | "fasthttp-routing" "fasthttp/router" "fiber" "gear" "gearbox" "gin" "goframe" "goji" "gorestful" \ 5 | "gorilla" "gorouter" "gorouterfasthttp" "go-ozzo" "goyave" "httprouter" "httptreemux" "httpz" \ 6 | "indigo" "lars" "lion" "muxie" "negroni" "pat" "pulse" "pure" "r2router" "tango" "tiger" \ 7 | "tinyrouter" "violetear" "vulcan" "webgo") 8 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "github.com/Unknwon/macaron": { 4 | "branch": "master" 5 | }, 6 | "github.com/ant0ine/go-json-rest": { 7 | "branch": "master" 8 | }, 9 | "github.com/astaxie/beego": { 10 | "branch": "master" 11 | }, 12 | "github.com/bmizerany/pat": { 13 | "branch": "master" 14 | }, 15 | "github.com/buaazp/fasthttprouter": { 16 | "branch": "master" 17 | }, 18 | "github.com/claygod/Bxog": { 19 | "branch": "master" 20 | }, 21 | "github.com/dimfeld/httptreemux": { 22 | "branch": "master" 23 | }, 24 | "github.com/dinever/golf": { 25 | "branch": "master" 26 | }, 27 | "github.com/emicklei/go-restful": { 28 | "branch": "master" 29 | }, 30 | "github.com/gin-gonic/gin": { 31 | "branch": "master" 32 | }, 33 | "github.com/go-gas/gas": { 34 | "branch": "master" 35 | }, 36 | "github.com/go-martini/martini": { 37 | "branch": "master" 38 | }, 39 | "github.com/go-ozzo/ozzo-routing": { 40 | "branch": "master" 41 | }, 42 | "github.com/go-playground/lars": { 43 | "branch": "master" 44 | }, 45 | "github.com/go-zoo/bone": { 46 | "branch": "master" 47 | }, 48 | "github.com/gocraft/web": { 49 | "branch": "master" 50 | }, 51 | "github.com/gorilla/mux": { 52 | "branch": "master" 53 | }, 54 | "github.com/ivpusic/neo": { 55 | "branch": "master" 56 | }, 57 | "github.com/julienschmidt/httprouter": { 58 | "branch": "master" 59 | }, 60 | "github.com/labstack/echo": { 61 | "branch": "master" 62 | }, 63 | "github.com/lunny/log": { 64 | "branch": "master" 65 | }, 66 | "github.com/lunny/tango": { 67 | "branch": "master" 68 | }, 69 | "github.com/mailgun/route": { 70 | "branch": "master" 71 | }, 72 | "github.com/mikespook/possum": { 73 | "branch": "master" 74 | }, 75 | "github.com/mustafaakin/gongular": { 76 | "branch": "master" 77 | }, 78 | "github.com/naoina/denco": { 79 | "branch": "master" 80 | }, 81 | "github.com/pilu/traffic": { 82 | "branch": "master" 83 | }, 84 | "github.com/plimble/ace": { 85 | "branch": "master" 86 | }, 87 | "github.com/pressly/chi": { 88 | "branch": "master" 89 | }, 90 | "github.com/qiangxue/fasthttp-routing": { 91 | "branch": "master" 92 | }, 93 | "github.com/rcrowley/go-tigertonic": { 94 | "branch": "master" 95 | }, 96 | "github.com/valyala/fasthttp": { 97 | "branch": "master" 98 | }, 99 | "github.com/vanng822/r2router": { 100 | "branch": "master" 101 | }, 102 | "goji.io": { 103 | "branch": "master" 104 | }, 105 | "golang.org/x/net": { 106 | "branch": "master" 107 | }, 108 | "gopkg.in/baa.v1": { 109 | "branch": "master" 110 | }, 111 | "gopkg.in/celrenheit/lion.v1": { 112 | "branch": "v1" 113 | }, 114 | "github.com/gogearbox/gearbox": { 115 | "branch": "master" 116 | }, 117 | "github.com/savsgio/atreugo": { 118 | "branch": "master" 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /pipeline.lua: -------------------------------------------------------------------------------- 1 | init = function(args) 2 | request_uri = args[1] 3 | depth = tonumber(args[2]) or 1 4 | 5 | local r = {} 6 | for i=1,depth do 7 | r[i] = wrk.format(nil, request_uri) 8 | end 9 | req = table.concat(r) 10 | end 11 | 12 | request = function() 13 | return req 14 | end -------------------------------------------------------------------------------- /pow.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/sha256" 5 | "math/big" 6 | "runtime" 7 | "strconv" 8 | ) 9 | 10 | func pow(targetBits int) { 11 | target := big.NewInt(1) 12 | target.Lsh(target, uint(256-targetBits)) 13 | 14 | var hashInt big.Int 15 | var hash [32]byte 16 | nonce := 0 17 | 18 | for { 19 | data := "hello world " + strconv.Itoa(nonce) 20 | hash = sha256.Sum256([]byte(data)) 21 | hashInt.SetBytes(hash[:]) 22 | 23 | if hashInt.Cmp(target) == -1 { 24 | break 25 | } else { 26 | nonce++ 27 | } 28 | 29 | if nonce%100 == 0 { 30 | runtime.Gosched() 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "log" 9 | "net/http" 10 | "os" 11 | "runtime" 12 | "strconv" 13 | "time" 14 | 15 | "github.com/aeilang/httpz" 16 | "github.com/indigo-web/indigo" 17 | "github.com/indigo-web/indigo/router/inbuilt" 18 | "github.com/vanng822/r2router" 19 | 20 | "github.com/abemedia/go-don" 21 | _ "github.com/abemedia/go-don/encoding/text" 22 | "github.com/ant0ine/go-json-rest/rest" 23 | "github.com/astaxie/beego" 24 | beegoContext "github.com/astaxie/beego/context" 25 | "github.com/bmizerany/pat" 26 | "github.com/bnkamalesh/webgo/v7" 27 | bxog "github.com/claygod/Bxog" 28 | "github.com/dimfeld/httptreemux" 29 | "github.com/dinever/golf" 30 | "github.com/emicklei/go-restful" 31 | fasthttprouter "github.com/fasthttp/router" 32 | "github.com/gin-gonic/gin" 33 | "github.com/go-chi/chi/v5" 34 | ozzo "github.com/go-ozzo/ozzo-routing" 35 | "github.com/go-playground/lars" 36 | "github.com/go-playground/pure" 37 | "github.com/go-zoo/bone" 38 | "github.com/gocraft/web" 39 | "github.com/gofiber/fiber/v2" 40 | "github.com/gogearbox/gearbox" 41 | gf "github.com/gogf/gf/v2/frame/g" 42 | "github.com/gopulse/pulse" 43 | "github.com/gorilla/mux" 44 | ihttp "github.com/indigo-web/indigo/http" 45 | "github.com/julienschmidt/httprouter" 46 | "github.com/kataras/muxie" 47 | "github.com/labstack/echo/v4" 48 | llog "github.com/lunny/log" 49 | "github.com/lunny/tango" 50 | vulcan "github.com/mailgun/route" 51 | "github.com/naoina/denco" 52 | "github.com/nbari/violetear" 53 | routing "github.com/qiangxue/fasthttp-routing" 54 | "github.com/rcrowley/go-tigertonic" 55 | "github.com/savsgio/atreugo/v11" 56 | "github.com/teambition/gear" 57 | "github.com/urfave/negroni" 58 | "github.com/valyala/fasthttp" 59 | "github.com/vardius/gorouter/v4" 60 | tiny "go101.org/tinyrouter" 61 | goji "goji.io" 62 | gojipat "goji.io/pat" 63 | gcontext "golang.org/x/net/context" 64 | "gopkg.in/baa.v1" 65 | "gopkg.in/celrenheit/lion.v1" 66 | "goyave.dev/goyave/v4" 67 | "goyave.dev/goyave/v4/config" 68 | ) 69 | 70 | var ( 71 | port = 8080 72 | sleepTime = 0 73 | cpuBound bool 74 | target = 15 75 | sleepTimeDuration time.Duration 76 | message = []byte("hello world") 77 | messageStr = "hello world" 78 | samplingPoint = 20 // seconds 79 | ) 80 | 81 | // server [default] [10] [8080] 82 | func main() { 83 | args := os.Args 84 | argsLen := len(args) 85 | webFramework := "default" 86 | if argsLen > 1 { 87 | webFramework = args[1] 88 | } 89 | if argsLen > 2 { 90 | sleepTime, _ = strconv.Atoi(args[2]) 91 | if sleepTime == -1 { 92 | cpuBound = true 93 | sleepTime = 0 94 | } 95 | } 96 | if argsLen > 3 { 97 | port, _ = strconv.Atoi(args[3]) 98 | } 99 | if argsLen > 4 { 100 | samplingPoint, _ = strconv.Atoi(args[4]) 101 | } 102 | sleepTimeDuration = time.Duration(sleepTime) * time.Millisecond 103 | samplingPointDuration := time.Duration(samplingPoint) * time.Second 104 | 105 | go func() { 106 | time.Sleep(samplingPointDuration) 107 | var mem runtime.MemStats 108 | runtime.ReadMemStats(&mem) 109 | var u uint64 = 1024 * 1024 110 | fmt.Printf("TotalAlloc: %d\n", mem.TotalAlloc/u) 111 | fmt.Printf("Alloc: %d\n", mem.Alloc/u) 112 | fmt.Printf("HeapAlloc: %d\n", mem.HeapAlloc/u) 113 | fmt.Printf("HeapSys: %d\n", mem.HeapSys/u) 114 | }() 115 | 116 | switch webFramework { 117 | case "default": 118 | startDefaultMux() 119 | case "atreugo": 120 | startAtreugo() 121 | case "baa": 122 | startBaa() 123 | case "beego": 124 | startBeego() 125 | case "bone": 126 | startBone() 127 | case "bxog": 128 | startBxog() 129 | case "chi": 130 | startChi() 131 | case "denco": 132 | startDenco() 133 | case "don": 134 | startDon() 135 | case "echo": 136 | startEcho() 137 | case "fasthttp": 138 | startFasthttp() 139 | case "fasthttp/router": 140 | startFastHTTPRouter() 141 | case "fasthttp-routing": 142 | startFastHTTPRouting() 143 | case "fiber": 144 | startFiber() 145 | case "gear": 146 | startGear() 147 | case "gearbox": 148 | startGearbox() 149 | case "gin": 150 | startGin() 151 | case "gocraftWeb": 152 | startGocraftWeb() 153 | case "goframe": 154 | startGoframe() 155 | case "goji": 156 | startGoji() 157 | case "golf": 158 | startGolf() 159 | case "gorestful": 160 | startGoRestful() 161 | case "gorilla": 162 | startGorilla() 163 | case "gorouter": 164 | startGorouter() 165 | case "gorouterfasthttp": 166 | startGorouterFastHTTP() 167 | case "go-ozzo": 168 | startGoozzo() 169 | case "httprouter": 170 | startHTTPRouter() 171 | case "httptreemux": 172 | starthttpTreeMux() 173 | case "httpz": 174 | startHTTPZ() 175 | case "indigo": 176 | startIndigo() 177 | case "lars": 178 | startLars() 179 | case "lion": 180 | startLion() 181 | case "muxie": 182 | startMuxie() 183 | case "negroni": 184 | startNegroni() 185 | case "pat": 186 | startPat() 187 | case "pulse": 188 | startPulse() 189 | case "pure": 190 | startPure() 191 | case "r2router": 192 | startR2router() 193 | case "tango": 194 | startTango() 195 | case "tiger": 196 | startTigerTonic() 197 | case "tinyrouter": 198 | startTinyRouter() 199 | case "violetear": 200 | startVioletear() 201 | case "vulcan": 202 | startVulcan() 203 | case "webgo": 204 | startWebgo() 205 | case "goyave": 206 | startGoyave() 207 | default: 208 | fmt.Println("--------------------------------------------------------------------") 209 | fmt.Println("------------- Unknown framework given!!! Check libs.sh -------------") 210 | fmt.Println("------------- Unknown framework given!!! Check libs.sh -------------") 211 | fmt.Println("------------- Unknown framework given!!! Check libs.sh -------------") 212 | fmt.Println("--------------------------------------------------------------------") 213 | } 214 | } 215 | 216 | // default mux 217 | func helloHandler(w http.ResponseWriter, r *http.Request) { 218 | if cpuBound { 219 | pow(target) 220 | } else { 221 | if sleepTime > 0 { 222 | time.Sleep(sleepTimeDuration) 223 | } else { 224 | runtime.Gosched() 225 | } 226 | } 227 | w.Write(message) 228 | } 229 | 230 | func startDefaultMux() { 231 | http.HandleFunc("/hello", helloHandler) 232 | http.ListenAndServe(":"+strconv.Itoa(port), nil) 233 | } 234 | 235 | // atreugo 236 | func atreugoHandler(ctx *atreugo.RequestCtx) error { 237 | if cpuBound { 238 | pow(target) 239 | } else { 240 | if sleepTime > 0 { 241 | time.Sleep(sleepTimeDuration) 242 | } else { 243 | runtime.Gosched() 244 | } 245 | } 246 | 247 | return ctx.TextResponse(messageStr) 248 | } 249 | 250 | func startAtreugo() { 251 | server := atreugo.New(atreugo.Config{ 252 | Addr: ":" + strconv.Itoa(port), 253 | Prefork: true, 254 | NoDefaultDate: true, 255 | NoDefaultContentType: true, 256 | DisableHeaderNamesNormalizing: true, 257 | }) 258 | server.GET("/hello", atreugoHandler) 259 | log.Fatal(server.ListenAndServe()) 260 | } 261 | 262 | // baa 263 | func baaHandler(ctx *baa.Context) { 264 | if cpuBound { 265 | pow(target) 266 | } else { 267 | if sleepTime > 0 { 268 | time.Sleep(sleepTimeDuration) 269 | } else { 270 | runtime.Gosched() 271 | } 272 | } 273 | ctx.Text(200, message) 274 | } 275 | 276 | func startBaa() { 277 | mux := baa.New() 278 | mux.Get("/hello", baaHandler) 279 | mux.Run(":" + strconv.Itoa(port)) 280 | } 281 | 282 | // beego 283 | func beegoHandler(ctx *beegoContext.Context) { 284 | if cpuBound { 285 | pow(target) 286 | } else { 287 | if sleepTime > 0 { 288 | time.Sleep(sleepTimeDuration) 289 | } else { 290 | runtime.Gosched() 291 | } 292 | } 293 | ctx.WriteString(messageStr) 294 | } 295 | 296 | func startBeego() { 297 | beego.BConfig.RunMode = beego.PROD 298 | beego.BeeLogger.Close() 299 | mux := beego.NewControllerRegister() 300 | mux.Get("/hello", beegoHandler) 301 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 302 | } 303 | 304 | // bone 305 | func startBone() { 306 | mux := bone.New() 307 | mux.HandleFunc("/hello", helloHandler) 308 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 309 | } 310 | 311 | // bxog 312 | func bxogHandler(w http.ResponseWriter, req *http.Request, r *bxog.Router) { 313 | if cpuBound { 314 | pow(target) 315 | } else { 316 | if sleepTime > 0 { 317 | time.Sleep(sleepTimeDuration) 318 | } else { 319 | runtime.Gosched() 320 | } 321 | } 322 | w.Write(message) 323 | } 324 | 325 | func startBxog() { 326 | mux := bxog.New() 327 | mux.Add("/hello", bxogHandler) 328 | mux.Start(":" + strconv.Itoa(port)) 329 | } 330 | 331 | // chi 332 | func startChi() { 333 | // Create a router instance. 334 | r := chi.NewRouter() 335 | 336 | // Register route handler. 337 | r.Get("/hello", helloHandler) 338 | 339 | // Start Chi. 340 | http.ListenAndServe(":"+strconv.Itoa(port), r) 341 | } 342 | 343 | // denco 344 | func dencoHandler(w http.ResponseWriter, r *http.Request, params denco.Params) { 345 | if cpuBound { 346 | pow(target) 347 | } else { 348 | if sleepTime > 0 { 349 | time.Sleep(sleepTimeDuration) 350 | } else { 351 | runtime.Gosched() 352 | } 353 | } 354 | w.Write(message) 355 | } 356 | 357 | func startDenco() { 358 | mux := denco.NewMux() 359 | handler, _ := mux.Build([]denco.Handler{mux.GET("/hello", dencoHandler)}) 360 | http.ListenAndServe(":"+strconv.Itoa(port), handler) 361 | } 362 | 363 | // don 364 | func donHandler(context.Context, any) ([]byte, error) { 365 | if cpuBound { 366 | pow(target) 367 | } else { 368 | if sleepTime > 0 { 369 | time.Sleep(sleepTimeDuration) 370 | } else { 371 | runtime.Gosched() 372 | } 373 | } 374 | return message, nil 375 | } 376 | 377 | func startDon() { 378 | api := don.New(nil) 379 | api.Get("/hello", don.H(donHandler)) 380 | api.ListenAndServe(":" + strconv.Itoa(port)) 381 | } 382 | 383 | // echo 384 | func echoHandler(c echo.Context) error { 385 | if cpuBound { 386 | pow(target) 387 | } else { 388 | if sleepTime > 0 { 389 | time.Sleep(sleepTimeDuration) 390 | } else { 391 | runtime.Gosched() 392 | } 393 | } 394 | c.Response().Write(message) 395 | return nil 396 | } 397 | 398 | func startEcho() { 399 | e := echo.New() 400 | e.GET("/hello", echoHandler) 401 | 402 | e.Start(":" + strconv.Itoa(port)) 403 | } 404 | 405 | // fasthttp 406 | func fastHTTPHandler(ctx *fasthttp.RequestCtx) { 407 | if cpuBound { 408 | pow(target) 409 | } else { 410 | if sleepTime > 0 { 411 | time.Sleep(sleepTimeDuration) 412 | } else { 413 | runtime.Gosched() 414 | } 415 | } 416 | 417 | ctx.Write(message) 418 | } 419 | 420 | func startFasthttp() { 421 | s := &fasthttp.Server{ 422 | Handler: fastHTTPHandler, 423 | GetOnly: true, 424 | NoDefaultDate: true, 425 | NoDefaultContentType: true, 426 | DisableHeaderNamesNormalizing: true, 427 | } 428 | 429 | log.Fatal(s.ListenAndServe(":" + strconv.Itoa(port))) 430 | } 431 | 432 | // fasthttp Router 433 | func startFastHTTPRouter() { 434 | mux := fasthttprouter.New() 435 | mux.GET("/hello", fastHTTPHandler) 436 | log.Fatal(fasthttp.ListenAndServe(":"+strconv.Itoa(port), mux.Handler)) 437 | } 438 | 439 | // fasthttprouting 440 | func fastHTTPRoutingHandler(c *routing.Context) error { 441 | if cpuBound { 442 | pow(target) 443 | } else { 444 | if sleepTime > 0 { 445 | time.Sleep(sleepTimeDuration) 446 | } else { 447 | runtime.Gosched() 448 | } 449 | } 450 | c.Write(message) 451 | return nil 452 | } 453 | 454 | func startFastHTTPRouting() { 455 | mux := routing.New() 456 | mux.Get("/hello", fastHTTPRoutingHandler) 457 | fasthttp.ListenAndServe(":"+strconv.Itoa(port), mux.HandleRequest) 458 | } 459 | 460 | // fiber 461 | func fiberHandler(c *fiber.Ctx) error { 462 | if cpuBound { 463 | pow(target) 464 | } else { 465 | if sleepTime > 0 { 466 | time.Sleep(sleepTimeDuration) 467 | } else { 468 | runtime.Gosched() 469 | } 470 | } 471 | return c.SendString(messageStr) 472 | } 473 | 474 | func startFiber() { 475 | app := fiber.New(fiber.Config{ 476 | Prefork: true, 477 | CaseSensitive: true, 478 | StrictRouting: true, 479 | DisableDefaultDate: true, 480 | DisableHeaderNormalizing: true, 481 | DisableDefaultContentType: true, 482 | }) 483 | app.Get("/hello", fiberHandler) 484 | log.Fatal(app.Listen(":" + strconv.Itoa(port))) 485 | } 486 | 487 | // gear 488 | func startGear() { 489 | app := gear.New() 490 | router := gear.NewRouter() 491 | 492 | router.Get("/hello", func(c *gear.Context) error { 493 | if cpuBound { 494 | pow(target) 495 | } else { 496 | if sleepTime > 0 { 497 | time.Sleep(sleepTimeDuration) 498 | } else { 499 | runtime.Gosched() 500 | } 501 | } 502 | return c.HTML(200, messageStr) 503 | }) 504 | app.UseHandler(router) 505 | app.Listen(":" + strconv.Itoa(port)) 506 | } 507 | 508 | // gearbox 509 | func startGearbox() { 510 | gb := gearbox.New() 511 | gb.Get("/hello", func(ctx gearbox.Context) { 512 | if cpuBound { 513 | pow(target) 514 | } else { 515 | if sleepTime > 0 { 516 | time.Sleep(sleepTimeDuration) 517 | } else { 518 | runtime.Gosched() 519 | } 520 | } 521 | ctx.SendString(messageStr) 522 | }) 523 | gb.Start(":" + strconv.Itoa(port)) 524 | } 525 | 526 | // gin 527 | func ginHandler(c *gin.Context) { 528 | if cpuBound { 529 | pow(target) 530 | } else { 531 | if sleepTime > 0 { 532 | time.Sleep(sleepTimeDuration) 533 | } else { 534 | runtime.Gosched() 535 | } 536 | } 537 | c.Writer.Write(message) 538 | } 539 | 540 | func startGin() { 541 | gin.SetMode(gin.ReleaseMode) 542 | mux := gin.New() 543 | mux.GET("/hello", ginHandler) 544 | mux.Run(":" + strconv.Itoa(port)) 545 | } 546 | 547 | // gocraftWeb 548 | type gocraftWebContext struct{} 549 | 550 | func gocraftWebHandler(w web.ResponseWriter, r *web.Request) { 551 | if cpuBound { 552 | pow(target) 553 | } else { 554 | if sleepTime > 0 { 555 | time.Sleep(sleepTimeDuration) 556 | } else { 557 | runtime.Gosched() 558 | } 559 | } 560 | w.Write(message) 561 | } 562 | 563 | func startGocraftWeb() { 564 | mux := web.New(gocraftWebContext{}) 565 | mux.Get("/hello", gocraftWebHandler) 566 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 567 | } 568 | 569 | // goframe 570 | func gfHandler(w http.ResponseWriter, r *http.Request) { 571 | if cpuBound { 572 | pow(target) 573 | } else { 574 | if sleepTime > 0 { 575 | time.Sleep(sleepTimeDuration) 576 | } else { 577 | runtime.Gosched() 578 | } 579 | } 580 | w.Header().Set("Content-Type", "text/html; charset=utf-8") 581 | _, _ = w.Write(message) 582 | } 583 | 584 | func startGoframe() { 585 | s := gf.Server() 586 | s.SetHandler(func(w http.ResponseWriter, r *http.Request) { 587 | switch r.URL.Path { 588 | case "/hello": 589 | gfHandler(w, r) 590 | 591 | default: 592 | w.WriteHeader(http.StatusNotFound) 593 | _, _ = w.Write([]byte(http.StatusText(http.StatusNotFound))) 594 | } 595 | }) 596 | s.SetPort(port) 597 | s.Run() 598 | } 599 | 600 | // goji 601 | func gojiHandler(w http.ResponseWriter, r *http.Request) { 602 | if cpuBound { 603 | pow(target) 604 | } else { 605 | if sleepTime > 0 { 606 | time.Sleep(sleepTimeDuration) 607 | } else { 608 | runtime.Gosched() 609 | } 610 | } 611 | w.Write(message) 612 | } 613 | 614 | func startGoji() { 615 | mux := goji.NewMux() 616 | mux.HandleFunc(gojipat.Get("/hello"), gojiHandler) 617 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 618 | } 619 | 620 | // goJsonRest 621 | func goJSONRestHandler(w rest.ResponseWriter, req *rest.Request) { 622 | if cpuBound { 623 | pow(target) 624 | } else { 625 | if sleepTime > 0 { 626 | time.Sleep(sleepTimeDuration) 627 | } else { 628 | runtime.Gosched() 629 | } 630 | } 631 | iow := w.(io.Writer) 632 | iow.Write(message) 633 | } 634 | 635 | func golfHandler(ctx *golf.Context) { 636 | if cpuBound { 637 | pow(target) 638 | } else { 639 | if sleepTime > 0 { 640 | time.Sleep(sleepTimeDuration) 641 | } else { 642 | runtime.Gosched() 643 | } 644 | } 645 | ctx.Send(messageStr) 646 | } 647 | 648 | func startGolf() { 649 | app := golf.New() 650 | app.Get("/hello", golfHandler) 651 | app.Run(":" + strconv.Itoa(port)) 652 | } 653 | 654 | // goRestful 655 | func goRestfulHandler(r *restful.Request, w *restful.Response) { 656 | if cpuBound { 657 | pow(target) 658 | } else { 659 | if sleepTime > 0 { 660 | time.Sleep(sleepTimeDuration) 661 | } else { 662 | runtime.Gosched() 663 | } 664 | } 665 | w.Write(message) 666 | } 667 | 668 | func startGoRestful() { 669 | wsContainer := restful.NewContainer() 670 | ws := new(restful.WebService) 671 | ws.Route(ws.GET("/hello").To(goRestfulHandler)) 672 | wsContainer.Add(ws) 673 | http.ListenAndServe(":"+strconv.Itoa(port), wsContainer) 674 | } 675 | 676 | // gorilla 677 | func startGorilla() { 678 | mux := mux.NewRouter() 679 | mux.HandleFunc("/hello", helloHandler).Methods("GET") 680 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 681 | } 682 | 683 | // gorouter 684 | func startGorouter() { 685 | router := gorouter.New() 686 | router.GET("/hello", http.HandlerFunc(helloHandler)) 687 | http.ListenAndServe(":"+strconv.Itoa(port), router) 688 | } 689 | 690 | func startGorouterFastHTTP() { 691 | router := gorouter.NewFastHTTPRouter() 692 | router.GET("/hello", fastHTTPHandler) 693 | fasthttp.ListenAndServe(":"+strconv.Itoa(port), router.HandleFastHTTP) 694 | } 695 | 696 | // go-ozzo 697 | func ozzoHandler(c *ozzo.Context) error { 698 | if cpuBound { 699 | pow(target) 700 | } else { 701 | if sleepTime > 0 { 702 | time.Sleep(sleepTimeDuration) 703 | } else { 704 | runtime.Gosched() 705 | } 706 | } 707 | c.Write(message) 708 | 709 | return nil 710 | } 711 | 712 | func startGoozzo() { 713 | r := ozzo.New() 714 | r.Get("/hello", ozzoHandler) 715 | http.ListenAndServe(":"+strconv.Itoa(port), r) 716 | } 717 | 718 | // httprouter 719 | func httpRouterHandler(w http.ResponseWriter, _ *http.Request, ps httprouter.Params) { 720 | if cpuBound { 721 | pow(target) 722 | } else { 723 | if sleepTime > 0 { 724 | time.Sleep(sleepTimeDuration) 725 | } else { 726 | runtime.Gosched() 727 | } 728 | } 729 | w.Write(message) 730 | } 731 | 732 | func startHTTPRouter() { 733 | mux := httprouter.New() 734 | mux.GET("/hello", httpRouterHandler) 735 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 736 | } 737 | 738 | // httpTreeMux 739 | func httpTreeMuxHandler(w http.ResponseWriter, _ *http.Request, vars map[string]string) { 740 | if cpuBound { 741 | pow(target) 742 | } else { 743 | if sleepTime > 0 { 744 | time.Sleep(sleepTimeDuration) 745 | } else { 746 | runtime.Gosched() 747 | } 748 | } 749 | w.Write(message) 750 | } 751 | 752 | func starthttpTreeMux() { 753 | mux := httptreemux.New() 754 | mux.GET("/hello", httpTreeMuxHandler) 755 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 756 | } 757 | 758 | // httpz 759 | func httpzHandler(w http.ResponseWriter, _ *http.Request) error { 760 | if cpuBound { 761 | pow(target) 762 | } else { 763 | if sleepTime > 0 { 764 | time.Sleep(sleepTimeDuration) 765 | } else { 766 | runtime.Gosched() 767 | } 768 | } 769 | 770 | w.Write(message) 771 | return nil 772 | } 773 | 774 | func startHTTPZ() { 775 | mux := httpz.NewServeMux() 776 | mux.Get("/hello", httpzHandler) 777 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 778 | } 779 | 780 | // indigo 781 | func indigoHandler(r *ihttp.Request) *ihttp.Response { 782 | if cpuBound { 783 | pow(target) 784 | } else { 785 | if sleepTime > 0 { 786 | time.Sleep(sleepTimeDuration) 787 | } else { 788 | runtime.Gosched() 789 | } 790 | } 791 | 792 | return ihttp.Bytes(r, message) 793 | } 794 | 795 | func startIndigo() { 796 | r := inbuilt.New() 797 | r.Get("/hello", indigoHandler) 798 | 799 | _ = indigo.New(":" + strconv.Itoa(port)).Serve(r) 800 | } 801 | 802 | // lars 803 | func larsHandler(c lars.Context) { 804 | if cpuBound { 805 | pow(target) 806 | } else { 807 | if sleepTime > 0 { 808 | time.Sleep(sleepTimeDuration) 809 | } else { 810 | runtime.Gosched() 811 | } 812 | } 813 | c.Response().Write(message) 814 | } 815 | 816 | func startLars() { 817 | mux := lars.New() 818 | mux.Get("/hello", larsHandler) 819 | http.ListenAndServe(":"+strconv.Itoa(port), mux.Serve()) 820 | } 821 | 822 | // lion 823 | func lionHandler(c gcontext.Context, w http.ResponseWriter, r *http.Request) { 824 | if cpuBound { 825 | pow(target) 826 | } else { 827 | if sleepTime > 0 { 828 | time.Sleep(sleepTimeDuration) 829 | } else { 830 | runtime.Gosched() 831 | } 832 | } 833 | w.Write(message) 834 | } 835 | 836 | func startLion() { 837 | mux := lion.New() 838 | mux.GetFunc("/hello", lionHandler) 839 | mux.Run(":" + strconv.Itoa(port)) 840 | } 841 | 842 | func startMuxie() { 843 | mux := muxie.NewMux() 844 | mux.HandleFunc("/hello", helloHandler) 845 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 846 | } 847 | 848 | // negroni 849 | func startNegroni() { 850 | mux := http.NewServeMux() 851 | mux.HandleFunc("/hello", helloHandler) 852 | 853 | n := negroni.New() 854 | n.UseHandler(mux) 855 | 856 | http.ListenAndServe(":"+strconv.Itoa(port), n) 857 | } 858 | 859 | // pat 860 | func startPat() { 861 | mux := pat.New() 862 | mux.Get("/hello", http.HandlerFunc(helloHandler)) 863 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 864 | } 865 | 866 | // pulse 867 | func startPulse() { 868 | app := pulse.New() 869 | router := pulse.NewRouter() 870 | 871 | app.Router = router 872 | 873 | router.Get("/hello", func(c *pulse.Context) error { 874 | c.String(string(message)) 875 | return nil 876 | }) 877 | 878 | app.Run(":" + strconv.Itoa(port)) 879 | } 880 | 881 | // pure 882 | func startPure() { 883 | p := pure.New() 884 | p.Get("/hello", helloHandler) 885 | http.ListenAndServe(":"+strconv.Itoa(port), p.Serve()) 886 | } 887 | 888 | // R2router 889 | func r2routerHandler(w http.ResponseWriter, req *http.Request, params r2router.Params) { 890 | if cpuBound { 891 | pow(target) 892 | } else { 893 | if sleepTime > 0 { 894 | time.Sleep(sleepTimeDuration) 895 | } else { 896 | runtime.Gosched() 897 | } 898 | } 899 | w.Write(message) 900 | } 901 | 902 | func startR2router() { 903 | mux := r2router.NewRouter() 904 | mux.Get("/hello", r2routerHandler) 905 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 906 | } 907 | 908 | // Tango 909 | func tangoHandler(ctx *tango.Context) { 910 | if cpuBound { 911 | pow(target) 912 | } else { 913 | if sleepTime > 0 { 914 | time.Sleep(sleepTimeDuration) 915 | } else { 916 | runtime.Gosched() 917 | } 918 | } 919 | ctx.Write(message) 920 | } 921 | 922 | func startTango() { 923 | llog.SetOutput(new(mockResponseWriter)) 924 | llog.SetOutputLevel(llog.Lnone) 925 | 926 | mux := tango.NewWithLog(llog.Std) 927 | mux.Get("/hello", tangoHandler) 928 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 929 | } 930 | 931 | // Tiger Tonic 932 | func startTigerTonic() { 933 | mux := tigertonic.NewTrieServeMux() 934 | mux.Handle("GET", "/hello", http.HandlerFunc(helloHandler)) 935 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 936 | } 937 | 938 | // TinyRouter 939 | func startTinyRouter() { 940 | routes := []tiny.Route{ 941 | { 942 | Method: "GET", 943 | Pattern: "/hello", 944 | HandleFunc: helloHandler, 945 | }, 946 | } 947 | router := tiny.New(tiny.Config{Routes: routes}) 948 | http.ListenAndServe(":"+strconv.Itoa(port), router) 949 | } 950 | 951 | // violetear 952 | func startVioletear() { 953 | mux := violetear.New() 954 | mux.HandleFunc("/hello", helloHandler) 955 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 956 | } 957 | 958 | // vulcan 959 | func startVulcan() { 960 | mux := vulcan.NewMux() 961 | expr := fmt.Sprintf(`Method("%s") && Path("%s")`, "GET", "/hello") 962 | mux.HandleFunc(expr, helloHandler) 963 | 964 | http.ListenAndServe(":"+strconv.Itoa(port), mux) 965 | } 966 | 967 | // webgo 968 | func getWebgoRoutes() []*webgo.Route { 969 | return []*webgo.Route{ 970 | { 971 | Name: "hello", 972 | Method: http.MethodGet, 973 | Pattern: "/hello", 974 | Handlers: []http.HandlerFunc{helloHandler}, 975 | }, 976 | } 977 | } 978 | 979 | func startWebgo() { 980 | cfg := webgo.Config{ 981 | Host: "", 982 | Port: strconv.Itoa(port), 983 | ReadTimeout: 120 * time.Second, 984 | WriteTimeout: 120 * time.Second, 985 | } 986 | router := webgo.NewRouter(&cfg, getWebgoRoutes()...) 987 | router.Start() 988 | } 989 | 990 | // Goyave 991 | func goyaveHandler(r *goyave.Response, req *goyave.Request) { 992 | if cpuBound { 993 | pow(target) 994 | } else { 995 | if sleepTime > 0 { 996 | time.Sleep(sleepTimeDuration) 997 | } else { 998 | runtime.Gosched() 999 | } 1000 | } 1001 | r.String(http.StatusOK, "hello") 1002 | } 1003 | 1004 | func getGoyaveRoutes(router *goyave.Router) { 1005 | router.Get("/hello", goyaveHandler) 1006 | } 1007 | 1008 | func startGoyave() { 1009 | cfg := []byte(fmt.Sprintf(` 1010 | { 1011 | "server": { 1012 | "host": "0.0.0.0", 1013 | "port": %d, 1014 | "timeout": 120 1015 | } 1016 | } 1017 | `, port)) 1018 | 1019 | tmpFile, err := ioutil.TempFile("", "goyavecfg.json") 1020 | if err != nil { 1021 | log.Fatal(err) 1022 | } 1023 | defer os.Remove(tmpFile.Name()) 1024 | 1025 | if _, err := tmpFile.Write(cfg); err != nil { 1026 | log.Fatal(err) 1027 | } 1028 | if err := tmpFile.Close(); err != nil { 1029 | log.Fatal(err) 1030 | } 1031 | 1032 | if err := config.LoadFrom(tmpFile.Name()); err != nil { 1033 | os.Exit(goyave.ExitInvalidConfig) 1034 | } 1035 | 1036 | if err := goyave.Start(getGoyaveRoutes); err != nil { 1037 | os.Exit(err.(*goyave.Error).ExitCode) 1038 | } 1039 | } 1040 | 1041 | // mock 1042 | type mockResponseWriter struct{} 1043 | 1044 | func (m *mockResponseWriter) Header() (h http.Header) { 1045 | return http.Header{} 1046 | } 1047 | 1048 | func (m *mockResponseWriter) Write(p []byte) (n int, err error) { 1049 | return len(p), nil 1050 | } 1051 | 1052 | func (m *mockResponseWriter) WriteString(s string) (n int, err error) { 1053 | return len(s), nil 1054 | } 1055 | 1056 | func (m *mockResponseWriter) WriteHeader(int) {} 1057 | -------------------------------------------------------------------------------- /test-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Running test.sh" > test.log 4 | ./test.sh 5 | ./testresults/plot.sh 6 | echo "Finished test.sh" >> test.log 7 | 8 | echo "Running test-latency.sh" >> test.log 9 | ./test-latency.sh 10 | ./testresults/plot.sh 11 | echo "Finished test-latency.sh" >> test.log 12 | 13 | echo "Running test-pipelining.sh" >> test.log 14 | ./test-pipelining.sh 15 | ./testresults/plot.sh 16 | echo "Finished test-pipelining.sh" >> test.log 17 | -------------------------------------------------------------------------------- /test-latency-nonkeepalive.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | server_bin_name="gowebbenchmark" 4 | 5 | . ./libs.sh 6 | 7 | length=${#web_frameworks[@]} 8 | 9 | test_result=() 10 | test_latency_result=() 11 | test_alloc_result=() 12 | 13 | cpu_cores=`cat /proc/cpuinfo|grep processor|wc -l` 14 | if [ $cpu_cores -eq 0 ] 15 | then 16 | cpu_cores=1 17 | fi 18 | 19 | test_web_framework() 20 | { 21 | echo "testing web framework: $2" 22 | ./$server_bin_name $2 $3 > alloc.log 2>&1 & 23 | sleep 2 24 | wrk -t$cpu_cores -c$4 -d30s -H 'Connection: Close' http://127.0.0.1:8080/hello > tmp.log 25 | throughput=$(< "tmp.log" grep Requests/sec|awk '{print $2}') 26 | latency=$(< "tmp.log" grep Latency | awk '{print $2}') 27 | latency=${latency%ms} 28 | alloc=$(< "alloc.log" grep HeapAlloc | awk '{print $2}') 29 | echo "throughput: $throughput requests/second, latency: $latency ms, alloc: $alloc" 30 | test_result[$1]=$throughput 31 | test_latency_result[$1]=$latency 32 | test_alloc_result[$1]=$alloc 33 | 34 | pkill -9 $server_bin_name 35 | sleep 2 36 | echo "finished testing $2" 37 | echo 38 | } 39 | 40 | test_all() 41 | { 42 | echo "###################################" 43 | echo " " 44 | echo " ProcessingTime $1ms " 45 | echo " Concurrency $2 " 46 | echo " " 47 | echo "###################################" 48 | for ((i=0; i processtime.csv 58 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > processtime_latency.csv 59 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > processtime_alloc.csv 60 | test_all 0 5000 61 | echo "0 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 62 | echo "0 ms,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> processtime_latency.csv 63 | echo "0 ms,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> processtime_alloc.csv 64 | test_all 10 5000 65 | echo "10 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 66 | echo "10 ms,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> processtime_latency.csv 67 | echo "10 ms,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> processtime_alloc.csv 68 | test_all 100 5000 69 | echo "100 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 70 | echo "100 ms,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> processtime_latency.csv 71 | echo "100 ms,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> processtime_alloc.csv 72 | test_all 500 5000 73 | echo "500 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 74 | echo "500 ms,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> processtime_latency.csv 75 | echo "500 ms,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> processtime_alloc.csv 76 | 77 | 78 | 79 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > concurrency.csv 80 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > concurrency_latency.csv 81 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > concurrency_alloc.csv 82 | test_all 30 100 83 | echo "100,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency.csv 84 | echo "100,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> concurrency_latency.csv 85 | echo "100,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> concurrency_alloc.csv 86 | test_all 30 1000 87 | echo "1000,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency.csv 88 | echo "1000,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> concurrency_latency.csv 89 | echo "1000,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> concurrency_alloc.csv 90 | test_all 30 5000 91 | echo "5000,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency.csv 92 | echo "5000,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> concurrency_latency.csv 93 | echo "5000,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> concurrency_alloc.csv 94 | 95 | mv -f processtime.csv ./testresults 96 | mv -f processtime_alloc.csv ./testresults 97 | mv -f processtime_latency.csv ./testresults 98 | 99 | mv -f concurrency.csv ./testresults 100 | mv -f concurrency_latency.csv ./testresults 101 | mv -f concurrency_alloc.csv ./testresults 102 | ./testresults/plot.sh 103 | -------------------------------------------------------------------------------- /test-latency.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | server_bin_name="gowebbenchmark" 4 | 5 | . ./libs.sh 6 | 7 | length=${#web_frameworks[@]} 8 | 9 | test_result=() 10 | test_latency_result=() 11 | test_alloc_result=() 12 | 13 | cpu_cores=$(< "/proc/cpuinfo" grep -c processor) 14 | if [ $cpu_cores -eq 0 ] 15 | then 16 | cpu_cores=1 17 | fi 18 | 19 | test_web_framework() 20 | { 21 | echo "testing web framework: $2" 22 | ./$server_bin_name $2 $3 > alloc.log 2>&1 & 23 | sleep 2 24 | wrk -t$cpu_cores -c$4 -d30s http://127.0.0.1:8080/hello > tmp.log 25 | throughput=$(< "tmp.log" grep Requests/sec|awk '{print $2}') 26 | latency=$(< "tmp.log" grep Latency | awk '{print $2}') 27 | latency=${latency%ms} 28 | alloc=$(< "alloc.log" grep HeapAlloc | awk '{print $2}') 29 | echo "throughput: $throughput requests/second, latency: $latency ms, alloc: $alloc" 30 | test_result[$1]=$throughput 31 | test_latency_result[$1]=$latency 32 | test_alloc_result[$1]=$alloc 33 | 34 | pkill -9 $server_bin_name 35 | sleep 2 36 | echo "finished testing $2" 37 | echo 38 | } 39 | 40 | test_all() 41 | { 42 | echo "###################################" 43 | echo " " 44 | echo " ProcessingTime $1ms " 45 | echo " Concurrency $2 " 46 | echo " " 47 | echo "###################################" 48 | for ((i=0; i processtime.csv 58 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > processtime_latency.csv 59 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > processtime_alloc.csv 60 | test_all 0 5000 61 | echo "0 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 62 | echo "0 ms,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> processtime_latency.csv 63 | echo "0 ms,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> processtime_alloc.csv 64 | test_all 10 5000 65 | echo "10 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 66 | echo "10 ms,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> processtime_latency.csv 67 | echo "10 ms,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> processtime_alloc.csv 68 | test_all 100 5000 69 | echo "100 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 70 | echo "100 ms,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> processtime_latency.csv 71 | echo "100 ms,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> processtime_alloc.csv 72 | test_all 500 5000 73 | echo "500 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 74 | echo "500 ms,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> processtime_latency.csv 75 | echo "500 ms,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> processtime_alloc.csv 76 | 77 | 78 | 79 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > concurrency.csv 80 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > concurrency_latency.csv 81 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > concurrency_alloc.csv 82 | test_all 30 100 83 | echo "100,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency.csv 84 | echo "100,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> concurrency_latency.csv 85 | echo "100,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> concurrency_alloc.csv 86 | test_all 30 1000 87 | echo "1000,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency.csv 88 | echo "1000,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> concurrency_latency.csv 89 | echo "1000,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> concurrency_alloc.csv 90 | test_all 30 5000 91 | echo "5000,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency.csv 92 | echo "5000,"$(IFS=$','; echo "${test_latency_result[*]}" ) >> concurrency_latency.csv 93 | echo "5000,"$(IFS=$','; echo "${test_alloc_result[*]}" ) >> concurrency_alloc.csv 94 | 95 | mv -f processtime.csv ./testresults 96 | mv -f processtime_alloc.csv ./testresults 97 | mv -f processtime_latency.csv ./testresults 98 | 99 | mv -f concurrency.csv ./testresults 100 | mv -f concurrency_latency.csv ./testresults 101 | mv -f concurrency_alloc.csv ./testresults 102 | ./testresults/plot.sh 103 | -------------------------------------------------------------------------------- /test-pipelining.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | server_bin_name="gowebbenchmark" 4 | 5 | . ./libs.sh 6 | 7 | length=${#web_frameworks[@]} 8 | 9 | test_result=() 10 | 11 | cpu_cores=$(< "/proc/cpuinfo" grep -c processor) 12 | if [ $cpu_cores -eq 0 ] 13 | then 14 | cpu_cores=1 15 | fi 16 | 17 | test_web_framework() 18 | { 19 | echo "testing web framework: $2" 20 | ./$server_bin_name $2 $3 & 21 | sleep 2 22 | 23 | throughput=$(wrk -t$cpu_cores -c$4 -d30s http://127.0.0.1:8080 -s pipeline.lua --latency -- /hello 16| grep Requests/sec | awk '{print $2}') 24 | echo "throughput: $throughput requests/second" 25 | test_result[$1]=$throughput 26 | 27 | pkill -9 $server_bin_name 28 | sleep 2 29 | echo "finished testing $2" 30 | echo 31 | } 32 | 33 | test_all() 34 | { 35 | echo "###################################" 36 | echo " " 37 | echo " ProcessingTime $1ms " 38 | echo " Concurrency $2 " 39 | echo " " 40 | echo "###################################" 41 | for ((i=0; i processtime-pipeline.csv 51 | test_all 0 5000 52 | echo "0 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime-pipeline.csv 53 | test_all 10 5000 54 | echo "10 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime-pipeline.csv 55 | test_all 100 5000 56 | echo "100 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime-pipeline.csv 57 | test_all 500 5000 58 | echo "500 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime-pipeline.csv 59 | 60 | 61 | 62 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > concurrency-pipeline.csv 63 | test_all 30 100 64 | echo "100,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency-pipeline.csv 65 | test_all 30 1000 66 | echo "1000,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency-pipeline.csv 67 | test_all 30 5000 68 | echo "5000,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency-pipeline.csv 69 | 70 | mv -f processtime-pipeline.csv ./testresults 71 | mv -f concurrency-pipeline.csv ./testresults 72 | ./testresults/plot.sh 73 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | server_bin_name="gowebbenchmark" 4 | 5 | . ./libs.sh 6 | 7 | length=${#web_frameworks[@]} 8 | 9 | test_result=() 10 | 11 | cpu_cores=$(< "/proc/cpuinfo" grep -c processor) 12 | if [ $cpu_cores -eq 0 ] 13 | then 14 | cpu_cores=1 15 | fi 16 | 17 | test_web_framework() 18 | { 19 | echo "testing web framework: $2" 20 | ./$server_bin_name $2 $3 & sleep 2 21 | 22 | throughput=$(wrk -t$cpu_cores -c$4 -d30s http://127.0.0.1:8080/hello) 23 | echo "$throughput" 24 | test_result[$1]=$(echo "$throughput" | grep Requests/sec | awk '{print $2}') 25 | 26 | pkill -9 $server_bin_name 27 | sleep 1 28 | echo "finished testing $2" 29 | echo 30 | } 31 | 32 | test_all() 33 | { 34 | echo "###################################" 35 | echo " " 36 | echo " ProcessingTime $1ms " 37 | echo " Concurrency $2 " 38 | echo " " 39 | echo "###################################" 40 | for ((i=0; i processtime.csv 50 | test_all 0 5000 51 | echo "0 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 52 | test_all 10 5000 53 | echo "10 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 54 | test_all 100 5000 55 | echo "100 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 56 | test_all 500 5000 57 | echo "500 ms,"$(IFS=$','; echo "${test_result[*]}" ) >> processtime.csv 58 | 59 | 60 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > concurrency.csv 61 | test_all 30 100 62 | echo "100,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency.csv 63 | test_all 30 1000 64 | echo "1000,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency.csv 65 | test_all 30 5000 66 | echo "5000,"$(IFS=$','; echo "${test_result[*]}" ) >> concurrency.csv 67 | 68 | 69 | test_all -1 5000 70 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > cpubound.csv 71 | echo "cpu-bound,"$(IFS=$','; echo "${test_result[*]}" ) >> cpubound.csv 72 | 73 | echo ","$(IFS=$','; echo "${web_frameworks[*]}" ) > cpubound-concurrency.csv 74 | test_all -1 100 75 | echo "100,"$(IFS=$','; echo "${test_result[*]}" ) >> cpubound-concurrency.csv 76 | test_all -1 1000 77 | echo "1000,"$(IFS=$','; echo "${test_result[*]}" ) >> cpubound-concurrency.csv 78 | test_all -1 5000 79 | echo "5000,"$(IFS=$','; echo "${test_result[*]}" ) >> cpubound-concurrency.csv 80 | 81 | 82 | mv -f processtime.csv ./testresults 83 | mv -f concurrency.csv ./testresults 84 | mv -f cpubound.csv ./testresults 85 | mv -f cpubound-concurrency.csv ./testresults 86 | ./testresults/plot.sh 87 | -------------------------------------------------------------------------------- /testresults/benchmark.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of different processing time" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "requests / second" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../benchmark.png" 21 | 22 | plot 't_processtime.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4), '' using 5:xticlabels(1) title columnheader(5) 23 | -------------------------------------------------------------------------------- /testresults/benchmark_alloc.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of different processing time (Allocations)" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "Allocations (MB)" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../benchmark_alloc.png" 21 | 22 | plot 't_processtime_alloc.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4), '' using 5:xticlabels(1) title columnheader(5) -------------------------------------------------------------------------------- /testresults/benchmark_latency.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of different processing time (Latency)" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "millisecond" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../benchmark_latency.png" 21 | 22 | #plot 't_processtime_latency.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4), '' using 5:xticlabels(1) title columnheader(5) 23 | 24 | plot 't_processtime_latency.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4) -------------------------------------------------------------------------------- /testresults/benchmark_pipeline.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of different processing time (pipelining)" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "requests / second" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../benchmark-pipeline.png" 21 | 22 | plot 't_processtime-pipeline.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4), '' using 5:xticlabels(1) title columnheader(5) 23 | -------------------------------------------------------------------------------- /testresults/concurrency-pipeline.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | 100,3113.88,3113.87,3116.27,3113.01,3110.66,3113.80 3 | 1000,32543.40,32513.29,32525.21,32525.93,32499.82,32528.43 4 | 5000,148368.67,142903.62,145767.53,146513.37,137985.84,145334.30 5 | -------------------------------------------------------------------------------- /testresults/concurrency.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | 100,3103.62,3103.73,3104.59,3103.72,3114.20,3105.10 3 | 1000,32423.67,32421.28,32413.72,32408.85,32411.78,32413.10 4 | 5000,120057.10,111899.80,114180.37,114503.28,108866.64,113671.85 5 | -------------------------------------------------------------------------------- /testresults/concurrency.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of concurrency 100, 1000, 5000" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "requests / second" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../concurrency.png" 21 | 22 | plot 't_concurrency.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4) -------------------------------------------------------------------------------- /testresults/concurrency_alloc.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | 100,11,6,10,7,11,7 3 | 1000,22,35,30,31,21,25 4 | 5000,144,132,97,151,130,117 5 | -------------------------------------------------------------------------------- /testresults/concurrency_alloc.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of concurrency 100, 1000, 5000 (Allocations)" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "Allocations (MB)" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../concurrency_alloc.png" 21 | 22 | 23 | plot 't_concurrency_alloc.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4) 24 | -------------------------------------------------------------------------------- /testresults/concurrency_latency.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | 100,30.90,30.90,30.89,30.88,30.78,30.89 3 | 1000,30.73,30.74,30.74,30.73,30.76,30.73 4 | 5000,41.09,44.13,43.23,43.18,45.27,43.46 5 | -------------------------------------------------------------------------------- /testresults/concurrency_latency.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of concurrency 100, 1000, 5000 (Latency)" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "millisecond" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../concurrency_latency.png" 21 | 22 | plot 't_concurrency_latency.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4) -------------------------------------------------------------------------------- /testresults/concurrency_pipeline.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of concurrency 100, 1000, 5000 (pipelining)" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "requests / second" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../concurrency-pipeline.png" 21 | 22 | plot 't_concurrency-pipeline.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4) 23 | -------------------------------------------------------------------------------- /testresults/cpubound-concurrency.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | 100,1663.74,1662.40,1668.58,1679.62,1676.21,1689.65 3 | 1000,1654.67,1652.65,1667.48,1662.35,1664.01,1662.96 4 | 5000,1579.48,1552.99,1645.13,1602.77,1610.72,1659.99 5 | -------------------------------------------------------------------------------- /testresults/cpubound.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | cpu-bound,1603.56,1525.20,1536.86,1511.77,1582.87,1615.46 3 | -------------------------------------------------------------------------------- /testresults/cpubound_benchmark.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of cpu-bound case" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "requests / second" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../cpubound_benchmark.png" 21 | 22 | plot 't_cpubound.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3) -------------------------------------------------------------------------------- /testresults/cpubound_concurrency.gnu: -------------------------------------------------------------------------------- 1 | reset 2 | set title "Benchmark of concurrency 100, 1000, 5000 for cpu-bound case" 3 | set boxwidth 0.9 4 | set datafile separator "," 5 | set style data histogram 6 | set style histogram clustered gap 2 7 | set style fill solid 0.7 border 8 | set border lw 0.8 9 | 10 | set ylabel "requests / second" 11 | set xtics nomirror rotate by -45 12 | set ytics nomirror 13 | 14 | set border 1+2 back 15 | set boxwidth -2 16 | 17 | set grid 18 | 19 | set term pngcairo font "Times Roman,14" enhanced size 1024,600 background rgb "gray80" 20 | set output "../cpubound_concurrency.png" 21 | 22 | plot 't_cpubound-concurrency.csv' using 2:xticlabels(1) title columnheader(2), '' using 3:xticlabels(1) title columnheader(3), '' using 4:xticlabels(1) title columnheader(4) -------------------------------------------------------------------------------- /testresults/plot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | m_path=$(dirname $0) 3 | m_path=${m_path/\./$(pwd)} 4 | cd $m_path 5 | 6 | ./transpose.sh 7 | 8 | gnuplot benchmark.gnu 9 | gnuplot benchmark_latency.gnu 10 | gnuplot benchmark_alloc.gnu 11 | gnuplot benchmark_pipeline.gnu 12 | 13 | gnuplot concurrency.gnu 14 | gnuplot concurrency_latency.gnu 15 | gnuplot concurrency_alloc.gnu 16 | gnuplot concurrency_pipeline.gnu 17 | 18 | gnuplot cpubound_benchmark.gnu 19 | gnuplot cpubound_concurrency.gnu 20 | 21 | rm -fr t_*.csv 22 | -------------------------------------------------------------------------------- /testresults/plot_mac.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | m_path=$(dirname $0) 3 | m_path=${m_path/\./$(pwd)} 4 | cd $m_path 5 | 6 | ./transpose.sh 7 | 8 | gnuplot -c benchmark.gnu 9 | gnuplot -c benchmark_latency.gnu 10 | gnuplot -c benchmark_alloc.gnu 11 | gnuplot -c benchmark_pipeline.gnu 12 | 13 | gnuplot -c concurrency.gnu 14 | gnuplot -c concurrency_latency.gnu 15 | gnuplot -c concurrency_alloc.gnu 16 | gnuplot -c concurrency_pipeline.gnu 17 | 18 | gnuplot -c cpubound_benchmark.gnu 19 | gnuplot -c cpubound_concurrency.gnu 20 | 21 | rm -fr t_*.csv 22 | -------------------------------------------------------------------------------- /testresults/processtime-pipeline.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | 0 ms,151731.17,147921.76,154685.14,154814.18,141616.29,152668.73 3 | 10 ms,144215.95,140200.34,144333.58,146462.50,134531.35,144914.32 4 | 100 ms,49372.16,49374.53,49389.27,49385.28,49363.96,49356.72 5 | 500 ms,9812.85,9800.71,9814.06,9813.04,9830.48,9816.31 6 | -------------------------------------------------------------------------------- /testresults/processtime.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | 0 ms,120770.06,120367.94,124727.97,124419.16,116549.53,123579.56 3 | 10 ms,116210.81,115965.84,117805.31,118851.87,110629.52,117960.15 4 | 100 ms,49373.54,49338.11,49375.19,49374.10,49346.70,49357.26 5 | 500 ms,9800.42,9800.55,9804.25,9801.69,9801.51,9801.15 6 | -------------------------------------------------------------------------------- /testresults/processtime_alloc.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | 0 ms,113,92,97,106,92,109 3 | 10 ms,120,96,123,97,123,112 4 | 100 ms,118,101,98,95,136,100 5 | 500 ms,76,131,79,84,120,123 6 | -------------------------------------------------------------------------------- /testresults/processtime_latency.csv: -------------------------------------------------------------------------------- 1 | ,default,chi,echo,gin,goframe,httpz 2 | 0 ms,40.49,40.70,39.24,39.22,41.98,39.54 3 | 10 ms,43.64,43.24,42.83,41.99,44.96,42.82 4 | 100 ms,100.83,100.88,100.81,100.83,100.84,100.83 5 | 500 ms,501.16,501.32,501.40,501.27,501.32,501.16 6 | -------------------------------------------------------------------------------- /testresults/transpose.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for file in `ls *.csv` 4 | do 5 | awk -f tst.awk $file > t_$file 6 | done 7 | -------------------------------------------------------------------------------- /testresults/tst.awk: -------------------------------------------------------------------------------- 1 | BEGIN { FS=OFS="," } 2 | { 3 | for (rowNr=1;rowNr<=NF;rowNr++) { 4 | cell[rowNr,NR] = $rowNr 5 | } 6 | maxRows = (NF > maxRows ? NF : maxRows) 7 | maxCols = NR 8 | } 9 | END { 10 | for (rowNr=1;rowNr<=maxRows;rowNr++) { 11 | for (colNr=1;colNr<=maxCols;colNr++) { 12 | printf "%s%s", cell[rowNr,colNr], (colNr < maxCols ? OFS : ORS) 13 | } 14 | } 15 | } 16 | --------------------------------------------------------------------------------