golang思考之运行速度之channel

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如此之快?

转载于:https://my.oschina.net/u/1436705/blog/519583

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值