亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

nodejs中使用多線程編程的方法實例

2019-11-20 12:52:18
字體:
來源:轉載
供稿:網友

在以前的博文別說不可能,nodejs中實現sleep中,我向大家介紹了nodejs addon的用法。今天的主題還是addon,繼續挖掘c/c++的能力,彌補nodejs的弱點。

我曾多次提到過nodejs的性能問題。其實就語言本身而言,nodejs的性能還是很高的,雖然不及大多部靜態語言,但差距也并不大;相對其他動態語言而言,速度優勢非常明顯。但為什么我們常常說nodejs不能勝任CPU密集型場景呢?因為由于其單線程特性,對于CPU密集型場景,它并不能充分利用CPU。計算機科學中有一個著名的Amdahl定律:

假設總工作量W,可以分解為兩個部分:只能串行計算的Ws和允許并行計算的Wp。那么,在p個CPU并行計算的情況下,性能上能夠帶來speedup倍的提升。Amdahl定律描述了并行能做到的和不能做到的。它是一種理想情況,實際情況會復雜得多。比如并發很可能會引起資源的爭奪,需要增加各種鎖,從而常常讓并行處于等待狀態;并發還會額外帶來操作系統對線程調度切換的時間開銷,增加Ws。不過,當一項任務中,Wp比Ws大得多,并且有多個CPU核心可供使用時,并行帶來的性能提升是相當可觀的。

好,回到nodejs上。我們設想一個計算場景:計算4000000內的質數數目。這個場景編程實現的時候,以除法運算為主,不涉及內存、對象等操作,理論上能夠確保讓nodejs以相對較快的速度運行,不會落后c太多,便于對比。

javascript尋找質數的方法已經在這篇博客中提供了,直接抄過來:

復制代碼 代碼如下:

