国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

PHP 混合 Go 協(xié)程并發(fā)

zhaofeihao / 1159人閱讀

摘要:當協(xié)程執(zhí)行權(quán)讓渡回來的時候,把原來的上下文恢復(fù)。說明協(xié)程是并發(fā)的。實際的收益取決于后端的服務(wù)的延遲,如果耗時很長,通過協(xié)程并發(fā)則可以收益明顯。

想法很簡單。通過設(shè)置 runtime.GOMAXPROCS(1) 讓 golang 的進程變成單線程執(zhí)行的。類似python用gevent的效果。然后通過調(diào)度多個協(xié)程實現(xiàn)異步I/O并發(fā)。php作為一個子函數(shù)跑在go的進程內(nèi),php需要yield到其他協(xié)程時,通過回調(diào)到golang函數(shù)來實現(xiàn)。從php里調(diào)用go提供的子函數(shù)時,go保證保存php的當前上下文。當協(xié)程執(zhí)行權(quán)讓渡回來的時候,把原來的php上下文恢復(fù)。關(guān)鍵的代碼在:

// 保存當前協(xié)程上的php上下文
    oldServerCtx := engine.ServerContextGet()
    fmt.Println(oldServerCtx)
    defer engine.ServerContextSet(oldServerCtx)
    oldExecutorCtx := engine.ExecutorContextGet()
    fmt.Println(oldExecutorCtx)
    defer engine.ExecutorContextSet(oldExecutorCtx)
    oldCoreCtx := engine.CoreContextGet()
    fmt.Println(oldCoreCtx)
    defer engine.CoreContextSet(oldCoreCtx)

// 放棄全局的鎖,使得其他的協(xié)程可以開始執(zhí)行php
    engineLock.Unlock()
    defer engineLock.Lock()

