ใช้ FastAPI ให้เร็วขึ้นถึงเกือบเท่า Go Gin

จากบทความก่อนหน้านี้

Python ก็เร็วเท่า GoLang ได้ จริงไหม?

เรามาทำให้ FastAPI ของเราให้เร็วขึ้นถึงเกือบเท่า Go Gin ในบทความนี้ จะทำการใช้ Docker เข้ามาช่วยในการทดสอบความเร็วในการประมวลผล ระหว่าง Python3.11 pypy3.10 และ Go1.20.6 นะครับ

โดย Docker จะถึงตั้งค่าไว้แบบเดี่ยวกัน และใช้ โค๊ต การทำงานแบบเดียวกัน

โค๊ตที่ใช้ในการทดสอบด้วย FastAPI

import timeit
import platform
from fastapi import FastAPI

def make_tree(d):
    if d > 0:
        d -= 1
        return (make_tree(d), make_tree(d))
    return (None, None)

def check_tree(node):
    (l, r) = node
    return 1 if l is None else 1 + check_tree(l) + check_tree(r)


def make_check(d, make=make_tree, check=check_tree):
    return check(make(d))

def main(n, min_depth=4):
    max_depth = max(min_depth + 2, n)
    stretch_depth = max_depth + 1
    print('stretch tree of depth {0}\t check: {1}'.format(
          stretch_depth, make_check(stretch_depth)))

    long_lived_tree = make_tree(max_depth)

    mmd = max_depth + min_depth
    for d in range(min_depth, stretch_depth, 2):
        i = 2 ** (mmd - d)
        cs = sum(make_check(d) for _ in range(i))
        print('{0}\t trees of depth {1}\t check: {2}'.format(i, d, cs))

    print('long lived tree of depth {0}\t check: {1}'.format(
          max_depth, check_tree(long_lived_tree)))


app = FastAPI()

@app.get("/")
async def Home():
    starttime = timeit.default_timer()
    n = 18
    d = 4
    print("Tree recursion ==> ",n)
    print("Python Version ==> ",platform.python_version())
    main(n,d)
    print("The time difference is :", timeit.default_timer() - starttime," seconds")
    return {}

โค๊ตที่ใช้ในการทดสอบด้วย Go gin

package main

import (
	"fmt"
	"math"
	"net/http"
	"runtime"
	"strings"
	"time"

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

type node struct {
	left, right *node
}

func makeTree(d int) *node {
	if d > 0 {
		d--
		return &node{left: makeTree(d), right: makeTree(d)}
	}
	return nil
}

func checkTree(node *node) int {
	if node == nil {
		return 0
	}
	return 1 + checkTree(node.left) + checkTree(node.right)
}

func makeCheck(d int) int {
	return checkTree(makeTree(d))
}

func run(n, minDepth int) {
	maxDepth := int(math.Max(float64(minDepth+2), float64(n)))
	stretchDepth := maxDepth + 1

	fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, makeCheck(stretchDepth))

	longLivedTree := makeTree(maxDepth)

	mmd := maxDepth + minDepth
	for d := minDepth; d <= maxDepth; d += 2 {
		i := int(math.Pow(2, float64(mmd-d)))
		cs := 0
		for j := 0; j < i; j++ {
			cs += makeCheck(d)
		}
		fmt.Printf("%d\t trees of depth %d\t check: %d\n", i, d, cs)
	}

	fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, checkTree(longLivedTree))
}

func homeHandler(c *gin.Context) {
	startTime := time.Now()
	n := 18
	d := 4
	fmt.Println("Tree recursion ==> ", n)
	fmt.Println("Go Version ==> ", runtime.Version())
	run(n, d)
	fmt.Println("The time difference is :", time.Since(startTime), " seconds")

	c.JSON(http.StatusOK, gin.H{})
}

func getRealIP(c *gin.Context) string {
	// Check X-Real-IP first, then X-Forwarded-For.
	// X-Forwarded-For may return multiple IP addresses, and the original client IP will be the first one.
	xRealIP := c.Request.Header.Get("X-Real-IP")
	xForwardedFor := c.Request.Header.Get("X-Forwarded-For")

	if xRealIP != "" {
		return xRealIP
	} else if xForwardedFor != "" {
		return strings.Split(xForwardedFor, ",")[0]
	}

	return c.Request.RemoteAddr
}

func main() {
	r := gin.Default()

	r.GET("/", homeHandler)

	if err := r.Run(":8080"); err != nil {
		fmt.Println("Error starting server:", err)
	}
}

docker-compose.yaml

