【Go言語】フレームワーク8種のベンチマークを測定してみた

# はじめに

Gin, Fiber, Echo, Iris, Aero, Gorilla, Chi, Beegoの8つのフレームワーク(Gorilla等は厳密にいうとフレームワークではない)のパフォーマンスを比較してみました。

[Bombardier](https://qiita.com/twrcd1227/items/e2165cec501b176495fa)というGo製のツールを用いて、ベンチマークを測定しました。結果だけ知りたい人は [結果](#結果) まで飛んでください。

# テスト環境情報

MacBook Air M2
メモリ 16GB
macOS 13.6
Docker Compose version v2.23.0-desktop.1
Docker version 24.0.6
go version 1.21.5
gin v1.9.1
Fiber v2.52.0
Echo v4.11.4
Iris v12.2.8
Aero v1.3.59
Gorilla v1.8.1
Chi v1.5.5
Beego v2.1.4

# テスト対象サーバのコード

## Gin

```go:main.go
package main

import "github.com/gin-gonic/gin"

func main() {
	gin.SetMode(gin.ReleaseMode)
	r := gin.New()
	r.GET("/", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "hello",
		})
	})
	r.Run()
}
```

## Fiber

```go:main.go
package main

import "github.com/gofiber/fiber/v2"

func main() {
	app := fiber.New()

	app.Get("/", func(c *fiber.Ctx) error {
		return c.JSON(fiber.Map{
			"message": "hello",
		})
	})

	app.Listen(":8080")
}
```

## Echo

```go:main.go
package main

import (
	"github.com/labstack/echo/v4"
	"net/http"
)

func main() {
	e := echo.New()

	e.GET("/", func(c echo.Context) error {
		return c.JSON(http.StatusOK, map[string]string{"message": "hello"})
	})

	e.Start(":8080")
}
```

## iris

```go:main.go
package main

import "github.com/kataras/iris/v12"

func main() {
	app := iris.New()
	app.Get("/", func(ctx iris.Context) {
		ctx.JSON(iris.Map{
			"message": "hello",
		})
	})

	app.Run(iris.Addr(":8080"))
}
```


## Aero

```go:main.go
package main

import (
	"github.com/aerogo/aero"
)

func main() {

	app := aero.New()
	app.Config.Ports.HTTP = 8080

	app.Get("/hello", func(ctx aero.Context) error {
		return ctx.JSON(map[string]interface{}{
			"message": "hello",
		})
	})

	app.Run()
}
```

## Gorilla

```go:main.go
package main

import (
	"encoding/json"
	"net/http"

	"github.com/gorilla/mux"
)

func main() {
	router := mux.NewRouter()

	router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)

		response := map[string]string{"message": "hello"}
		json.NewEncoder(w).Encode(response)
	}).Methods("GET")

	http.Handle("/", router)

	// ポート8080でサーバーを起動
	http.ListenAndServe(":8080", nil)
}
```

## Chi

```go:main.go
package main

import (
	"encoding/json"
	"net/http"

	"github.com/go-chi/chi"
)

func main() {
	r := chi.NewRouter()

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		response := map[string]string{"message": "hello"}
		json.NewEncoder(w).Encode(response)
	})

	http.ListenAndServe(":8080", r)
}
```


## beego

```go:main.go
package main

import (
	"github.com/beego/beego/v2/server/web"
)

type MainController struct {
	web.Controller
}

func (ctrl *MainController) Get() {
	ctrl.Data["json"] = map[string]string{"message": "hello"}
	ctrl.ServeJSON()
}

func main() {
	web.Router("/", &MainController{})
	web.Run()
}
```

## テストケース

以下の4つのケースで行いました。

```bash
# 1コネクションで合計1000000リクエスト送る
bombardier -c 1 -n 1000000 http://localhost:8080
# 1コネクションで10秒間リクエストする
bombardier -c 1 -d 10s -l http://localhost:8080
# 200コネクションで1000000リクエスト送る
bombardier -c 125 -n 1000000 http://localhost:8080
# 125コネクションで10秒間リクエストする
bombardier -c 200 -d 10s -l http://localhost:8080
```

# 結果


## 1コネクションで1000000リクエスト送った結果

| フレームワーク | Reqs/sec(Avg) | Reqs/sec(Stdev) | Reqs/sec(Max) | Latency(Avg) | Latency(Stdev) | Latency(Max) | Throughput |
|--------------|---------------|------------------|---------------|--------------|----------------|--------------|------------|
| Gin          | 17243.16      | 1907.85          | 49741.92      | 56.73us      | 35.67us        | 11.73ms      | 3.36MB/s    |
| Fiber        | 20517.75      | 1812.56          | 61718.28      | 47.52us      | 23.76us        | 10.21ms      | 3.70MB/s    |
| Echo         | 17212.66      | 1587.81          | 41085.46      | 56.81us      | 44.09us        | 14.58ms      | 3.37MB/s    |
| iris         | 16554.60      | 1296.85          | 31794.50      | 59.14us      | 29.66us        | 18.43ms      | 3.24MB/s    |
| Aero         | 17517.70      | 2971.88          | 55515.81      | 55.82us      | 72.92us        | 23.27ms      | 2.40MB/s    |
| Gorilla      | 16653.57      | 2559.59          | 37527.32      | 58.80us      | 64.68us        | 23.68ms      | 3.02MB/s    |
| Chi          | 17084.79      | 2018.57          | 42708.64      | 57.26us      | 58.04us        | 17.75ms      | 3.24MB/s    |
| beego        | 15426.07      | 2108.86          | 34108.83      | 63.51us      | 57.57us        | 20.79ms      | 3.00MB/s    |

![single1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156096/8d5a37ea-f139-6eb5-4506-6fbee5ada71a.png)


## 1コネクションで10秒間リクエストした結果

| フレームワーク | Reqs/sec(Avg) | Reqs/sec(Stdev) | Reqs/sec(Max) | Latency(Avg) | Latency(Stdev) | Latency(Max) | Throughput |
|--------------|---------------|------------------|---------------|--------------|----------------|--------------|------------|
| Gin          | 17106.22      | 1282.68          | 25141.96      | 57.22us      | 16.31us        | 4.13ms       | 3.33MB/s    |
| Fiber        | 20799.90      | 2484.20          | 47345.97      | 46.87us      | 33.74us        | 8.53ms       | 3.75MB/s    |
| Echo         | 16931.02      | 1514.14          | 23866.86      | 57.79us      | 24.29us        | 5.95ms       | 3.31MB/s    |
| iris         | 16099.18      | 1906.67          | 38404.39      | 60.84us      | 40.52us        | 6.39ms       | 3.15MB/s    |
| Aero         | 18089.56      | 1909.10          | 27211.90      | 54.03us      | 26.72us        | 4.78ms       | 2.48MB/s    |
| Gorilla      | 16639.12      | 2032.12          | 23358.05      | 58.83us      | 51.22us        | 18.90ms      | 3.01MB/s    |
| Chi          | 17083.86      | 1351.04          | 32302.24      | 57.28us      | 20.16us        | 3.90ms       | 3.24MB/s    |
| beego        | 14867.76      | 2521.89          | 24303.04      | 65.97us      | 119.40us       | 34.81ms      | 2.89MB/s    |

![single2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156096/fb6eaa8a-4eeb-6f95-ba9d-6d14e4b6bca9.png)

## 200コネクションで1000000リクエスト送った結果

| フレームワーク | Reqs/sec(Avg) | Reqs/sec(Stdev) | Reqs/sec(Max) | Latency(Avg) | Latency(Stdev) | Latency(Max) | Throughput |
|------|--------------|-------------------|---------------|--------------|----------------|--------------|------------|
| Gin    | 208636.02    | 25754.38          | 253525.30     | 597.28us      | 325.95us       | 12.29ms      | 40.63MB/s   |
| Fiber    | 336809.43    | 55120.39          | 400314.69     | 369.63us      | 484.75us       | 31.42ms      | 60.67MB/s   |
| Echo    | 205317.11    | 34161.60          | 249844.79     | 608.24us      | 356.58us       | 23.65ms      | 40.08MB/s   |
| Iris    | 170416.71    | 55652.55          | 247878.33     | 732.21us      | 636.67us       | 25.55ms      | 33.29MB/s   |
| Aero4    | 222673.49    | 47455.50          | 287053.07     | 560.91us      | 477.03us       | 27.47ms      | 30.53MB/s   |
| Gorilla      | 193247.91    | 30438.74          | 248160.39     | 645.60us      | 463.03us       | 48.23ms      | 34.99MB/s   |
| Chi    | 195821.22    | 49706.30          | 258315.63     | 637.03us      | 484.10us       | 27.10ms      | 37.11MB/s   |
| Beego    | 148201.65    | 37780.27          | 200222.14     | 842.40us      | 760.16us       | 52.49ms      | 28.82MB/s   |

![multi1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156096/5edddf64-83fa-dde8-4c80-023f84d7e432.png)


## 125コネクションで10秒間リクエストした結果

| フレームワーク | Reqs/sec(Avg) | Reqs/sec(Stdev) | Reqs/sec(Max) | Latency(Avg) | Latency(Stdev) | Latency(Max) | Throughput |
|--------------|---------------|------------------|---------------|--------------|----------------|--------------|------------|
| Gin          | 189460.07     | 54921.14         | 266439.56     | 1.06ms       | 740.37us       | 50.99ms      | 36.83MB/s   |
| Fiber        | 324226.98     | 59336.25         | 499175.37     | 616.27us     | 481.23us       | 37.24ms      | 58.33MB/s   |
| Echo         | 205546.31     | 38669.41         | 255035.10     | 0.97ms       | 519.23us       | 26.75ms      | 40.16MB/s   |
| iris         | 197964.44     | 36639.99         | 260544.20     | 1.01ms       | 529.77us       | 41.35ms      | 38.69MB/s   |
| Aero         | 207057.97     | 55036.34         | 294250.62     | 0.96ms       | 509.91us       | 26.24ms      | 28.42MB/s   |
| Gorilla      | 193298.12     | 28153.72         | 238842.58     | 1.03ms       | 529.80us       | 30.72ms      | 35.01MB/s   |
| Chi          | 205582.09     | 39478.05         | 276359.19     | 0.97ms       | 512.48us       | 38.60ms      | 38.92MB/s   |
| beego        | 171670.19     | 28420.81         | 216237.75     | 1.16ms       | 631.20us       | 33.14ms      | 33.38MB/s   |

![multi2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156096/4b4467cc-89fb-9bdc-e901-6fb3ebb192d8.png)

# まとめ

個人的にはGinが一番速いものだと思っていたのですが、今回のベンチマーク結果ではFiberがほとんどの場面で高パフォーマンスでした。環境や目的によって最適なフレームワークは変わると思うので、トレードオフを考えて、自分にあったベストなフレームワークを見つけましよう。