description
    性能测试

    elton的性能如何是大家都会关心的重点,下面是使用测试服务器(4U8线程,8G内存)的几个测试场景,go版本为1.14:

    1. package main
    2. import (
    3. "bytes"
    4. "github.com/vicanso/elton"
    5. )
    6. func main() {
    7. d := elton.New()
    8. d.GET("/", func(c *elton.Context) (err error) {
    9. c.BodyBuffer = bytes.NewBufferString("Hello, World!")
    10. return
    11. })
    12. err := d.ListenAndServe(":3000")
    13. if err != nil {
    14. panic(err)
    15. }
    16. }
    1. wrk -c 1000 -t 10 --latency 'http://127.0.0.1:3000/'
    2. Running 10s test @ http://127.0.0.1:3000/
    3. 10 threads and 1000 connections
    4. Thread Stats Avg Stdev Max +/- Stdev
    5. Latency 11.24ms 12.07ms 127.54ms 87.12%
    6. Req/Sec 11.39k 2.60k 33.20k 74.42%
    7. Latency Distribution
    8. 50% 7.24ms
    9. 75% 13.95ms
    10. 90% 26.98ms
    11. 99% 56.30ms
    12. 1129086 requests in 10.09s, 139.98MB read
    13. Requests/sec: 111881.19
    14. Transfer/sec: 13.87MB

    从上面的测试可以看出,每秒可以处理110K的请求数,这看着性能是好高,但实际上这种测试的意义不太大,不过总可以让大家放心不至于拖后腿。

    elton的亮点是在响应数据中间件的处理,以简单的方式返回正常或出错的响应数据,下面我们来测试一下这两种场景的性能表现。

    1. package main
    2. import (
    3. "strings"
    4. "github.com/vicanso/elton"
    5. "github.com/vicanso/elton/middleware"
    6. "github.com/vicanso/hes"
    7. )
    8. type (
    9. HelloWord struct {
    10. Content string `json:"content,omitempty"`
    11. Size int `json:"size,omitempty"`
    12. Price float32 `json:"price,omitempty"`
    13. VIP bool `json:"vip,omitempty"`
    14. }
    15. )
    16. func main() {
    17. d := elton.New()
    18. arr := make([]string, 0)
    19. for i := 0; i < 100; i++ {
    20. arr = append(arr, "花褪残红青杏小。燕子飞时,绿水人家绕。枝上柳绵吹又少,天涯何处无芳草!")
    21. }
    22. content := strings.Join(arr, "\n")
    23. d.Use(middleware.NewDefaultError())
    24. d.Use(middleware.NewDefaultResponder())
    25. d.GET("/", func(c *elton.Context) (err error) {
    26. c.Body = &HelloWord{
    27. Content: content,
    28. Size: 100,
    29. Price: 10.12,
    30. VIP: true,
    31. }
    32. return
    33. })
    34. d.GET("/error", func(c *elton.Context) (err error) {
    35. err = hes.New("abcd")
    36. return
    37. })
    38. err := d.ListenAndServe(":3000")
    39. if err != nil {
    40. panic(err)
    41. }
    42. }
    1. wrk -c 1000 -t 10 --latency 'http://127.0.0.1:3000/'
    2. Running 10s test @ http://127.0.0.1:3000/
    3. 10 threads and 1000 connections
    4. Thread Stats Avg Stdev Max +/- Stdev
    5. Latency 46.41ms 58.15ms 606.12ms 83.56%
    6. Req/Sec 4.22k 798.75 7.18k 69.90%
    7. Latency Distribution
    8. 50% 15.31ms
    9. 75% 79.23ms
    10. 90% 129.41ms
    11. 99% 240.98ms
    12. 420454 requests in 10.07s, 4.26GB read
    13. Requests/sec: 41734.70
    14. Transfer/sec: 432.80MB
    1. wrk -c 1000 -t 10 --latency 'http://127.0.0.1:3000/error'
    2. Running 10s test @ http://127.0.0.1:3000/error
    3. 10 threads and 1000 connections
    4. Thread Stats Avg Stdev Max +/- Stdev
    5. Latency 11.29ms 11.36ms 146.95ms 86.59%
    6. Req/Sec 10.91k 2.37k 21.86k 70.08%
    7. Latency Distribution
    8. 50% 7.62ms
    9. 75% 14.23ms
    10. 90% 26.56ms
    11. 99% 53.32ms
    12. 1083752 requests in 10.10s, 142.63MB read
    13. Non-2xx or 3xx responses: 1083752
    14. Requests/sec: 107344.19
    15. Transfer/sec: 14.13MB

    对于正常返回(数据量为10KB)的struct做序列化时,性能会有所降低,从测试结果可以看出,每秒还是可以处理41K的请求,出错的转换处理效率更高,每秒能处理107K的请求。

    下面是gin的测试结果:

    1. package main
    2. import (
    3. "strings"
    4. "github.com/gin-gonic/gin"
    5. )
    6. type (
    7. HelloWord struct {
    8. Content string `json:"content,omitempty"`
    9. Size int `json:"size,omitempty"`
    10. Price float32 `json:"price,omitempty"`
    11. VIP bool `json:"vip,omitempty"`
    12. }
    13. )
    14. func main() {
    15. arr := make([]string, 0)
    16. for i := 0; i < 100; i++ {
    17. arr = append(arr, "花褪残红青杏小。燕子飞时,绿水人家绕。枝上柳绵吹又少,天涯何处无芳草!")
    18. }
    19. content := strings.Join(arr, "\n")
    20. router := gin.New()
    21. router.GET("/", func(c *gin.Context) {
    22. c.JSON(200, &HelloWord{
    23. Content: content,
    24. Size: 100,
    25. Price: 10.12,
    26. VIP: true,
    27. })
    28. })
    29. router.Run(":3000")
    30. }
    1. wrk -c 1000 -t 10 --latency 'http://127.0.0.1:3000/'
    2. Running 10s test @ http://127.0.0.1:3000/
    3. 10 threads and 1000 connections
    4. Thread Stats Avg Stdev Max +/- Stdev
    5. Latency 52.17ms 66.58ms 629.46ms 83.46%
    6. Req/Sec 3.97k 0.91k 13.91k 72.16%
    7. Latency Distribution
    8. 50% 16.37ms
    9. 75% 89.93ms
    10. 90% 145.96ms
    11. 99% 277.75ms
    12. 394628 requests in 10.10s, 4.00GB read
    13. Requests/sec: 39075.49
    14. Transfer/sec: 405.90MB

    从上面的测试数据可以看出elton的性能与gin整体上基本一致,无需太过担忧性能问题,需要注意的是elton不再使用httprouter来处理路由,路由参数支持更多自定义的处理,因此路由的查询性能有所下降。