文档章节

golang思考之运行速度之channel

 学习吧
发布于 2015/10/20 22:45
字数 940
阅读 111
收藏 1
点赞 0
评论 0

golang channel测速程序:

package main

import (
    "runtime"
)

var PC_DATA_SIZE int 

var chEnd chan int 

func producer(ch chan byte) {
    for i := 0; i < PC_DATA_SIZE; i++ {
        ch <- 0
    }   
    chEnd <- 0
}

func consumer(ch chan byte) {
    for i := 0; i < PC_DATA_SIZE; i++ {
        <-ch
    }   
    chEnd <- 0
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    PC_DATA_SIZE = 10000000
    chEnd = make(chan int)
    ch := make(chan byte, 1024)
    go producer(ch)
    go consumer(ch)
    <-chEnd
    <-chEnd
}

C语言有锁并发队列:

#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#define PC_DATA_SIZE        10000000

typedef struct Queue{
    uint8_t *data;
    int front;
    int rear;
    int size;
    int maxSize;
    pthread_mutex_t mutex;
    pthread_cond_t empty;
    pthread_cond_t fill;
}Queue;

Queue *QueueInit(int maxSize){
    Queue *queue=malloc(sizeof(Queue));
    if(queue==NULL){
        perror("malloc");
        return NULL;
    }   
    queue->data=malloc(maxSize);
    if(queue->data==NULL){
        perror("malloc");
        free(queue);
        return NULL;
    }   
    queue->front=0;
    queue->rear=0;
    queue->size=0;
    queue->maxSize=maxSize;
    if(pthread_mutex_init(&queue->mutex,NULL)!=0){
        perror("pthread_mutex_init");
        return NULL;
    }
    if(pthread_cond_init(&queue->empty,NULL)!=0){
        perror("pthread_cond_init");
        return NULL;
    }
    if(pthread_cond_init(&queue->fill,NULL)!=0){
        perror("pthread_cond_init");
        return NULL;
    }
    return queue;
}

int QueueIn(Queue *queue,uint8_t data){
    if(pthread_mutex_lock(&queue->mutex)!=0){
        perror("pthread_mutex_lock");
        return -1;
    }
    while(queue->size==queue->maxSize){
        if(pthread_cond_wait(&queue->empty,&queue->mutex)!=0){
            perror("pthread_cond_wait");
            return -1;
        }
    }
    queue->data[queue->front]=data;
    ++queue->front;
    queue->front%=queue->maxSize;
    ++queue->size;
    if(pthread_cond_signal(&queue->fill)!=0){
        perror("pthread_cond_signal");
    }
    if(pthread_mutex_unlock(&queue->mutex)!=0){
        perror("pthread_mutex_unlock");
        return -1;
    }
    return 0;
}

int QueueOut(Queue *queue,uint8_t *data){
    if(pthread_mutex_lock(&queue->mutex)!=0){
        perror("pthread_mutex_lock");
        return -1;
    }
    while(queue->size==0){
        if(pthread_cond_wait(&queue->fill,&queue->mutex)!=0){
            perror("pthread_cond_wait");
            return -1;
        }
    }
    *data=queue->data[queue->rear];
    ++queue->rear;
    queue->rear%=queue->maxSize;
    --queue->size;
    if(pthread_cond_signal(&queue->empty)!=0){
        perror("pthread_cond_signal");
    }
    if(pthread_mutex_unlock(&queue->mutex)!=0){
        perror("pthread_mutex_unlock");
        return -1;
    }
    return 0;
}

void QueueDestroy(Queue *queue){
    if(pthread_cond_destroy(&queue->fill)!=0){
        perror("pthread_cond_destroy");
    }
    if(pthread_cond_destroy(&queue->empty)!=0){
        perror("pthread_cond_destroy");
    }
    if(pthread_mutex_destroy(&queue->mutex)!=0){
        perror("pthread_mutex_destroy");
    }
    free(queue->data);
    free(queue);
}

void *producerStart(void *arg){
    Queue *queue=(Queue*)arg;
    int64_t sum=0;
    int i;
    for(i=0;i<PC_DATA_SIZE;++i){
        uint8_t data=(uint8_t)i;
        if(QueueIn(queue,data)<0){
            perror("QueueIn");
            return NULL;
        }
        sum+=data;
    }
    printf("producerStart sum %ld\n",sum);
    return NULL;
}

