我们正在将 C 中的遗留代码重写为 C++。在我们系统的核心,我们有一个 TCP 客户端,它连接到 master。Master 将不断地流式传输消息。每个套接字读取都会产生 N 条格式为 - 的消息{type, size, data[0]}
。
现在我们不将这些消息复制到单独的缓冲区中——而只是将消息开头的指针、长度和 shared_ptr 传递给底层缓冲区给工作人员。
旧的 C 版本是单线程的,会进行如下的 NTOH 转换:
struct Message {
uint32_t something1;
uint16_t something2;
};
process (char *message)
Message *m = (message);
m->something1 = htonl(m->something1);
m->something2 = htons(m->something2);
然后使用消息。
跟踪新代码的登录存在几个问题。
由于我们将消息分派给不同的工作人员,每个进行 ntoh 转换的工作人员都会导致缓存未命中问题,因为消息没有缓存对齐 - 即消息没有填充 b/w。
相同的消息可以由不同的工作人员处理 - 这是消息需要在本地处理并中继到另一个进程的情况。在这里,中继工作者需要原始网络顺序的消息,本地工作需要转换为主机顺序。显然,由于消息不重复,两者都不能满足。
我想到的解决方案是 -
复制消息并为所有中继工作人员发送一份副本(如果有)。在分派之前,在分派器本身中对属于同一缓冲区的所有消息进行 ntoh 转换 - 比如说通过调用 a
handler->ntoh(message);
以便解决缓存未命中问题。向每个工人发送原件。每个worker将消息复制到本地缓冲区,然后进行ntoh转换并使用它。在这里,每个工作人员都可以使用特定于线程的(thread_local)静态缓冲区作为便签本来复制消息。
现在我的问题是
选项 1 是进行 ntoh 转换的方式 - C++sy 吗?我的意思是结构的对齐要求将与 char 缓冲区不同。(我们还没有遇到任何问题。)。在这种情况下使用方案 2 应该没问题,因为暂存缓冲区可以具有 max_align_t 对齐,因此应该可以类型转换为任何结构。但这会导致复制整个消息 - 这可能非常大(比如几个 K 大小)
有没有更好的方法来处理这种情况?