golang/goroutine 和 swoole/coroutine 协程性能测试对比

栏目: PHP · 发布时间: 7年前

内容简介:协程的一些特性和优点我就不说了,网上很多文章都讲述的很透彻。协程可以理解为纯用户态的线程,其通过协作而不是抢占来进行切换。相对于进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低。开发者可以无感知的用同步的代码编写方式达到异步IO的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护。1、golang::goroutine

协程的一些特性和优点我就不说了,网上很多文章都讲述的很透彻。

协程可以理解为纯用户态的线程,其通过协作而不是抢占来进行切换。相对于进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低。开发者可以无感知的用同步的代码编写方式达到异步IO的效果和性能,避免了传统异步回调所带来的离散的代码逻辑和陷入多层回调中导致代码无法维护。

1、golang::goroutine

最近在学习 go,一些高大上的特性果然是为高并发而生,自带的 net/http 包对请求的处理也透明的放在了协程上下文中,真开箱即用。

server.go

package main

import (
    "fmt"
    "net/http"
    "time"
    "log"
    "runtime"
    "bytes"
    "strconv"
)

func main() {
    // 注册请求 handler
    http.HandleFunc("/", func (responseWrite http.ResponseWriter, request *http.Request) {
        log.Println("goroutine: ", GetGID(), "start")
        // 模拟2秒的IO耗时操作 会发生协程切换
        time.Sleep(2 * time.second)
        // 协程继续执行
        log.Println("goroutine: ", GetGID(), "end")
        // 结束请求
        fmt.Fprintln(responseWrite, "<h1>hello world!</h1>")
    })

    log.Println("server start ...")
    
    http.ListenAndServe(":8081", nil)
}

// 获取 goroutine 的协程 id
func GetGID() uint64 {
    b := make([]byte, 64)
    b = b[:runtime.Stack(b, false)]
    b = bytes.TrimPrefix(b, []byte("goroutine "))
    b = b[:bytes.IndexByte(b, ' ')]
    n, _ := strconv.ParseUint(string(b), 10, 64)
    return n
}

golang 自带的 net/http 包是会自行的创建一个协程去处理请求的,所以阻塞的 2秒 并不会将主进程挂起,主进程仍在不停的接收请求并创建一个协程去处理请求。

2、swoole::coroutine

Swoole在2.0开始内置协程(Coroutine)的能力,提供了具备协程能力IO接口(统一在命名空间SwooleCoroutine*)。

server.php

<?php
// 高并发下多协程也需要一定的内存
ini_set('mermory_limit', '1024M');

$server = new Swoole\Http\Server('127.0.0.1', 8082);

// 工作进程数设为1 这样和 golang 的进程模型基本一致
// swoole worker 默认的 max_coroutine 数为 3000 可根据业务负载自行配置
// @reference https://wiki.swoole.com/wiki/page/950.html
$server->set([
    'worker_num' => 1,
]);

$server->on("start", function ($server) {
    echo "server start ..." . PHP_EOL;
});

// 处理请求
$server->on('request', function ($request, $response) {
    echo "goroutine: " . Swoole\Coroutine::getuid() . " start" . PHP_EOL;
    
    /**
     * 这里我们需要使用 Swoole\Coroutine::sleep() 来模拟IO耗时 触发协程切换
     * 真实的业务场景中你可能使用的是以下协程客户端
     * Coroutine\Client Coroutine\Http\Client Coroutine\Http2\Client
     * Coroutine\Redis Coroutine\Socket Coroutine\MySQL Coroutine\PostgreSQL
     * php 的 sleep() 是没办法触发协程切换的 会被同步阻塞
     * 这也是为什么 swoole 的协程中要使用指定的 IO 客户端才能发挥协程的性能
     */
    Swoole\Coroutine::sleep(2);

    echo "goroutine: " . Swoole\Coroutine::getuid() . " end" . PHP_EOL;
    
    $response->end("<h1>Hello world!</h1>");
});

$server->start();

swoole 的 Server 同 golang 的 net/http 一样的将协程透明化,不过我们在 swoole 中需要使用一些预先提供的方法或客户端才能触发协程切换,进而发挥协程的高性能。

swoole 的各协程客户端: https://wiki.swoole.com/wiki/...

3、ab压测

服务器配置略渣,vsphere上的一台小小自用服务器 1 核 2G,不要在意

golang/goroutine 和 swoole/coroutine 协程性能测试对比

压测 200 并发 5000 请求

ab -c 200 -n 5000 -k http://127.0.0.1:8081
ab -c 200 -n 5000 -k http://127.0.0.1:8082

go

golang/goroutine 和 swoole/coroutine 协程性能测试对比

swoole

golang/goroutine 和 swoole/coroutine 协程性能测试对比

压测 500 并发 5000 请求

ab -c 500 -n 5000 -k http://127.0.0.1:8081
ab -c 500 -n 5000 -k http://127.0.0.1:8082

go

golang/goroutine 和 swoole/coroutine 协程性能测试对比

swoole

golang/goroutine 和 swoole/coroutine 协程性能测试对比

压测 1000 并发 5000 请求

ab -c 1000 -n 5000 -k http://127.0.0.1:8081
ab -c 1000 -n 5000 -k http://127.0.0.1:8082

go

golang/goroutine 和 swoole/coroutine 协程性能测试对比

swoole

golang/goroutine 和 swoole/coroutine 协程性能测试对比

压测 2000 并发 5000 请求

ab -c 2000 -n 5000 -k http://127.0.0.1:8081
ab -c 2000 -n 5000 -k http://127.0.0.1:8082

go

golang/goroutine 和 swoole/coroutine 协程性能测试对比

swoole

golang/goroutine 和 swoole/coroutine 协程性能测试对比

可以通过以上几组数据看出,golang::goroutine 和 swoole::coroutine 两个协程的性能基本没有什么差距,而且协程在高并发下才能更直观的体现出优异的性能。

同样 5000 的请求,200 - 500 - 1000 - 2000 处理耗时越来越小,说明不是我吃不掉,是你发的太慢。当 2000 并发时,我这台 1核 2G 的服务器都能在阻塞 2 秒的场景下跑到 600- 并发。

但 swoole 还是要占更多些的内存,我测试机内存比较小,没办法用 swoole 完美的跑 c10k,内存不够用,没办法创建更多的协程去并发处理请求,但 go 还可以,后面在看下 go::goroutine 是不是占用内存更小吧,先跑一个看看。

go 10k 并发 200k请求

golang/goroutine 和 swoole/coroutine 协程性能测试对比

go 20k 并发 1000k请求

golang/goroutine 和 swoole/coroutine 协程性能测试对比

ab 最大并发模拟量为 20k,仅供参考


以上所述就是小编给大家介绍的《golang/goroutine 和 swoole/coroutine 协程性能测试对比》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

An Introduction to the Analysis of Algorithms

An Introduction to the Analysis of Algorithms

Robert Sedgewick、Philippe Flajolet / Addison-Wesley Professional / 1995-12-10 / CAD 67.99

This book is a thorough overview of the primary techniques and models used in the mathematical analysis of algorithms. The first half of the book draws upon classical mathematical material from discre......一起来看看 《An Introduction to the Analysis of Algorithms》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具