void *consumerStart(void *arg){
    Queue *queue=(Queue*)arg;
    int64_t sum=0;
    int i;
    for(i=0;i<PC_DATA_SIZE;++i){
        uint8_t data;
        if(QueueOut(queue,&data)<0){
            perror("QueueOut");
            return NULL;
        }
        sum+=data;
    }
    printf("consumerStart sum %ld\n",sum);
    return NULL;
}

int main(void){
    Queue *queue=QueueInit(1024);
    if(queue==NULL){
        perror("QueueInit");
        return -1;
    }
    pthread_t producerTId;
    if(pthread_create(&producerTId,NULL,producerStart,queue)!=0){
        perror("pthread_create");
        return -1;
    }
    pthread_t consumerTId;
    if(pthread_create(&consumerTId,NULL,consumerStart,queue)!=0){
        perror("pthread_create");
        return -1;
    }
    pthread_join(producerTId,NULL);
    pthread_join(consumerTId,NULL);
    QueueDestroy(queue);
    return 0;
}

C语言无锁并发队列:

#include <pthread.h>
#include <semaphore.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#define PC_DATA_SIZE        10000000

typedef struct Queue{
    uint8_t *data;
    int front;
    int rear;
    int maxSize;
    sem_t empty;
    sem_t fill;
}Queue;

Queue *QueueInit(int maxSize){
    Queue *queue=malloc(sizeof(Queue));
    if(queue==NULL){
        perror("malloc");
        return NULL;
    }   
    queue->data=malloc(maxSize);
    if(queue->data==NULL){
        perror("malloc");
        free(queue);
        return NULL;
    }   
    queue->front=0;
    queue->rear=0;
    queue->maxSize=maxSize;
    if(sem_init(&queue->empty,0,queue->maxSize)<0){
        perror("sem_init");
        return NULL;
    }   
    if(sem_init(&queue->fill,0,0)<0){
        perror("sem_init");
        return NULL;
    }
    return queue;
}

int QueueIn(Queue *queue,uint8_t data){
    if(sem_wait(&queue->empty)<0){
        perror("sem_wait");
        return -1;
    }
    queue->data[queue->front]=data;
    ++queue->front;
    queue->front%=queue->maxSize;
    if(sem_post(&queue->fill)<0){
        perror("sem_post");
        return -1;
    }
    return 0;
}

int QueueOut(Queue *queue,uint8_t *data){
    if(sem_wait(&queue->fill)<0){
        perror("sem_wait");
        return -1;
    }
    *data=queue->data[queue->rear];
    ++queue->rear;
    queue->rear%=queue->maxSize;
    if(sem_post(&queue->empty)<0){
        perror("sem_post");
        return -1;
    }
    return 0;
}

void QueueDestroy(Queue *queue){
    if(sem_destroy(&queue->empty)<0){
        perror("sem_destroy");
    }
    if(sem_destroy(&queue->fill)<0){
        perror("sem_destroy");
    }
    free(queue->data);
    free(queue);
}

void *producerStart(void *arg){
    Queue *queue=(Queue*)arg;
    int64_t sum=0;
    int i;
    for(i=0;i<PC_DATA_SIZE;++i){
        uint8_t data=(uint8_t)i;
        if(QueueIn(queue,data)<0){
            perror("QueueIn");
            return NULL;
        }
        sum+=data;
    }
    printf("producerStart sum %ld\n",sum);
    return NULL;
}

void *consumerStart(void *arg){
    Queue *queue=(Queue*)arg;
    int64_t sum=0;
    int i;
    for(i=0;i<PC_DATA_SIZE;++i){
        uint8_t data;
        if(QueueOut(queue,&data)<0){
            perror("QueueOut");
            return NULL;
        }
        sum+=data;
    }
    printf("consumerStart sum %ld\n",sum);
    return NULL;
}

int main(void){
    Queue *queue=QueueInit(1024);
    if(queue==NULL){
        perror("QueueInit");
        return -1;
    }
    pthread_t producerTId;
    if(pthread_create(&producerTId,NULL,producerStart,queue)!=0){
        perror("pthread_create");
        return -1;
    }
    pthread_t consumerTId;
    if(pthread_create(&consumerTId,NULL,consumerStart,queue)!=0){
        perror("pthread_create");
        return -1;
    }
    pthread_join(producerTId,NULL);
    pthread_join(consumerTId,NULL);
    QueueDestroy(queue);
    return 0;
}

