国产+高潮+在线,国产 av 仑乱内谢,www国产亚洲精品久久,51国产偷自视频区视频,成人午夜精品网站在线观看

golang workerman webman swoole壓測對比

songsong

看到嗶哩嗶哩有個視頻對比golang和webman helloword壓力測試性能,webman比goloang低了很多,低我理解,golang畢竟多線程自帶協(xié)程,而且webman是框架,golang是http標(biāo)準(zhǔn)庫,不在一個層次,但是感覺不會低這么多才對。還有我覺得應(yīng)該是golang的http標(biāo)準(zhǔn)庫和workerman對比才公平。所以我特地買了臺aliyun服務(wù)器測試下,順便把swoole workerman也壓測了下,結(jié)果也發(fā)到了群里,既然測試了就記錄下來給大家參考下,代碼都有大家可以自行測試。

環(huán)境配置:

4核(vCPU) 4 GiB Ubuntu 20.04 64位
PHP 7.4.3
Go version go1.13.8 linux/amd64

壓測命令

ab -n100000 -c200 http://127.0.0.1:xxx/ 沒開keepalive
ab -n100000 -c200 -k http://127.0.0.1:xxx/ 開了keepalive

進(jìn)程數(shù)(線程數(shù)數(shù)):

對go不熟悉,不知道go怎么開多進(jìn)程,為了公平起見我默認(rèn)workerman webman swoole 全部1個進(jìn)程,go就是教程里的helloword代碼,應(yīng)該也是一個進(jìn)程,是不是多線程我不知道。

先貼結(jié)果:

沒開keepalive 開了keepalive
golang 19995 98546
workerman 30120 125986
webman 29301 85938
swoole 25836 73304
swoole+協(xié)程 27093 54596

結(jié)果是workeman壓測性能高于golang,webman短連接高于golang,keepalive長連接略低于golang。
swoole短連接高于golang,keepalive低于golang。workerman和webman不管是短連接還是keepliave都高于swoole。

go代碼

package main

import (
    "net/http"
)

func handler(w http.ResponseWriter,r *http.Request) {
   w.Write([]byte("hello"))
}

func main() {
    http.HandleFunc("/",handler)
    http.ListenAndServe(":8080",nil)
}

workerman代碼

require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
$worker = new Worker('http://0.0.0.0:12345');
$worker->onMessage = function($connection, $request)
{
     // 不加-k參數(shù)時(shí)要用close才行?
     $connection->close('hello');
};
Worker::runAll();
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
$worker = new Worker('http://0.0.0.0:12345');
$worker->onMessage = function($connection, $request)
{
    // 不加-k時(shí)用send
     $connection->send('hello');
};
Worker::runAll();

workerman這里不太好,ab測試時(shí)-k 參數(shù)需要自己區(qū)別處理,所以需要兩個腳本

webman代碼

<?php
namespace app\controller;
use support\Request;
class Index
{
    public function index(Request $request)
    {
        return 'hello';
    }
}

swoole代碼

<?php
$http = new Swoole\Http\Server('0.0.0.0', 12346, SWOOLE_BASE);
$http->on('Request', function ($request, $response) {
    $response->end('hello');
});
$http->start();

swoole協(xié)程代碼

<?php
use Swoole\Coroutine\Http\Server;
use function Swoole\Coroutine\run;

run(function () {
    $server = new Server('127.0.0.1', 9502, false);
    $server->handle('/', function ($request, $response) {
        $response->end("hello");
    });
    $server->start();
});

不開keep-alive結(jié)果截圖:

?截圖
?截圖
?截圖
?截圖
?截圖

開keep-alive結(jié)果截圖

?截圖
?截圖
?截圖
?截圖
?截圖

最后

我知道肯定會有人說helloword壓測沒有意義,但是我覺得還有一定意義的,畢竟代表了框架的極限性能啊。
https://learnku.com/laravel/t/63523
另外這里也有一個golang框架與webman的比較,帶簡單業(yè)務(wù)的,大家也可以參考的

14434 12 5
12個評論

魯達(dá)

支持一下

  • 暫無評論
Tinywan

群主:我這里只開一個進(jìn)程 helloworld 壓測QPS達(dá)到10萬左右,其它框架包括c寫的擴(kuò)展,只開一個進(jìn)程QPS最多6萬多。
Intel Core i7 處理器,php7.3。http://wtbis.cn/q/5328#reply_11278

  • 暫無評論
魯達(dá)


親測單進(jìn)程11w++

  • 暫無評論