function zhishu_js(num) {
    if (num == 1) {
        return false;
    }
    if (num == 2) {
        return true;
    }
    for (var i = 2; i <= Math.sqrt(num); i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
}

再寫一個c語言版本的:

復制代碼 代碼如下:

#include <math.h>

bool zhishu(int num){
    if (num == 1) {
        return false;
    }
    if (num == 2) {
        return true;
    }
    for (int i = 2; i <= sqrt(num); i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
};

在nodejs中,我們用一個從1到4000000的循環來檢索質數;c語言中,我們設置若干個線程,定義count為4000000,每個線程做如下操作要:如果count大于0,則取出count的值,并計算是否為質數,同時將count減1。根據這個思路,javascript版本的很容易寫:

復制代碼 代碼如下:

var count = 0;

for (j = 1; j < 4000000; j++) {
    if(zhishu(j)){
        count++;
    }
}


關鍵難點就是c語言的多線程編程。早期c/c++并沒有考慮并行計算的需求,所以標準庫中并沒有提供多線程支持。而不同的操作系統通常實現也是有區別的。為了避免這種麻煩,我們采用pthread來處理線程。

下載pthread最新版本。由于我對gyp不熟,link依賴lib搞了半天沒搞定,最后我的方式是,直接把pthread的源代碼放到了項目目錄下,并在binding.gyp中把pthread.c添加到源代碼列表中,在編譯項目的時候把pthread也編譯一次。修改后的binding.gyp是這樣的:

復制代碼 代碼如下:

{
  "targets": [
    {
      "target_name": "hello",
      "sources": [ "hello.cc","pthreads/pthread.c" ],
      "include_dirs": [
        "<!(node -e /"require('nan')/")",
        "pthreads"
      ],
      "libraries": ["Ws2_32.lib"]
    }
  ]
}

 當然了,我這種方法很麻煩,如果你們只添加pthread中lib和include目錄的引用,并且不出現依賴問題,那是最好的,就沒有必要用我的方法來做。

那么接下來就進入C/C++多線程的一切了,定義一個線程處理函數:

復制代碼 代碼如下:

pthread_mutex_t lock;

void *thread_p(void *null){
    int num, x=0;
    do{
        pthread_mutex_lock(&lock);
        num=count--;
        pthread_mutex_unlock(&lock);
        if(num>0){
            if(zhishu(num))x++;
        }else{
            break;
        }
    }while(true);
    std::cout<<' '<<x<<' ';
    pthread_exit(NULL);
        return null;
}

 在線程與線程之間,對于count這個變量是相互競爭的,我們需要確保同時只能有一個線程操作count變量。我們通過 pthread_mutex_t lock; 添加一個互斥鎖。當執行 pthread_mutex_lock(&lock); 時,線程檢查lock鎖的情況,如果已鎖定,則等待、重復檢查,阻塞后續代碼運行;如果鎖已釋放,則鎖定,并執行后續代碼。相應的, pthread_mutex_unlock(&lock); 就是解除鎖狀態。

由于編譯器在編譯的同時,進行編譯優化,如果一個語句沒有明確做什么事情,對其他語句的執行也沒有影響時,會被編譯器優化掉。在上面的代碼中,我加入了統計質數數量的代碼,如果不加的話,像這樣的代碼:

復制代碼 代碼如下:

for (int j = 0; j < 4000000; j++) {
    zhishu(j);
}

 是會直接被編譯器跳過的,實際不會運行。

添加addon的寫法已經介紹過了,我們實現從javascript接收一個參數,表示線程數,然后在c中創建指定數量的線程完成質數檢索。完整代碼:

復制代碼 代碼如下:

#include <nan.h>
#include <math.h>
#include <iostream>
#include "pthreads/pthread.h"
#define MAX_THREAD 100
using namespace v8;

int count=4000000;
pthread_t tid[MAX_THREAD];
pthread_mutex_t lock;

void *thread_p(void *null){
    int num, x=0;
    do{
        pthread_mutex_lock(&lock);
        num=count--;
        pthread_mutex_unlock(&lock);
        if(num>0){
            if(zhishu(num))x++;
        }else{
            break;
        }
    }while(true);
    std::cout<<' '<<x<<' ';
    pthread_exit(NULL);
    return null;
}

NAN_METHOD(Zhishu){
    NanScope();
    pthread_mutex_init(&lock,NULL);
    double arg0=args[0]->NumberValue();
    int c=0;
    for (int j = 0; j < arg0 && j<MAX_THREAD; j++) {
        pthread_create(&tid[j],NULL,thread_p,NULL);
    }
    for (int j = 0; j < arg0 && j<MAX_THREAD; j++) {
        pthread_join(tid[j],NULL);
    }
    NanReturnUndefined();
}

void Init(Handle<Object> exports){
    exports->Set(NanSymbol("zhishu"), FunctionTemplate::New(Zhishu)->GetFunction());
}

NODE_MODULE(hello, Init);

 phread_create可以創建線程,默認是joinable的,這個時候子線程受制于主線程;phread_join阻塞住主線程,等待子線程join,直到子線程退出。如果子線程已退出,則phread_join不會做任何事。所以對所有的線程都執行thread_join,可以保證所有的線程退出后才會例主線程繼續進行。

完善一下nodejs腳本:

復制代碼 代碼如下:

var zhishu_c=require('./build/Release/hello.node').zhishu;
function zhishu(num) {
    if (num == 1) {
        return false;
    }
    if (num == 2) {
        return true;
    }
    for (var i = 2; i <= Math.sqrt(num); i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
}

console.time("c");
    zhishu_c(100);
console.timeEnd("c");

console.time("js");
var count=0;
for (j = 1; j < 4000000; j++) {
    if(zhishu(j)){
        count++;
    }
}
console.log(count);
console.timeEnd("js");

 看一下測試結果:

 單線程時,雖然C/C++的運行速度是nodejs的181%,但這個成績我們認為在動態語言中,還是非常不錯的。雙線程時速度提升最明顯,那是因為我的電腦是雙核四線程CPU,這個時候已經可能在使用兩個核心在進行處理。4線程時速度達到最大,此時應該是雙核四線程能達到的極限,當線程再增加時,并不能再提升速度了。上述Amdahl定律中,p已達上限4。再增加線程,會增加操作系統進程調度的時間,增加鎖的時間,盡管同時也能增加對CPU時間的競爭,但總體而言,Ws的增加更加明顯,性能是下降的。如果在一臺空閑的機器上做這個實驗,數據應該會更好一點。

從這個實驗中,我們可以得出這樣的結論,對于CPU密集型的運算,交給靜態語言去做,效率會提高很多,如果計算中較多涉及內存、字符串、數組、遞歸等操作(以后再驗證),性能提升更為驚人。同時,合理地利用多線程能有效地提高處理效率,但并不是線程越多越好,要根據機器的情況合理配置。

對于nodejs本身,的確是不擅長處理CPU密集的任務,但有了本文的經驗,我想,想克服這個障礙,并非什么不可能的事情。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人国产精品av| 成人免费大片黄在线播放| 欧美成人免费小视频| 国产亚洲免费的视频看| 91色精品视频在线| 疯狂做受xxxx高潮欧美日本| 日韩av在线影院| 精品国产31久久久久久| 国产精国产精品| 91精品久久久久久久久久另类| 色吧影院999| 国产mv久久久| 欧美日韩国产限制| 精品久久久久久| 亚洲欧美精品一区二区| 亚洲电影成人av99爱色| 日韩欧美一区二区三区久久| 精品中文字幕久久久久久| 亚洲美女精品久久| 欧美激情视频一区二区三区不卡| 中文字幕亚洲一区| 亚洲视频免费一区| 久久频这里精品99香蕉| 国产成人精品综合久久久| 国产精品久久99久久| 欧美午夜宅男影院在线观看| 国产美女久久精品| 国产精品久久久久久av| 成人网在线视频| 91理论片午午论夜理片久久| 精品久久久久久亚洲国产300| 久久99精品久久久久久噜噜| 国产精品偷伦视频免费观看国产| 国产成人精品一区| 亚洲国产91色在线| 欧美激情精品久久久久久变态| 91精品国产成人| 久久99视频精品| 亚洲理论在线a中文字幕| 亚洲精品一区二区久| 久久久精品2019中文字幕神马| 91精品在线播放| 亚洲а∨天堂久久精品9966| 亚洲国产成人91精品| 在线视频日韩精品| 国产精品国产自产拍高清av水多| 97在线视频免费| 国产日韩在线亚洲字幕中文| 久久精品亚洲精品| 亚洲女人天堂视频| 中文字幕久热精品在线视频| 亚洲美女视频网站| 韩国视频理论视频久久| 中文字幕精品在线| 日本午夜人人精品| 亚洲精品国产精品自产a区红杏吧| 国产日产亚洲精品| 国产精品白丝jk喷水视频一区| 日韩在线欧美在线国产在线| 日本19禁啪啪免费观看www| 精品无人国产偷自产在线| 尤物yw午夜国产精品视频| 国产精品99久久久久久久久| 亚洲精品电影在线| 久久夜色精品亚洲噜噜国产mv| 欧美日韩国产色视频| 国产日韩欧美日韩大片| 中文国产亚洲喷潮| 欧洲一区二区视频| 欧美精品videofree1080p| 国产精品丝袜久久久久久不卡| 亚洲视频视频在线| 国产精品久久电影观看| 成人免费观看a| 91精品国产自产在线老师啪| 一区二区国产精品视频| 欧美激情一区二区三区久久久| 国产主播精品在线| 日韩精品视频免费在线观看| 亚洲午夜精品久久久久久久久久久久| 欧美亚洲一级片| 91在线观看免费高清完整版在线观看| 亚洲欧美综合另类中字| 欧美特级www| 琪琪亚洲精品午夜在线| 菠萝蜜影院一区二区免费| 高清在线视频日韩欧美| 欧美性感美女h网站在线观看免费| 欧美亚洲一级片| 日韩大片免费观看视频播放| 亚洲成人久久久久| 国产欧美日韩亚洲精品| 最新91在线视频| 国产精品一区二区av影院萌芽| 亚洲免费av网址| 久久久久久亚洲精品中文字幕| 热99在线视频| 在线成人免费网站| 揄拍成人国产精品视频| 国产在线观看91精品一区| 视频在线观看一区二区| 久久久日本电影| 国模极品一区二区三区| 日韩中文字幕在线免费观看| 日韩av在线网页| 日韩女优人人人人射在线视频| 中文字幕自拍vr一区二区三区| 性亚洲最疯狂xxxx高清| 国产精品jvid在线观看蜜臀| 一区二区三区高清国产| 欧美日韩日本国产| 日韩有码在线电影| 国产在线精品一区免费香蕉| 国产精品九九九| 欧美成人免费全部| 国产精品吹潮在线观看| 亚洲韩国日本中文字幕| 91国在线精品国内播放| 亚洲男人天堂九九视频| 日韩一二三在线视频播| 国产伦精品一区二区三区精品视频| 欧美性猛交xxxx富婆弯腰| 69av在线播放| 亚洲一区www| 69国产精品成人在线播放| 综合国产在线观看| 久久69精品久久久久久国产越南| 最新69国产成人精品视频免费| 亚洲精品国产美女| 日韩高清有码在线| 国产a级全部精品| 在线电影中文日韩| 国产午夜精品麻豆| 韩国19禁主播vip福利视频| 国产成人精品999| 538国产精品一区二区在线| 久久久伊人欧美| 97碰碰碰免费色视频| 国内成人精品一区| 久久中文字幕在线| 久久久久久亚洲精品不卡| 久久全球大尺度高清视频| 日韩最新中文字幕电影免费看| 国产精品视频网站| 亚洲色图18p| 久久精品国产视频| 日韩亚洲一区二区| 亚洲欧美制服另类日韩| 久久综合久久88| 成人性生交xxxxx网站| 日韩av不卡在线| 狠狠色狠狠色综合日日小说| 国产一区二区三区在线播放免费观看| 欧美美女操人视频| 26uuu另类亚洲欧美日本一| 亚洲国产欧美一区| 国产乱人伦真实精品视频| 性欧美在线看片a免费观看| 国产精品亚洲第一区| 国产乱肥老妇国产一区二| 日韩美女在线看| 久久久视频免费观看| 亚洲第一精品夜夜躁人人躁| 欧美视频第一页|