森子格 2020-01-21 16:39 采纳率: 0%
浏览 444

请问如何用linux套接字编程来发挥万兆网卡的性能?

双线程,一个生产数据放入kfifo,一个从kfifo取出数据,通过套接字发送。最终测试出来速度只能达到400MB/S。(kfifo出队64KB数据要100us)

之后我将生产者做了更改,让它只更新队首的in指针,不做数据拷贝,此时速度能达到1000MB/S。(kfifo出队64KB数据只要10us)

我怀疑是生产者生产数据写入队列时,导致消费者所在的cpu cache失效,然后cache未命中导致速度骤降。但是不知道怎么解决这个问题。

在网上搜索答案,但是没有找到类似情况。看到有一个和我问题应该比较类似的,但是没有找到解决方法。

《请问为何tcp send第一次时很慢, 第二次时很快呢?》

https://www.oschina.net/question/2897213_2193602

#include "szg_common.h"
#include "szg_kfifo.h"
#include "szg_socket.h"

/**kfifo
 * 队列是将linux内核中的kfifo移到了这里来用,用malloc来替代内核中的kmalloc
 * 此代码(发送端)运行在NXP T4240上,系统linux,万兆网卡。
 * 接收端软件运行在PC上,系统windows10,万兆网卡。
 *
 * 1.正常出入队,kfifo总大小64M 元素大小256bytes 期望出队和期望入队都是256个元素
 *      速度400MB/S   出队64k要100us send要50us
 * 2.注释掉kfifoin中的两行memcpy(szgKfifoCopyIn中的),让其只更新队首in指针
 *      速度1000MB/S 出队64k要10us      send要50us 
 * 
 *
 */
#define KFIFO_SEND_SIZE         0x10000     //64k

#define FIFO_IN         0x100       //每次入队时期望入队的元素个数:256个(即256*256 = 64k)
#define FIFO_OUT        0x100       //每次出队时期望出队的元素个数:256个(即256*256 = 64k)
#define FIFO_E_SIZE     0x100       //元素大小:256byte  
#define FIFO_SIZE       0x4000000   //总大小:64Mbyte (256*256*1024个)

kfifo   testkFifo;
void *szgTestKfifoThread(void *param)
{
    UINT32 ret;

    char data_buf[KFIFO_SEND_SIZE] = {0};


    while(TRUE)
    {
        ret = szgKfifoIn(&testkFifo,data_buf,FIFO_IN);

        if(ret == 0)
        {
            pthread_yield();
            //usleep(2);
        }

    }
}



int kfifo_test(void)
{
    INT32 listenFd;
    INT32 connectFd;
    INT32 ret;
    UINT32 clientIp;
    pthread_t threadId; 
    pthread_attr_t attr;
    struct timeval start,end;
    char send_buf[KFIFO_SEND_SIZE];
    memset(send_buf,1,KFIFO_SEND_SIZE);

    signal(SIGPIPE,SIG_IGN);
    /**
     * 初始化kfifo
     * 总大小 64M 
     * 元素大小 256byes
     * 元素个数 256*1024个
     * 出队,入队都是期望256个元素,不到256个有多少出多少,实际个数作为返回值返回
     */
    ret = szgKfifoAlloc(&testFifo,FIFO_SIZE/FIFO_E_SIZE,FIFO_E_SIZE);
    CHECK_EXIT(ret == ERROR, "fifo init err!");



    /*创建线程,线程分离*/
    pthread_attr_init (&attr);
    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
    if (0 != pthread_create(&threadId,&attr, (void *)szgTestKfifoThread,NULL))  
    {
        SZG_LOG(SZG_LOG_ERR,"Create Thread data_filter_thread Fail \n");
        return ERROR;
    }


    /*服务器初始化 端口6101 发送缓存2M 接收缓存1M(2M/2)*/  
    listenFd = szgSockInit(NULL,6101,0x200000);
    CHECK_EXIT(listenFd < 0, "socket error");


    while(TRUE)
    {
        printf("wait connect\n");
        /*客户端ip通过&clientIp返回(其实下面没用到)*/
        connectFd = szgSockAccept(listenFd,&clientIp);
        if (connectFd  < 0)
        {
            SZG_LOG(SZG_LOG_ERR,"server Accept Failed!/n");
            return 0;
        }
        while(TRUE)
        {
            //gettimeofday(&start,NULL);
            /*出队 256*256 */
            ret = szgKfifoOut(&testkFifo,send_buf,FIFO_OUT);
            if(ret == 0)//没有数据
            {
                pthread_yield();
                continue;
                //usleep(2);            
            }
            //gettimeofday(&end,NULL);
            //printf("kfifo time %lu us \n",(1000000*(end.tv_sec-start.tv_sec) + (end.tv_usec-start.tv_usec)));


            /*发送64k*/
            //gettimeofday(&start,NULL);
            ret = szgSendData(connectFd,send_buf,ret*FIFO_E_SIZE);
            if(ret == ERROR)
            {
                SZG_LOG(SZG_LOG_ERR,"szgSendData data error\n");
                break;
            }
            //gettimeofday(&end,NULL);
            //printf("send time %lu us \n",(1000000*(end.tv_sec-start.tv_sec) + (end.tv_usec-start.tv_usec)));
        }
    }
    return 0;
}
  • 写回答

1条回答 默认 最新

  • 在黎明的反思 2020-01-22 10:53
    关注

    1、首先分析瓶颈是在那里,是发送还是接受,是入队还是出队,还是缓存不够导致的。

    评论

报告相同问题?

悬赏问题

  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型