admin

hellword不能代表什么,但是連helloword都不行,那...

第二,框架選擇并不是最先進(jìn)最好,而是最適合團(tuán)隊(duì)的,團(tuán)隊(duì)易用性,協(xié)作,門檻等等。
許多知名的軟件依然是最穩(wěn)定的,而不是最先進(jìn)的

chaz6chez

這里我有必要說一下,PHP好在開發(fā)效率上,綜合下來,性能夠用、開發(fā)迅速;

golang的http庫更像php-fpm,fast-http在地位上有點(diǎn)類似workerman,golang的web開發(fā)框架里利用了http-fast且支持fork多進(jìn)程的框架fiber,還有個evio庫和gnet庫是類似于workerman但更低層,更像一個libevent、libuv、libev

比來比去沒用,用適合的語言干適合的事,高效完成任務(wù)工作,才是應(yīng)該干的事

  • chaz6chez 2022-05-14

    感興趣的人可以試一下gnet網(wǎng)絡(luò)庫

a6965921

現(xiàn)在不是流行協(xié)程+epoll嗎

  • 暫無評論
shicaijun

你這個測試不具備實(shí)際的參考意義,真實(shí)的web應(yīng)用業(yè)務(wù)場景是io密集型的,io操作是影響性能的關(guān)鍵,我在真實(shí)業(yè)務(wù)的測試結(jié)果是golang(gin)>swoole(hyperf)>workerman(webman),不信你可以試試,在一個接口中查幾次數(shù)據(jù)庫,插入或修改數(shù)據(jù),然后寫入一條日志,協(xié)程在處理io機(jī)密性操作還是有優(yōu)勢的,阻塞了會自動切換,要不然swoole花這么多精力搞個協(xié)程有什么意義呢

  • chaz6chez 2022-12-01

    協(xié)程不具備并發(fā)能力,協(xié)程只是調(diào)度,協(xié)程需要結(jié)合線程,swoole是單線程,golang是多線程;swoole和libco應(yīng)該有淵源關(guān)系;
    另外您所謂的真實(shí)業(yè)務(wù)也需要建立在這幾次查詢數(shù)據(jù)庫和插入及修改是否是原子性、是否有關(guān)聯(lián)等前提下,順帶一提,gin+gorm的性能其實(shí)不如webman和hyperf;在重查詢的實(shí)際項(xiàng)目中g(shù)orm+gin的組合的結(jié)果大約是hyperf、webman的80%,在重更新的實(shí)際項(xiàng)目中大約是hyperf、webman的105%左右,前提是webman使用常駐單例的數(shù)據(jù)庫連接。

  • chaz6chez 2022-12-01

    這個實(shí)際項(xiàng)目中還需要考慮是否有過重的json序列化需求,如果結(jié)合json序列化,golang所謂的性能及開發(fā)效率還要大打折扣

  • chaz6chez 2022-12-01

    如果喜歡golang,我比較推薦一個基于fasthttp的框架fiber,這個框架包含了高性能orm及周邊插件;如果是涉及到游戲服務(wù)開發(fā),我推薦gnet網(wǎng)絡(luò)框架。

  • payne 2022-12-07

    如果請求中有需要訪問第三方接口的情況,比如2s才返回結(jié)果,那么webman的性能應(yīng)該就不如自帶協(xié)程的golang了吧,不阻塞的情況下webman性能確實(shí)不錯

  • chaz6chez 2022-12-08

    類似的,golang用的線程池,和worker用多進(jìn)程差不太多,線程更方便管理和彈性,但開多了一樣的,區(qū)別不大;實(shí)際上整個生命周期屬于阻塞隊(duì)列

  • army 2023-03-07

    chaz6chez 說的很對,golang在重業(yè)務(wù)下很糟糕,我們將php項(xiàng)目轉(zhuǎn)成了go,邏輯照搬,跑起來很差,fiber比gin要強(qiáng)很多,兩個框架我們都上了,最后放棄go了

  • Tinywan 2023-03-07

    @army 為什么?

  • army 2023-03-07

    @Tinywan 初步斷定為json的問題,起初用自帶的庫能干到CPU80%,換成sonic后好了很多,但還是不理想,還不如phpfpm, 其實(shí)qps500不算大,但是go表現(xiàn)真的不佳,不帶業(yè)務(wù)或者業(yè)務(wù)小確實(shí)很流弊。

  • Tinywan 2023-03-07

    好吧!沒用過go,有webman,基本夠了,webman+fpm完全夠用了

  • army 2023-03-07

    花了幾天時(shí)間也用workerman重構(gòu)了,今天在本地帶業(yè)務(wù)壓測,是原來php-fpm的6倍,感覺很棒,看線上效果了

  • Tinywan 2023-03-08

    可以的

  • a6965921 2023-04-18

    webman夠用了 多花點(diǎn)精力在數(shù)據(jù)庫上

  • zpw 2023-11-29

    協(xié)程不具備并發(fā)這不是瞎扯嘛

