我尝试在从缓冲区获取数据时充分利用效率,从套接字接收并将其复制到全局字符数组xmlResponce[35000]
。
char buf[2048];
if (sendResponce != -1)
{
int bytes;
memset(buf, '\0', 2048);
while((bytes = recv(sockfd, buf, 2047, 0)) > 0)
{
buf[bytes] = '\0';
strcat(xmlResponce, buf);
}
}
我特别关注最小化内存碎片,因为我在Linux Kernel 2.6.27上有一些问题。有没有更有效的方法来做到这一点?使用strcat
正确选择从缓冲区复制到主char数组吗?
答案 0 :(得分:2)
首先,我认为你可能会过度思考这一点。内核内存碎片(如您对内核的引用所示)是物理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字节。这通常意味着你通常会在一次通话中得到它。
不要忘记检查你是否在缓冲区末尾写字。为了清楚起见,我把它留了下来。
答案 1 :(得分:1)
除非你在代码中的某个地方进行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;
}