2

这更像是一个设计问题。

我正计划编写一些实现 CPU 密集型算法的 Web 服务。我要解决的问题是——python、perl 或 java 等高级语言使编写 Web 服务变得容易。虽然 C、C++ 等较低级别的语言可以微调代码的性能。

所以我在研究我能做些什么来桥接两种语言。这是我想出的选项:

特定于语言的绑定

使用 perl-xs 或 python 的 ctypes/loadlibrary 或 java 的 JNI 之类的东西。好处是我可以编写可以在同一进程中执行的扩展。在本地语言类型与 C 之间的转换和转换回来的开销很小。

实现一个单独的守护进程

使用 thrift / avro 之类的东西,并有一个单独的守护进程来运行 C/C++ 代码。好处是,它与高级语言松散耦合。我可以快速替换高级语言。缺点是序列化和本地 unix 域套接字的开销可能高于在相同地址空间中执行代码(由前一个选项提供)。

你们有什么感想?

4

4 回答 4

1

如果您的 C/C++ 代码已经存在,最好的办法是将其发布为服务,并使用与您已有的功能相匹配的 API。然后,您可以用您选择的语言编写新服务,匹配您需要的 API,并且它们可以调用 C/C++ 服务。

如果您的 C/C++ 代码尚不存在,并且您准备使用 Java 或 C# 等高级语言创建大部分代码,请考虑在初始时也使用该语言实现性能关键部分。只有在分析显示特定的性能问题,并且在你用尽了语言中最基本的优化技术之后,例如避免在最热循环内分配,你应该考虑将已被证明消耗最多循环的位重写为另一种语言使用JNI之类的胶水。

换句话说,在你手头有数字之前不要优化。也没有根本原因,您不能通过足够的尝试从 Java 中挤出(几乎)与 C++ 相同的性能水平。您有真正的机会最终获得比您预期的更简单的架构。

于 2013-03-25T08:09:38.950 回答
0

“序列化和本地 UNIX 域套接字的开销”不是问题。假设守护进程和 Web 服务代码之间交换的数据大小与从 Web 服务通过网络发送到客户端的数据大小相同(或更小),那么网络最终可能会成为您的瓶颈,并且开销几乎无法衡量。

这是一个测试通过 UNIX 套接字传输 1GB 的脚本(需要具有大量支持的 netcat-openbsd 包和 bash,时间命令借用自自定义格式的时间代码):

#!/bin/bash
rm -f hello.sock
nc -l -U hello.sock | wc -c &
sleep 1
T="$(date +%s%N)"
dd if=/dev/zero bs=1048576 count=1024 | nc -U hello.sock
T="$(($(date +%s%N)-T))"
echo "$T nanoseconds / GB"
rm -f hello.sock

在我的 Intel Core i7 系统上,我得到 1664042362 纳秒/GB。转换为 gbit/s:

(1 GB / 1664042362 ns) * (1000000000 ns / s) * (8 gbit / 1 GB) ~ 4.8 gbit / s

在我的系统上,这个基准测试充分利用了 2 个内核(通过修改程序以输出几 GB 并查看 vmstat 来确定)。因此,如果您的 Internet 连接(以 gbit/s 为单位)为 K,并且您有 N 个内核,那么当网络满载时 IPC 使用的 CPU 百分比将是:

(K / 4.8) * (2 / N)

如果您使用至少四个核心,那么您到 Web 服务客户端的带宽为 100 mbps 或更慢,并且通过 IPC 传输的数据与从 Web 服务传输到客户端的数据大小大致相同或更小,这可以解决1% 或更少的 CPU 被 IPC 开销烧毁。

于 2013-03-26T22:53:43.673 回答
0

按照你自己的推理,用更高级的语言来实现守护进程不是更好吗?这让我们回到了第 1 步:如何提供从高级语言访问 C 代码的权限。

如果您决定直接在 C 中编写守护程序,那么最大的缺点是您必须维护所有与您提供的核心功能实际上无关的服务器代码。这是要调试的另一件事。由于它是一项服务,因此它还需要保持安全并且没有安全漏洞。

但是正如您所提到的,用 C 为特定语言编写扩展意味着您基本上被该语言所困。正确的?

不必要。让我向您介绍 SWIG:http ://www.swig.org/

使用 SWIG,编写 C 代码和目标语言之间的接口桥的工作大大简化。事实上,在我工作的地方,我们甚至使用它来单独与 Java 交互,并且永远不会使用它的多语言支持。它是一个根据您提供的接口文件为您自动生成样板代码的工具。

是的,接口文件是另一种需要学习的语法。是的,它确实有其局限性。但它的效果非常好。

使用 SWIG 的一大优势是您的库只是一个常规的 C/C++ 库。这倾向于简化和澄清代码。这也意味着如果需要,您还可以直接在 C/C++ 项目中使用该库。

于 2013-03-25T08:09:29.130 回答
0

看看Mongrel,只需用 C++ 编写 Web 服务和高性能代码。

于 2013-03-25T08:13:33.227 回答