從這個我感覺就只能說明golang不用多線程并且線程數(shù)一樣是比不過,但是如果golang用多線程,并且多進(jìn)程情況下肯定更快

  • 暫無評論
wasoncheung

沒有可比性,我用jmeter深度測試過workerman和springboot 純hello world 前者是快,原因在于 wm的request,session等等組件的封裝其實(shí)很原生,做的并不多。而主流的框架,對請求要進(jìn)行很多業(yè)務(wù)的封裝,比如依賴注入,響應(yīng)類型的自動處理,aop切面等等 一系列的業(yè)務(wù)。

  • 暫無評論
排骨蘇

我有個項(xiàng)目使用go開發(fā)的,目前正常使用中,在我本地調(diào)試 ,同樣的請求同樣的邏輯,go是10ms 而webman是25ms左右,我挺想把go改成webman的(已經(jīng)重構(gòu)10%),因?yàn)間o我不太熟悉,開發(fā)速度很慢,也受不了不停的err判斷,但是說句實(shí)在話,速度真的比webman 要快很多,webman已經(jīng)開啟了常駐內(nèi)存

  • 排骨蘇 2023-06-19

    而且go的base64解密有問題,=號如果沒處理好變成%3D ,就解不出來,php沒問題,寫一句一個err,簡直一萬個臥槽

jonsan

先說結(jié)論

都不使用orm的情況下使用sql查詢
webman(1.78萬QPS)>swoole(1.30萬QPS)>gin(0.80萬QPS)
結(jié)果與第三方techempower壓測跑分百分比基本一致
截圖

硬件

4核4G阿里云,ubuntu 22.04 64位

壓測命令

ab -n100000 -c100 -k http://127.0.0.1:8787/user # webman
ab -n100000 -c100 -k http://127.0.0.1:8080/user # go
ab -n100000 -c100 -k http://127.0.0.1:9090      # swoole

環(huán)境

PHP 8.1
swoole 5.0.3
go 1.20.5

webman
進(jìn)程數(shù) cpu*4,阻塞調(diào)用無連接池

swoole
進(jìn)程數(shù) 4,協(xié)程+連接池

go(gin)
多線程+協(xié)程+連接池

業(yè)務(wù)

隨機(jī)從user表查詢一條記錄json形式返回給客戶端。用戶表10萬條記錄。

壓測結(jié)果

webman
截圖

swoole
截圖

go(gin)
截圖

代碼

webman

<?php
namespace app\controller;

use support\Db;
use support\Request;
use app\model\User;
use PDO;

class UserController
{
    public function index()
    {
        $pdo = $this->getPdo();
        $stmt = $pdo->prepare("SELECT * FROM user WHERE id = :id");
        $id = rand(1, 100000);
        $stmt->bindParam(":id", $id, PDO::PARAM_INT);
        $stmt->execute();

        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        return json($result);
    }

    public function table()
    {
        $id = rand(1, 100000);
        return json(Db::table('user')->find($id));
    }

    public function model()
    {
        $id = rand(1, 100000);
        return json(User::find($id));
    }

