Go language Web Frame comparison: Gin vs Iris vs Echo

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Objective

Because Golang provides a complete library of net/http standards, the difficulty of implementing a Web framework based on the standard library is much lower than in other languages, so the Go web framework is simply a flowering. From the old Revel and Beego, to the new gin, and Iris, and some like the router of Chi. Personal general small projects, especially middleware needs to expose some HTTP interface, the basic use of Chi can be.
This test is mainly the gin iris echo of the three frames. Focus on high performance, from concurrency and JSON serialization and deserialization two aspects to evaluate, after all, background projects focus on these two aspects.

Test

Test environment Description

In order to select a framework that conforms to the heavy IO, the specific requirements for the following scenarios are set Demo,demo:

    1. Turn on logging (logs are also logged when impersonating a normal business), recording a log separately at the beginning and end of a request
    2. Interface with sleep pause for 1 seconds, assuming the network IO operation here (and also more easily from the log to see if the behavior of the co-process concurrency)
    3. Use the Post interface to do the test, the interface does not do any processing, the received body directly serialized return (serialization and deserialization is the framework of the highest frequency action)
    4. Open the Accesslog function of a frame

Test tools and scenarios are as follows

    1. Test tools use the classic JMeter to test directly with the GUI interface
    2. Scenarios are divided into 10 thread concurrency, 100 thread concurrency, 500 thread concurrency, 1000 thread concurrency, and 1500 thread concurrency
    3. All results only look at JMeter aggregation reports, focusing on throughput, time, and number of errors
    4. All demos start with a single thread, and the async framework does not limit the number of threads, setting Gomaxprocs=1
    5. All tests are local, two minutes of pressure measurement
    6. Post requests are tested with data samples of 565bytes, 5KB, 10KB, 50KB, and 100KB, each tested on a different concurrent thread

Test code

Gin

Package Mainimport ("Log" "Net/http" "Time" "Github.com/gin-gonic/gin")//Agent ... type agent struct {age Ntid string ' JSON: ' agent_id ' ' Queuedat string ' json: ' Queued_at ' ' Queuedby string ' json: ' queued_by ' '}//Details ... t ype Details struct {EventID string ' JSON: "event_id" ' Endpoint string Metric string Content string Prio rity int Status string}//Test1 ... type Test1 struct {agent agent details details Description str     ing EventType string ' json: ' Event_type ' ' Servicekey string ' json: ' Service_key ' '}//Test2 test2type Test2 struct { Data []*test1}func Main () {r: = gin. New ()//Global middleware//Logger middleware would write the logs to gin.    Defaultwriter even if you set with Gin_mode=release. By default gin. Defaultwriter = OS. Stdout R.use (gin. Logger ()) R.get ("/ping", func (c *gin). Context) {C.json, gin. h{"message": "Pong",})}) R.post ("/v1/test", Func (c*gin. Context) {var test Test1 if Err: = C.bindjson (&test); err = = Nil {log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") C.json (http. Statusok, test)} else {C.json (http. Statusbadrequest, Gin. h{"error": Err. Error ()})}) R.post ("/v2/test", func (c *gin). Context) {var test Test2 if Err: = C.bindjson (&test); err = = Nil {log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") C.json (http. Statusok, test)} else {C.json (http. Statusbadrequest, Gin. h{"error": Err. Error ()})}) R.post ("/v3/test", func (c *gin). Context) {var test Test2 if ERr: = C.bindjson (&test); Err = = Nil {log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") C.json (http. Statusok, test)} else {C.json (http. Statusbadrequest, Gin. h{"error": Err. Error ()})}) R.post ("/v4/test", func (c *gin). Context) {var test Test2 if Err: = C.bindjson (&test); err = = Nil {log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") C.json (http. Statusok, test)} else {C.json (http. Statusbadrequest, Gin. h{"error": Err. Error ()})}) R.run ()//listen and serve on 0.0.0.0:8080}

Iris:

Package Mainimport ("Time" "Github.com/kataras/iris" "Github.com/kataras/iris/middleware/logger")//Agent ... Typ E Agent struct {agentid string ' JSON: ' agent_id ' ' Queuedat string ' json: ' Queued_at ' ' Queuedby string ' JSON: ' Queu    Ed_by "'}//details ... type details struct {EventID string ' JSON: ' event_id ' ' Endpoint string Metric string Content string Priority int Status string}//Test1 ... type Test1 struct {Agent agent Details Det Ails Description string EventType string ' JSON: ' Event_type ' ' Servicekey string ' json: ' Service_key ' '}//Test2 t Est2type Test2 struct {Data []*test1}func main () {app: = Iris. New () app. Use (logger. New ()) app. Get ("/ping", func (c Iris). Context) {c.writestring ("Pong")}) app. Post ("/v1/test", func (c Iris). Context) {var test Test1 if Err: = C.readjson (&test); err = = Nil {app. Logger (). Println ("========================start io=====================")           Time. Sleep (time. Duration (1) * time. Second) app. Logger (). Println ("=========================end io=======================") C.json (test)} else {C.wri Testring ("Failure")}) app. Post ("/v2/test", func (c Iris). Context) {var test Test2 if Err: = C.readjson (&test); err = = Nil {app. Logger (). Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) app. Logger (). Println ("=========================end io=======================") C.json (test)} else {C.wri Testring ("Failure")}) app. Post ("/v3/test", func (c Iris). Context) {var test Test2 if Err: = C.readjson (&test); err = = Nil {app. Logger (). Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) app. Logger (). Println ("=========================end io======================= ") C.json (test)} else {c.writestring (" failure ")} }) app. Post ("/v4/test", func (c Iris). Context) {var test Test2 if Err: = C.readjson (&test); err = = Nil {app. Logger (). Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) app. Logger (). Println ("=========================end io=======================") C.json (test)} else {C.wri    Testring ("Failure")})//Start the server using a network address. App. Run (Iris. ADDR (": 8080"),//Disables Updates:iris. Withoutversionchecker,//Skip ERR server closed when Ctrl/cmd+c Pressed:iris. Withoutservererror (Iris. errserverclosed),//enables faster JSON serialization and More:iris. Withoptimizations)}

Echo:

Package Mainimport ("Log" "Net/http" "Time" "Github.com/labstack/echo" "Github.com/labstack/echo/middlewar E ")//Agent ... type agent struct {agentid string ' JSON:" agent_id "' Queuedat string ' JSON:" Queued_at "' Queuedby String ' JSON: ' queued_by '}//details ... type details struct {EventID string ' JSON: ' event_id ' ' Endpoint string M    Etric string Content string priority int Status string}//Test1 ... type Test1 struct {agent agent Details Description string EventType string ' JSON: "Event_type" ' Servicekey string ' JSON: "Servic E_key "'}//Test2 test2type Test2 struct {Data []*test1}func Main () {//echo instance app: = Echo. New ()//middleware app. Use (middleware. Logger ())//Routes app. GET ("/ping", Func (c echo.) Context) Error {return c.string ("Pong")}) app. POST ("/v1/test", Func (c echo.) Context) error {var test Test1 if Err: = C.bind (&test); Err! = Nil {            Return err} log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") return C.json (http. Statusok, Test)}) app. POST ("/v2/test", Func (c echo.)        Context) error {var test Test2 if Err: = C.bind (&test); Err! = nil {return err} Log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") return C.json (http. Statusok, Test)}) app. POST ("/v3/test", Func (c echo.)        Context) error {var test Test2 if Err: = C.bind (&test); Err! = nil {return err} Log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io======================= ") return C.json (http. Statusok, Test)}) app. POST ("/v4/test", Func (c echo.)        Context) error {var test Test2 if Err: = C.bind (&test); Err! = nil {return err} Log. Println ("========================start io=====================") time. Sleep (time. Duration (1) * time. Second) log. Println ("=========================end io=======================") return C.json (http. Statusok, Test)})//Start server app. Logger.fatal (app. Start (": 8080"))}
    1. In addition to Echo, the three other JSON serialization libraries that natively support the performance of Jsoniter are enabled.
    2. Wait 1s, analog io read/write wait

Test comparison

Due to the testing of 5 body samples, 4 scenarios, 4 frames, the key data is filtered out (throughput, error rate and 99%line, the importance descending in order), the results are drawn graphics, easy to view.

Test results under 565bytes



Test results under 5KB



Test results under 10KB



Test results under 50KB



Test results under 100KB



Summarize

Combined with each of these test results, gin and iris are excellent frameworks, gin are slightly more advantageous than others, Iris is the second, and Echo is almost the same.
This test simply tested the concurrency and JSON correlation of the 3 frameworks. The comparison results, excluding the ecology and the perfection of tools and so on. If there are any imperfections in the test, welcome to the exchange.
You are also welcome to try and star another web framework baa, in order to suspicion I did not post a BAA data, the performance test is gin and between Iris.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.