TCP:

dd if=/dev/zero of=send bs=10000 count=100000
nc -l 0.0.0.0 12345 > recv
time nc 127.0.0.1 12345 < send

速度:

                第一次测试        第二次测试        平均速度
golang             1.322s           1.301s        58.2Mbps
C有锁并发队列        3.693s           3.619s        20.9Mbps
C无锁并发队列        2.008s           1.767s        40.4Mbps
TCP                2.232s           2.213s        3433.0Mbps

测试暂时完成了,留下了很多问题:

1、为什么golang的channel比C语言快?如果C语言在内核态实现并发队列呢?

2、为什么TCP如此之快?

© 著作权归作者所有

共有 人打赏支持
粉丝 1
博文 20
码字总数 6841
作品 0
海淀
程序员
golang实现web中间件的一些思考

最近陆续看了golang的Martini框架,也试用了,这个山寨自node.js的Express框架和最新的koa框架的golang框架, 同样具有低耦合的特点,不过还是担忧其性能,因为核心采用了reflect反射技术。 ...

yzq1979
2014/04/15
0
0
goroutine, channel 和 CSP

引子 老听 clojure 社区的人提起 core.async ,说它如何好用,如何简化了并发编程的模型,不由得勾起了我的好奇心,想了解一番其思想的源头:CSP 模型及受其启发的 goroutine 和 channel 。 ...

wangxuwei
01/29
0
0
golang思考之运行速度

有些资料显示golang的运行速度很慢,比Java慢,有时比Python慢。学习吧测试发现golang的运行速度和Java差不多。 首先,使用各种语言编写同一个CPU密集的程序sum。 C(或C++) Golang Java Py...

学习吧
2015/10/17
124
0
go学习笔记0-helloWorld

有一次听一个沙龙技术演讲,讲师说go是互联网时代的c,听了详细介绍以后感觉很赞,尤其是并行层面真正在语言层面上做了控制及特殊的内存管理机制等。。。 好吧,下面上先上helloWorld代码。(...

老范的自留地
2014/06/01
0
0
go笔记1-helloWorld

有一次听一个沙龙技术演讲,讲师说go是互联网时代的c,听了详细介绍以后感觉很赞,尤其是并行层面真正在语言层面上做了控制及特殊的内存管理机制等。。。 好吧,下面上先上helloWorld代码。(...

老范的自留地
2012/10/29
0
3
Golang 学习笔记(06)—— 多线程

本文为转载,原文:Golang 学习笔记(06)—— 多线程 Golang 介绍 线程是cpu调度的最小单位,只有不同的线程才能同时在多核cpu上同时运行。但线程太占资源,线程调度开销大。go中的gorouti...

ChainZhang
2017/12/26
0
0
【译】如何使用 Golang 中的 Go-Routines 写出高性能的代码

原文地址:How to write high-performance code in Golang using Go-Routines 原文作者:Vignesh Sk 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:tmpbook 校对者:...

临书
2017/11/24
0
0
golang入门学习笔记(三)

作者: 一字马胡 转载标志 【2017-11-23】 更新日志 日期 更新内容 备注 2017-11-23 新建文章 go语言入门学习笔记(三) golang入门学习笔记系列 golang入门学习笔记(一) golang入门学习笔...

一字马胡
2017/11/24
0
0
golang: 使用 delve 调试 golang 程序

猜你喜欢 golang: 在 Golang 中使用 Go 关键字和 Channel 实现并行 在 Golang 中使用 Go 关键字和 Channel 实现并行 使用Golang语言实现一个简单的Bitcask引擎的文件存储系统 安装 delve 官方...

d_watson
2016/05/25
102
0
golang入门学习笔记(二)

作者: 一字马胡 转载标志 【2017-11-22】 更新日志 日期 更新内容 备注 2017-11-22 新建文章 go语言入门学习笔记(二) golang入门学习笔记系列 golang入门学习笔记(一) interface for go...

一字马胡
2017/11/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
9
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
4
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
172
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
昨天
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
昨天
2
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
昨天
2
0
开发技术瓶颈期,如何突破

前言 读书、学习的那些事情,以前我也陆续叨叨了不少,但总觉得 “学习方法” 就是一个永远在路上的话题。个人的能力、经验积累与习惯方法不尽相同,而且一篇文章甚至一本书都很难将学习方法...

_小迷糊
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部