    protected function getPdo()
    {
        static $pdo;
        if (!$pdo) {
            $db = config('database.connections.mysql.database');
            $username = config('database.connections.mysql.username');
            $password = config('database.connections.mysql.password');
            $host = config('database.connections.mysql.host');
            $dsn = "mysql:host=$host;dbname=$db";
            $pdo = new PDO($dsn, $username, $password);
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        return $pdo;
    }

}

swoole

<?php
use Swoole\Database\PDOPool;
use Swoole\Database\PDOConfig;
use Swoole\Coroutine;

//Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]);
\Swoole\Runtime::enableCoroutine();

$http = new Swoole\Http\Server('0.0.0.0', 9090, SWOOLE_BASE);
$http->set([
    'worker_num' => 4
]);
$http->on('Request', function ($request, $response) {
    static $pool;
    if (!$pool) {
        $pool = new PDOPool((new PDOConfig)
            ->withHost('127.0.0.1')
            ->withPort(3306)
            ->withDbName('bench')
            ->withCharset('utf8mb4')
            ->withUsername('root')
            ->withPassword('123456'),
            2
        );
    }

    $pdo = $pool->get();
    $statement = $pdo->prepare('select * from user where id=?');
    $id = rand(1, 100000);
    $statement->execute([$id]);
    $result = $statement->fetchAll();
    $pool->put($pdo);
    $response->end(json_encode($result[0]));
});

$http->start();

go(gin)

import (
        "database/sql"
//      "fmt"
        "log"
        "math/rand"
        "net/http"
        "time"

        "github.com/gin-gonic/gin"
        _ "github.com/go-sql-driver/mysql"
)

func main() {
        // 創(chuàng)建數(shù)據(jù)庫連接池
        db, err := sql.Open("mysql", "root:P@ssword@tcp(localhost:3306)/bench?parseTime=true")
        if err != nil {
                log.Fatal(err)
        }
        defer db.Close()

        // 設(shè)置連接池參數(shù)
        db.SetMaxOpenConns(100)
        db.SetMaxIdleConns(10)
        db.SetConnMaxIdleTime(20 * time.Second)

        gin.SetMode(gin.ReleaseMode)

        // 創(chuàng)建Gin路由
        r := gin.New()

        // 注冊接口
        r.GET("/user", func(c *gin.Context) {
                // 隨機(jī)生成id
                id := rand.Intn(100000) + 1

                // 查詢用戶數(shù)據(jù)
                var name, gender string
                var age int
                err := db.QueryRow("SELECT name, gender, age FROM user WHERE id = ?", id).Scan(&name, &gender, &age)
                if err != nil {
                        c.JSON(http.StatusInternalServerError, gin.H{"error": "查詢用戶數(shù)據(jù)失敗"})
                        return
                }

                // 構(gòu)造響應(yīng)數(shù)據(jù)
                user := gin.H{
                        "id":     id,
                        "name":   name,
                        "gender": gender,
                        "age":    age,
                }

                // 返回JSON響應(yīng)
                c.JSON(http.StatusOK, user)
        })

        // 啟動HTTP服務(wù)器
        err = r.Run(":8080")
        if err != nil {
                log.Fatal(err)
        }
}

生成user表的代碼

<?php

// 連接到MySQL數(shù)據(jù)庫
$mysqli = new mysqli("127.0.0.1", "root", "P@ssword");

// 檢查連接是否成功
if ($mysqli->connect_error) {
    die("連接數(shù)據(jù)庫失敗: " . $mysqli->connect_error);
}

// 創(chuàng)建數(shù)據(jù)庫
$createDbQuery = "CREATE DATABASE IF NOT EXISTS bench";
if ($mysqli->query($createDbQuery) !== TRUE) {
    die("創(chuàng)建數(shù)據(jù)庫失敗: " . $mysqli->error);
}

// 選擇數(shù)據(jù)庫
$mysqli->select_db("bench");

// 創(chuàng)建user表
$createTableQuery = "CREATE TABLE IF NOT EXISTS user (
    id INT(11) AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    gender VARCHAR(10) NOT NULL,
    age INT(11) NOT NULL,
    avatar VARCHAR(255) NOT NULL,
    phone VARCHAR(20) NOT NULL,
    email VARCHAR(255) NOT NULL
)";
if ($mysqli->query($createTableQuery) !== TRUE) {
    die("創(chuàng)建表失敗: " . $mysqli->error);
}

// 填充數(shù)據(jù)
$insertQuery = "INSERT INTO user (name, gender, age, avatar, phone, email) VALUES (?, ?, ?, ?, ?, ?)";
$statement = $mysqli->prepare($insertQuery);

// 生成隨機(jī)數(shù)據(jù)并插入表中
for ($i = 1; $i <= 100000; $i++) {
        $rand = mt_rand(100000000, 999999999);
    $name = "User " . $rand;
    $gender = ($rand % 2 == 0) ? "Male" : "Feml";
    $age = mt_rand(18, 60);
    $avatar = "avatar_" . $rand . ".jpg";
    $phone = "1234567890";
    $email = "user" . $rand . "@example.com";

    $statement->bind_param("ssisss", $name, $gender, $age, $avatar, $phone, $email);
    $statement->execute();
}

// 關(guān)閉連接
$statement->close();
$mysqli->close();

echo "數(shù)據(jù)庫bench已創(chuàng)建并填充10萬條數(shù)據(jù)。";