ServerContextGet 這幾個函數(shù)是我加的,獲得的是php的(EG/SG/PG)這三個全局context(參見:http://www.cnblogs.com/chance...)。修改過的github.com/deuill/go-php的源代碼在:https://github.com/taowen/go-...

完整的php/go混合協(xié)程的demo:

package main

import (
    "fmt"
    "github.com/deuill/go-php/engine"
    "os"
    "runtime"
    "time"
    "sync"
)

type TestObj struct{}

func newTestObj(args []interface{}) interface{} {
    return &TestObj{}
}
var engineLock *sync.Mutex

func (self *TestObj) Hello() {
    oldServerCtx := engine.ServerContextGet()
    fmt.Println(oldServerCtx)
    defer engine.ServerContextSet(oldServerCtx)
    oldExecutorCtx := engine.ExecutorContextGet()
    fmt.Println(oldExecutorCtx)
    defer engine.ExecutorContextSet(oldExecutorCtx)
    oldCoreCtx := engine.CoreContextGet()
    fmt.Println(oldCoreCtx)
    defer engine.CoreContextSet(oldCoreCtx)
    engineLock.Unlock()
    defer engineLock.Lock()
    time.Sleep(time.Second)
    fmt.Println("sleep done")
}

func main() {
    runtime.GOMAXPROCS(1)
    theEngine, err := engine.New()
    engineLock = &sync.Mutex{}
    if err != nil {
        fmt.Println(err)
    }
    _, err = theEngine.Define("TestObj", newTestObj)
    wg := &sync.WaitGroup{}
    wg.Add(2)
    before := time.Now()
    fmt.Println("1")
    go func() {
        engineLock.Lock()
        defer engineLock.Unlock()
        context1, err := theEngine.NewContext()
        if err != nil {
            fmt.Println(err)
        }
        context1.Output = os.Stdout
        if err != nil {
            fmt.Println(err)
        }
        fmt.Println("1 enter")
        _, err = context1.Eval("$testObj = new TestObj(); $testObj->Hello();")
        fmt.Println("1 back")
        if err != nil {
            fmt.Println(err)
        }
        //theEngine.DestroyContext(context1)
        fmt.Println("1 done")
        wg.Done()
    }()
    fmt.Println("2")
    go func() {
        engineLock.Lock()
        defer engineLock.Unlock()
        context2, err := theEngine.NewContext()
        if err != nil {
            fmt.Println(err)
        }
        if err != nil {
            fmt.Println(err)
        }
        context2.Output = os.Stdout
        fmt.Println("2 enter")
        _, err = context2.Eval("$testObj = new TestObj(); $testObj->Hello();")
        fmt.Println("2 back")
        if err != nil {
            fmt.Println(err)
        }
        //theEngine.DestroyContext(context2)
        fmt.Println("2 done")
        wg.Done()
    }()
    wg.Wait()
    after := time.Now()
    fmt.Println(after.Sub(before))
}

執(zhí)行結(jié)果是

1
2
2 enter
{0x2cf2930 {   0     0 0 0 [0 0 0 0 0]        0 0  1000 [0 0 0 0]} {{  0 16 0x7f682e819780 0 [0 0 0 0 0 0 0] } 0 1 [0 0 0]  } 0 0 0 [0 0 0 0 0 0] {0 0 0 0 0 0 0 0 0 0 0 {0 0} {0 0} {0 0} [0 0 0]} 0x2a00270 0x2a00f60  8388608 0 1 [0 0 0] 0 {8 7 2 [0 0 0 0] 0 0x29f4520 0x29f4520 0x29f4470 0x29f4420  1 0 0 [0 0 0 0 0]}  {0 [0 0 0 0 0 0 0]    } 0 [0 0 0 0 0 0 0]}
{0x7ffd30bac588 {[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 2 0 0 [0 0]} 0x7f682f01b928 {[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 1 0 0 [0 0]} 0x7f682f01b948 [                               ] 0x7f682f01ba60 0x7f682f01b960 0x7f682f167168 0x7f682f01ba88 {64 63 5 [0 0 0 0] 0 0x7f682f1972d8 0x7f682f1972d8 0x7f682f1993f8 0x7f682f1970c8 0x7f682e862d10 0 0 1 [0 0 0 0 0]} {8 0 0 [0 0 0 0] 0    0x7f682f016a00  0 0 1 [0 0 0 0 0]} 0x7ffd30bac590 22527 0 0 [0 0 0 0] 0x7f682f197640 0x29f4f80 0x29f4fd0 0x29f5070  0x2cf2950 0x7f682f1989c0 14 0 1 [0 0 0]   0 1 [0 0 0 0 0 0] {8 0 0 [0 0 0 0] 1    0x7f682f016a00 0x7f682e883140 0 0 1 [0 0 0 0 0]} {8 0 0 [0 0 0 0] 0    0x7f682f016a00 0x7f682e8831d0 1 0 0 [0 0 0 0 0]} 0x7f682f167088 0 [0 0 0 0]   {0 0 } {0 0   0 [0 0 0 0 0 0 0]} {0 0   0 [0 0 0 0 0 0 0]} 0 [0 0 0 0]  0 0 0x29fb2e0   {0x7f682f187030 2 1024 -1 [0 0 0 0]}    [{0x7f682e915050 [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] 0 0 149 8 8 8} {0x7f682e915050 [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] 0 0 149 8 8 8} {0x7f682e915050 [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] 0 0 149 8 8 8}] 0x7f682f167168  {0 [0 0 0 0]  0 [0 0 0 0] 0 0 [0 0 0 0]  0 [0 0 0 0] } 1 [0 0 0 0 0 0 0]  0x7f682f01bde8 895 [0 0 0 0 0 0] [   ]}
{1 [0 0 0 0 0 0 0] 0 0 0 [0 0 0 0 0 0]  0x29ff9a0 17 134217728 -1 0 0 0 1 [0 0 0 0] 1024 0 0 1 [0 0 0 0 0] 0x2a00870  0x2a010a0 0x7f682ecc58b0  0x7f682ecc5c23    2097152   0x2a00180 0x2a00230    {0x7f682ec91aa8 0x7f682ec91aa8} 0x2a00910 {0 0 0 [0 0 0 0] 0      0 0 0 [0 0 0 0 0]} 0 0 0 [0 0 0] {0x2b6dc10 0x2b6dc10 1 8  1 [0 0 0 0 0 0 0] } [0x7f682f197330 0x7f682f197040 0x7f682f197410   0x7f682f1974f0] 0 1 1 [0 0 0 0 0] 0x7f682ec9544b 0x7f682ec9544b 0 0 [0 0 0 0 0 0] 0 [0 0 0 0 0 0 0 0] 1 1 1 1 1 0 1 [0] 0 [0 0 0 0]   0 [0 0 0 0] 0x2cf27c0  0 0 [0 0 0 0 0 0] 64 1000 0 [0 0 0 0 0 0 0] 0x7f682ecc6270 300 0x2a009b0 1 [0 0 0 0 0 0 0]  0 [0 0 0 0 0 0 0]}
1 enter
{0x7f6818000aa0 {   0     0 0 0 [0 0 0 0 0]        0 0  1000 [0 0 0 0]} {{  0 16 0x7f682e819780 0 [0 0 0 0 0 0 0] } 0 1 [0 0 0]  } 0 0 0 [0 0 0 0 0 0] {0 0 0 0 0 0 0 0 0 0 0 {0 0} {0 0} {0 0} [0 0 0]} 0x2a00270 0x2a00f60  8388608 0 1 [0 0 0] 0 {8 7 2 [0 0 0 0] 0 0x29f4520 0x29f4520 0x29f4470 0x29f4420  1 0 0 [0 0 0 0 0]}  {0 [0 0 0 0 0 0 0]    } 0 [0 0 0 0 0 0 0]}
{0x7f682a4cccd8 {[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 2 0 0 [0 0]} 0x7f682f01b928 {[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 1 0 0 [0 0]} 0x7f682f01b948 [                               ] 0x7f682f01ba60 0x7f682f01b960 0x7f682802f110 0x7f682f01ba88 {64 63 5 [0 0 0 0] 0 0x7f682f197a00 0x7f682f197a00 0x7f682f198368 0x7f682f198fa0 0x7f682e862d10 0 0 1 [0 0 0 0 0]} {8 0 0 [0 0 0 0] 0    0x7f682f016a00  0 0 1 [0 0 0 0 0]} 0x7f682a4ccce0 22527 0 0 [0 0 0 0] 0x7f682f197d28 0x29f4f80 0x29f4fd0 0x29f5070  0x2cf2950 0x7f682f1983e8 14 0 1 [0 0 0]   0 1 [0 0 0 0 0 0] {8 0 0 [0 0 0 0] 1    0x7f682f016a00 0x7f682e883140 0 0 1 [0 0 0 0 0]} {8 0 0 [0 0 0 0] 0    0x7f682f016a00 0x7f682e8831d0 1 0 0 [0 0 0 0 0]} 0x7f682802f030 0 [0 0 0 0]   {0 0 } {0 0   0 [0 0 0 0 0 0 0]} {0 0   0 [0 0 0 0 0 0 0]} 0 [0 0 0 0]  0 0 0x29fb2e0   {0x7f682804efd8 2 1024 -1 [0 0 0 0]}    [{0x7f682e915050 [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] 0 0 149 8 8 8} {0x7f682e915050 [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] 0 0 149 8 8 8} {0x7f682e915050 [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] 0 0 149 8 8 8}] 0x7f682802f110  {0 [0 0 0 0]  0 [0 0 0 0] 0 0 [0 0 0 0]  0 [0 0 0 0] } 1 [0 0 0 0 0 0 0]  0x7f682f01bde8 895 [0 0 0 0 0 0] [   ]}
{1 [0 0 0 0 0 0 0] 0 0 0 [0 0 0 0 0 0]  0x29ff9a0 17 134217728 -1 0 0 0 1 [0 0 0 0] 1024 0 0 1 [0 0 0 0 0] 0x2a00870  0x2a010a0 0x7f682ecc58b0  0x7f682ecc5c23    2097152   0x2a00180 0x2a00230    {0x7f682ec91aa8 0x7f682ec91aa8} 0x2a00910 {0 0 0 [0 0 0 0] 0      0 0 0 [0 0 0 0 0]} 0 0 0 [0 0 0] {0x2b6dc10 0x2b6dc10 1 8  1 [0 0 0 0 0 0 0] } [0x7f682f197a58 0x7f682f198ce0 0x7f682f197b38   0x7f682f197c18] 0 1 1 [0 0 0 0 0] 0x7f682ec9544b 0x7f682ec9544b 0 0 [0 0 0 0 0 0] 0 [0 0 0 0 0 0 0 0] 1 1 1 1 1 0 1 [0] 0 [0 0 0 0]   0 [0 0 0 0] 0x2cf27c0  0 0 [0 0 0 0 0 0] 64 1000 0 [0 0 0 0 0 0 0] 0x7f682ecc6270 300 0x2a009b0 1 [0 0 0 0 0 0 0]  0 [0 0 0 0 0 0 0]}
sleep done
1 back
1 done
sleep done
2 back
2 done
1.00099211s

可以看到兩個sleep 1s,最終只用了1.00099211s。說明協(xié)程是并發(fā)的。

一些性能指標。走http調(diào)用后端,在i7-6700k上,用ab -n 100 -c 4 可以跑出這樣的結(jié)果

Requests per second:    3183.70 [#/sec] (mean)
Time per request:       1.256 [ms] (mean)
Time per request:       0.314 [ms] (mean, across all concurrent requests)

如果不用http調(diào)用后端,直接php=>go返回"hello",則可以達到

Requests per second:    10073.54 [#/sec] (mean)
Time per request:       0.397 [ms] (mean)
Time per request:       0.099 [ms] (mean, across all concurrent requests)

這些指標只說明了協(xié)程切換的成本。實際的收益取決于后端的http服務(wù)的延遲,如果耗時很長,通過協(xié)程并發(fā)則可以收益明顯。

這個實驗說明了可以用golang實現(xiàn)一個代替nginx+php-fpm的應(yīng)用服務(wù)器。并且提供了一條從php向golang遷移的平滑遷移路徑。在一個應(yīng)用里混合PHP和Go兩種語言。

并且可以通過提供golang函數(shù)給php調(diào)用的方式實現(xiàn)I/O的異步化。像libcurl這樣的擴展自身是支持異步回調(diào)的,只是php是同步的所以只給php暴露了同步的execute。有了Golang之后,可以把execute變成對異步execute+callback的包裝,從而實現(xiàn)基于協(xié)程的調(diào)度。

參考資料:

https://wiki.php.net/internal...

http://www.cunmou.com/phpbook...

http://www.phpinternalsbook.c...

http://www.php-internals.com/...

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/21976.html

相關(guān)文章

  • PHP 協(xié)程Go + Chan + Defer

    摘要:為語言提供了強大的協(xié)程編程模式。提供的協(xié)程語法借鑒自,在此向開發(fā)組致敬協(xié)程可以與很好地互補。并發(fā)執(zhí)行使用創(chuàng)建協(xié)程,可以讓和兩個函數(shù)變成并發(fā)執(zhí)行。協(xié)程需要拿到請求的結(jié)果。 Swoole4為PHP語言提供了強大的CSP協(xié)程編程模式。底層提供了3個關(guān)鍵詞,可以方便地實現(xiàn)各類功能。 Swoole4提供的PHP協(xié)程語法借鑒自Golang,在此向GO開發(fā)組致敬 PHP+Swoole協(xié)程可以與...

    nidaye 評論0 收藏0
  • 聊聊 2018 年后端技術(shù)趨勢

    摘要:現(xiàn)在在后端業(yè)務(wù)開發(fā)編程方面,技術(shù)力量強的團隊已經(jīng)開始將技術(shù)棧從同步模式切換為異步了。使用這些技術(shù)方案是無法兼容已有程序的。影響了異步回調(diào)技術(shù)棧的普及。將會成為未來后端開發(fā)領(lǐng)域的主流技術(shù)方案。 今天太忙,少寫一點,后面再補充。 異步模式 Go 語言越來越熱門,很多大型互聯(lián)網(wǎng)公司后端正在轉(zhuǎn)向 GO 。Java 圈知名的服務(wù)化框架 Dubbo 也宣布轉(zhuǎn)型異步模式。這是一個大趨勢,異步模式已經(jīng)...

    Miyang 評論0 收藏0
  • Easyswoole 源碼學習和個人解析 目錄

    摘要:易用穩(wěn)定,本次想通過對的學習和個人解析,吸收框架的思想和設(shè)計知識,加強自己對的認知和理解。當然,筆者能力水平有限,后續(xù)的文章如有錯誤,還請指出和諒解。目錄如下后續(xù)添加文章都會記錄在此服務(wù)啟動過程以及主體設(shè)計流程源碼解析 前言 swoole是什么?官網(wǎng)的原話介紹是這樣的: Swoole 使用純 C 語言編寫,提供了 PHP 語言的異步多線程服務(wù)器,異步 TCP/UDP 網(wǎng)絡(luò)客戶端,異步 ...

    CoXie 評論0 收藏0
  • Swoole4.x探究之多進程TCP協(xié)程服務(wù)實現(xiàn)

    摘要:有研究過框架的同學就會發(fā)現(xiàn),其實最核心的,就是用了拓展加上拓展來實現(xiàn)其底層的網(wǎng)絡(luò)服務(wù)和多進程調(diào)度。我們在模式下,測試起五個進程主進程要等待回收我們,這樣就很簡單的實現(xiàn)了一個多進程的協(xié)程服務(wù)。 有研究過Workman框架的同學就會發(fā)現(xiàn),其實workman最核心的,就是用了php socket拓展加上pcntl拓展來實現(xiàn)其底層的網(wǎng)絡(luò)服務(wù)和多進程調(diào)度。那我們今天就來探討如何使用Swoole的...

    ad6623 評論0 收藏0
  • PHP下用Swoole實現(xiàn)Actor并發(fā)模型

    摘要:協(xié)程與信箱得益于,我們可以基于的協(xié)程與快速實現(xiàn)一個信箱模式調(diào)度。樣例代碼比如在一個聊天室中,我們可以定義一個房間模型。 什么是Actor? Actor對于PHPer來說,可能會比較陌生,寫過Java的同學會比較熟悉,Java一直都有線程的概念(雖然PHP有Pthread,但不普及),它是一種非共享內(nèi)存的并發(fā)模型,每個Actor內(nèi)的數(shù)據(jù)獨立存在,Actor之間通過消息傳遞的形式進行交互調(diào)...

    GeekQiaQia 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<