version: "3.9"
services:
  pypy-test:
    ports:
      - 8000:8000
    build:
      context: .
      dockerfile: Dockerfile-pypy
  python-test:
    ports:
      - 8001:8000
    build:
      context: .
      dockerfile: Dockerfile-python
  golang-test:
    ports:
      - 8002:8080
    build:
      context: .
      dockerfile: Dockerfile-golang

Dockerfile-python == Python3.11

FROM python:3.11-slim

WORKDIR /app

COPY . .

RUN python -m pip install --no-cache-dir -r requirements.txt

EXPOSE 8000

CMD ["python", "-m","uvicorn", "app2:app","--host", "0.0.0.0","--port","8000"]

Dockerfile-pypy == pypy3.10

FROM pypy:3.10-slim

WORKDIR /app

COPY . .

RUN pypy -m pip install --no-cache-dir -r requirements.txt

EXPOSE 8000

CMD ["pypy","-m","uvicorn", "app2:app","--host", "0.0.0.0","--port","8000"]

Dockerfile-golang == go1.20.6

FROM golang:1.20-alpine

WORKDIR /app

COPY go.mod go.sum ./

RUN go mod download

COPY app.go .

RUN go build app.go

EXPOSE 8080

CMD ["./app"]


Docker Golang (0.9 วินาที)
Docker pypy3.10 (1.3 วินาที)
Docker python3.11 (6.4 วินาที)

จะเห็นได้ว่าเมื่อใช้งานผ่าน Docker แล้ว Golang 1.20.6 เร็วกว่า pypy3.10 นิดหน่อย เพียง 300-400ms เท่านั้น ในทาง API แล้วถือว่าเป็นทางเลือกที่ดีเลยทีเดี่ยวสำหรับคนที่เขียน Python ด้วย FastAPI

Read more

สวีเดน พบ ตูนิเซีย: ศึกเปิดสนามฟุตบอลโลก 2026 กลุ่ม F – ใครจะเหนือกว่ากัน?

สวีเดน พบ ตูนิเซีย: ศึกเปิดสนามฟุตบอลโลก 2026 กลุ่ม F – ใครจะเหนือกว่ากัน?

วิเคราะห์เจาะลึกแมตช์เดือด สวีเดน พบ ตูนิเซีย ฟุตบอลโลก 2026 กลุ่ม F พร้อมรายชื่อนักเตะ การวิเคราะห์เกมรุก-รับ และช่องทางดูบอลสด

By ทีมงาน devdog
ลือสะเทือนวงการ! HUAWEI Mate 90 series เตรียมเขย่าตลาดด้วย 5 รุ่นรวด พร้อม "Fan Edition" ทรงพลัง

ลือสะเทือนวงการ! HUAWEI Mate 90 series เตรียมเขย่าตลาดด้วย 5 รุ่นรวด พร้อม "Fan Edition" ทรงพลัง

เตรียมพบกับ HUAWEI Mate 90 series ที่ลือว่าจะเปิดตัว 5 รุ่นรวด รวมถึง Fan Edition พร้อมเทคโนโลยีระบายความร้อน 3D Liquid-Cooling สุดล้ำ คาดการณ์กันยายนนี้!

By ทีมงาน devdog
อัปเดตล่าสุด: ราคาน้ำมันเบนซิน แก๊สโซฮอล์ และดีเซลวันนี้ (15 มิ.ย. 69) พร้อมแนวโน้มตลาด

อัปเดตล่าสุด: ราคาน้ำมันเบนซิน แก๊สโซฮอล์ และดีเซลวันนี้ (15 มิ.ย. 69) พร้อมแนวโน้มตลาด

เช็กราคาน้ำมันเบนซิน แก๊สโซฮอล์ และดีเซลล่าสุด 15 มิ.ย. 69 จาก ปตท. บางจาก เชลล์ และปั๊มอื่น ๆ พร้อมข้อมูลการปรับลดราคา วางแผนการเดินทางได้เลย!

By ทีมงาน devdog
เจาะลึก! iOS 27 กับ 3 ฟีเจอร์ลับที่ Apple ยังไม่เปิดตัว คาดเตรียมเซอร์ไพรส์กันยายนนี้

เจาะลึก! iOS 27 กับ 3 ฟีเจอร์ลับที่ Apple ยังไม่เปิดตัว คาดเตรียมเซอร์ไพรส์กันยายนนี้

Mark Gurman เผย iOS 27 มี 3 ฟีเจอร์ลับ Siri AI เชื่อมต่อภายนอก, กล้องปรับแต่งได้, หน้าปัด Apple Watch Ultra ใหม่ คาดเปิดตัวพร้อม iPhone 18 เดือน ก.ย. นี้

By ทีมงาน devdog