2

我目前正在开发一个使用面向连接的 SCTP 的服务器来为少数客户端提供服务。在用一个简单的实现完成第一个原型之后,我现在正在分析应用程序以进行优化。事实证明,CPU 时间的两个主要消耗者之一是网络部分。

关于我实现的应用层协议的效率有两个问题:

1) 数据包大小

目前,我使用的最大数据包大小为 64 字节。您可以找到许多讨论数据包大小的帖子太大,但它们会不会太小?由于 SCTP 允许我一次读取一个数据包 - 类似于 UPD - 同时保证按顺序交付 - 类似于 TCP - 这显着简化了实现。但是,如果我理解正确,每次发送数据包都会花费一个系统调用。系统调用的数量是否会对性能产生重大影响?我可以通过以更大的数据包(即 1024 - 8192 字节)的形式发送消息来减少大量 CPU 周期吗?

2)读取和写入缓冲区

我目前正在使用 memcpy 将数据移入和移出应用程序级网络缓冲区。我发现了许多关于什么是更有效的、memcpy 或正常分配的相互矛盾的帖子。我想知道在这种情况下,一种方法是否会比另一种方法快得多:

选项1

void Network::ReceivePacket(char* packet)
{
    uint8_t param1;
    uint16_t param2
    uint32_t param3;

    memcpy(&param1, packet, 1);
    memcpy(&param2, packet+1, 2);
    memcpy(&param3, packet+3, 4);

    // Handle the packet here
}

void Network::SendPacket(uint8_t param1, uint16_t param2, uint32_t param3)
{
    char packet[7]

    memcpy(&packet, &param1, 1);
    memcpy(&packet+1, &param2, 2);
    memcpy(&packet+3, &param3, 4);

    // Send the packet here
}

选项 2

void Network::ReceivePacket(char* packet)
{
    uint8_t param1;
    uint16_t param2
    uint32_t param3;

    param1 = *((uint8_t*)packet);
    param2 = *((uint16_t*)packet+1);
    param3 = *((uint32_t*)packet+3);

    // Handle the packet here
}

void Network::SendPacket(uint8_t param1, uint16_t param2, uint32_t param3)
{
    char packet[7]

    *((uint8_t*)packet) = param1;
    *((uint16_t*)packet+1) = param2;
    *((uint32_t*)packet+3) = param3;

    // Send the packet here
}

第一个对我来说似乎更干净,但我发现很多帖子表明第二个可能快得多。

当然欢迎任何形式的反馈。

4

3 回答 3

0

如果您希望最大限度地减少系统调用的数量,并且您确实发现自己一次发送和接收多条消息,您可能需要考虑使用(仅限 Linux)sendmmsg()recvmmsg().

要使用这些,您可能需要在内部将消息排入队列,这可能会增加原本不存在的延迟。

于 2013-08-26T11:45:57.030 回答
0

据我所知,编译器会特别优化 memcpy 调用,因此您可能应该使用它。

关于你的第一个问题:

  • 总结: 尽可能地增大数据包大小,并避免 CPU 性能降低的可能性。

A syscall,一个系统调用,是您的操作系统回复或处理您的请求,并且每次您的请求在内核中执行时,这是一个适度的工作量。老实说,我对这个SCTP概念并不熟悉,事实上,自从我上次处理一些东西并通过 TCP 创建服务器以来,我还没有处理过套接字编程。我记得相关物理层元素的 MTU 是1500,我还记得将我的数据包大小实现为1450-1460,因为我试图在上限下获得最大数据包大小1500

所以我想说的是,如果我是你,我希望我的操作系统尽可能地不活跃,这样我就不会在 CPU 性能方面遇到任何问题。

于 2013-08-26T11:08:51.540 回答
0

我个人不会超过 1024 的缓冲区大小。我在使用超过 1500 个数据包时遇到了一些运行时问题,但 1024 当然是 4 的 5 次方,使用起来非常棒。这是可能的,但我不建议这样做。我会使用 recvmsg() 创建一个单独的线程来接收数据包,这样您就可以使用多个流。我发现这非常有效。SCTP 的要点是多流,所以我会充分利用这一点。您只需确保在收到所有内容后以正确的顺序放回数据(这需要做一些工作)。

于 2016-11-20T20:32:01.863 回答