Пропускная способность Ethernet при разностном методе выделения буфера

Мы попробовали следующий подход к серверному коду и получили очень плохие результаты. Может ли стиль кодирования и распределение памяти повлиять на производительность, и как мы это настраиваем? Мне нужно достичь как минимум 55% выше. Я проверяю свою пропускную способность с помощью wireshark, и я делаю некоторые настройки:
сервер

   ethtool -K eth0 tx off
ifdown eth0
ifconfig eth0 mtu 3500
ifup eth0
taskset -c 0 ./server

клиент

  ifconfig eth0 mtu 9000
  1. массив
    а. Без заполнения каких-либо данных.

    unsigned long bytetosent = 4080*65536;
    char sendBuff[4080 * 65536];
    while(x < bytetosent)
    {
    int bytesWritten = send(connfd, (const char*)sendBuff+x, 6144, 0);
    x += 6144;
    }
    

Пропускная способность: 73%

б. заполнить случайными данными

    for(int y=0; y<(4080); y++)
{
sendBuff[y] = (rand() %255);
}
while(x < bytetosent)
{
int bytesWritten = send(connfd, (const char*)sendBuff+x, 6144, 0);
x += 6144;
}

Пропускная способность: 53%

  1. ММАП

    pImagePool = mmap( (void *)DDR_RAM_PHYS,MAPPED_SIZE_BUFFER, PROT_READ, MAP_SHARED, _fdMem, 0);
    while(x < bytetosent)
    {
    bytesWritten =send(connfd, ((const char*)(pImagePool))+ x, 6144, 0);
    x += 6144;
    }
    

Пропускная способность: 20%

  1. таНос

    char *_mBuffer;
    _mBuffer = malloc(4080 * 65536);
    

а. без заполнения каких-либо данных

    while(x < bytetosent)
{
bytesWritten =send(connfd, (const char*)_mBuffer+x, 6144, 0);
x += 6144;
}

Пропускная способность: 73%

б. заполнить случайные данные
Пропускная способность: 50%

  1. вектор

    vector<char>_pBuffer;
    

    а. копия

    copy((char*)(pImagePool), (((char*)(pImagePool))+1000000), back_inserter(_pBuffer));
    bytesWritten = send(connfd, &_pBuffer[bytesSent], bytetosent, MSG_CONFIRM);
    bytesSent += bytesWritten;
    

Пропускная способность: очень медленно

б. отталкивать

   for(int y=0; y<bytetosent; y++)
{
_pBuffer.push_back(*((char*)pImagePool+y));
}

Пропускная способность: очень очень медленно

Код настройки подключения к моему серверу:

    int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
time_t ticks;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(8080);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);

Мой клиент получает код:

   char recvBuff[4080 * 65536];
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
//printf("\n in while\n");
if(0)//fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}

Я попытался выполнить профилирование времени, используя mmap и memcpy. Результат:
Это считается быстрым?

Всего байт: 40000 * 1088
Время: 0.107197с

Код:

    void *pImagePool;
char _cpy[40000 * 1088];
/*Memory Mapping */
const char imagePoolDevice[]="/dev/mem";
int _fdMem;
if( (_fdMem = open( imagePoolDevice, O_RDWR | O_SYNC )) < 0 )
{
printf("Unable to open /dev/mem %d\n", _fdMem);
}
//start
start = chrono::system_clock::now();
pImagePool = mmap(0,MAPPED_SIZE_BUFFER, PROT_READ|PROT_WRITE, MAP_SHARED, _fdMem, DDR_RAM_PHYS);
if( pImagePool == MAP_FAILED ){printf("Mapping Failed\n");}
else{printf("Successful Mapping\n");}
memcpy ( _cpy, &pImagePool, sizeof(_cpy));
//end
end = chrono::system_clock::now();
chrono::duration<double>elapsed_seconds = end - start;
time_t end_time = chrono::system_clock::to_time_t(end);
cout<<"mmap time taken = "<<elapsed_seconds.count()<<endl;

0

Решение

Я наконец-то преодолел проблему путем слепого тестирования, я тестирую с помощью 2 подходов ниже:

  1. Я создаю массив и memcpy указатель возврата mmap на массив. Это увеличивает пропускную способность Ethernet до 55%. Код показан ниже:

    char _cpy[40000 * 1088];
    pImagePool = mmap(0,MAPPED_SIZE_BUFFER, PROT_READ|PROT_WRITE, MAP_SHARED, _fdMem, DDR_RAM_PHYS);
    memcpy ( _cpy, pImagePool, 40000 * 1088);
    while(bytesSent != bytetosent)
    {
    bytesWritten = send(connfd, &_cpy[bytesSent], bytetosent, MSG_CONFIRM);
    bytesSent += bytesWritten;
    }
    
  2. скопируйте mmap, чтобы вернуть указатель на вектор, но сначала нужно зарезервировать размер вектора. Извините, я не сделал это правильно в моем предыдущем тестовом коде. Пропускная способность Ethernet увеличивается до 51%.

    vector<char>_pBuffer;
    pImagePool = mmap(0,MAPPED_SIZE_BUFFER, PROT_READ|PROT_WRITE, MAP_SHARED, _fdMem, DDR_RAM_PHYS);
    _pBuffer.reserve(43520000); //40000 * 1088
    copy((char*)pImagePool, (char*)pImagePool + 43520000, back_inserter(_pBuffer));
    while(bytesSent != bytetosent)
    {
    bytesWritten = send(connfd, &_pBuffer[bytesSent], bytetosent, MSG_CONFIRM);
    bytesSent += bytesWritten;
    }
    

Я не знаю, как работает этот метод, я просто предполагаю, что это копия в кэш-память.

0

Другие решения


По вопросам рекламы [email protected]