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