最大化C中套接字recv的字符串接操作的效率



我试图最大限度地提高从套接字接收的充满数据的缓冲区的效率,并将其复制到全局字符数组xmlResponce[35000]中。

    char buf[2048];
    if (sendResponce != -1)
    {
        int bytes;
        memset(buf, '', 2048);
        while((bytes = recv(sockfd, buf, 2047, 0)) > 0)
        {
            buf[bytes] = '';
            strcat(xmlResponce, buf);
        }
    }

我特别关心最小化内存碎片,因为我使用的是Linux内核2.6.27,它在该部门有一些问题。有更有效的方法吗?使用strcat是从缓冲区复制到主字符数组的正确选择吗?

首先,我认为你可能想得太多了。内核内存碎片(如您对内核的引用所示)是物理RAM的碎片,这意味着伙伴算法不能分配物理上连续的页面。然而,由于您的内存是虚拟内存,这并不重要,因为虚拟连续内存不需要在物理上连续。虚拟内存碎片取决于如何在用户空间(libc或其他什么)中分配页面。

如果您确实关心虚拟内存碎片,那么可以使用mmap( ... MAP_ANON ... )分配一个大阵列。使其比您可能需要的更大(在您向每个页面写入或从每个页面读取之前,它实际上不会消耗物理内存),如果您需要扩展它,则将其mremap扩展到两倍的大小。如果您查看man mallopt(特别是M_MMAP_THRESHOLD),您会发现如果您使原始分配足够大,malloc()将为您完成所有工作。因此,我建议您只分配一个大的缓冲区(如果您愿意,可以分配35000字节),然后如果您要溢出它,请将其大小增加一倍。

现在,如何将字节写入缓冲区?

不要使用strcat。直接将它们写入缓冲区即可。根本不需要复制东西。下面是一些未经测试的代码。

ssize_t offset = 0;
....
if (sendResponce != -1)
{
    ssize_t bytes;
    while((bytes = recv(sockfd, xmlResponse+offset, 65536, 0)) > 0)
    {
        offset += bytes;
    }
}
xmlResponse[offset] = 0;

注意,为了提高效率,我已将recv的大小增加到65536字节。这意味着,通常情况下,你只需打一个电话就可以得到它。

不要忘记检查您的写入是否超过缓冲区的末尾。为了清楚起见,我把它省略了。

除非您在代码中的某个地方执行malloc/realloc/free(事实并非如此),否则不应该存在碎片问题。

主要问题是,当您的代码重新扫描每个strcat上的xmlResponse时,它接收到的数据的长度是二次的。Strcat不是最好的选择,因为你已经知道的长度

if (sendResponce != -1)
{
    int bytes, offset = 0;
    while((bytes = recv(sockfd, buf, 2047, 0)) > 0 && 
           offset+bytes < sizeof(xmlResponce)-1)
    {
        memcpy(xmlResponce+offset, buf, bytes);
        offset+= bytes;
    }
    xmlResponse[offcet]=0;
}

最新更新