techempower 第三方壓測數(shù)據(jù)

另外附上第三方壓測數(shù)據(jù),感覺他們壓測的更專業(yè)
https://www.techempower.com/benchmarks/#section=data-r21&hw=ph&test=db&l=zijnjz-6bj&a=2&f=1ekg-cbcw-2t4w-27wr68-pc0-iv9slc-0-1ekgw-39g-kxs00-o0zk-5jsemh-2x8doc-2

一次數(shù)據(jù)庫查詢
截圖

多次數(shù)據(jù)庫查詢
截圖

數(shù)據(jù)庫查詢加更新
截圖

數(shù)據(jù)庫更新
截圖

不帶業(yè)務(wù)的helloworld
截圖

其它說明

同時(shí)我測試了webman下使用原生PDO和使用orm的性能差別

如果使用原生PDO
webman QPS為1.78萬

如果使用laravel的Db::table()
webman QPS降到 0.94萬QPS

如果使用laravel的Model
webmanQPS降到 0.72萬QPS

可見,orm庫對性能影響很大,性能最多相差2倍多。
可能這就是為什么有人測試webman 高于 gin,有人測試webman低于gin,因?yàn)闆]有在同一個層面去壓測。
webman 1.78W QPS 對比 go(gin)的0.80W QPS 是合理的對比。

不過不管怎么樣,webman性能不輸go的框架,甚至一些情況下比go的框架性能好很多。
當(dāng)然性能不是唯一指標(biāo),簡單、好用、穩(wěn)定、社區(qū)活躍、性能好這幾點(diǎn)要找到一個平衡。
至于框架間性能那點(diǎn)區(qū)別,加點(diǎn)硬件就完事了,早點(diǎn)下班它不香嗎?

admin

試試go也和workerman一樣使用事件庫,而不是他內(nèi)置的

package main

import (
    "fmt"
    "log"
    "net"
    "os"

    "golang.org/x/sys/unix"
)

const (
    EPOLLIN       = 0x001
    EPOLLOUT      = 0x004
    EPOLLET       = 0x80000000
    MaxConnections = 1024
    BufferSize    = 1024
)

func main() {
    listener, err := net.Listen("tcp4", ":8080")
    if err != nil {
        log.Fatal(err)
    }

    fd, err := syscall.EpollCreate1(0)
    if err != nil {
        log.Fatal(err)
    }

    events := make([]syscall.EpollEvent, MaxConnections)
    event := syscall.EpollEvent{
        Events: EPOLLIN | EPOLLET,
        Fd:     int32(listener.(*net.TCPListener).Fd()),
    }

    if err := syscall.EpollCtl(fd, syscall.EPOLL_CTL_ADD, int(listener.(*net.TCPListener).Fd()), &event); err != nil {
        log.Fatal(err)
    }

    buffer := make([]byte, BufferSize)
    for {
        nevents, err := syscall.EpollWait(fd, events, -1)
        if err != nil {
            log.Fatal(err)
        }

        for ev := 0; ev < nevents; ev++ {
            if int(events[ev].Fd) == int(listener.(*net.TCPListener).Fd()) {
                conn, err := listener.Accept()
                if err != nil {
                    log.Fatal(err)
                }

                fmt.Println("Accepted connection from", conn.RemoteAddr())

                event := syscall.EpollEvent{
                    Events: EPOLLIN | EPOLLOUT | EPOLLET,
                    Fd:     int32(conn.(*net.TCPConn).Fd()),
                }

                if err := syscall.EpollCtl(fd, syscall.EPOLL_CTL_ADD, int(conn.(*net.TCPConn).Fd()), &event); err != nil {
                    log.Fatal(err)
                }
            } else {
                conn, err := net.FileConn(os.NewFile(uintptr(events[ev].Fd), ""))
                if err != nil {
                    log.Fatal(err)
                }
                defer conn.Close()

                var n int
                n, err = conn.Read(buffer)
                if err != nil {
                    log.Fatal(err)
                }

                response := []byte("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nHello World\n")
                _, err = conn.Write(response)
                if err != nil {
                    log.Fatal(err)
                }

                syscall.EpollCtl(fd, syscall.EPOLL_CTL_DEL, int(events[ev].Fd), nil)
            }
        }
    }
}
  • 暫無評論
年代過于久遠(yuǎn),無法發(fā)表評論

songsong

220
積分
0
獲贊數(shù)
0
粉絲數(shù)
2022-05-10 加入
??