RCF is a library/framework for RPC and distributed messaging. I like the RCF framework for the following reasons
- in line service - interface - rpc call specification (i.e., no separate compilation of an IDL).
- C10K design style (layers ontop of windows IOCP or boost ASIO).
- supports windows named pipes and unix domain sockets (I absolutely cannot compromise on this).
- SSL.
- Messaging paradigms, 2-way, 1-way, client-callback, 1-way batched.
- protocol buffers support (tho I think I can stick with the built-in-serialization).
- publish/subscribe functionality.
I am using GCC 4.4.3 on a 64-bit ubuntu install. I compile the trivial server and client code using the following line in the demo subdirectory of the distribution.
g++ -O3 -DRCF_USE_BOOST_ASIO Client.cpp ../src/RCF/RCF.cpp -I ../../Boost/ -I ../include/ -lpthread ../../Boost/lib/libboost_system.a -s
The resulting client and server binaries fluctuate between 1.7 to 2.2 megabytes.
Alarm bells are ringing; I use the following three examples as my yard sticks:
- Boost::ASIO: server 2 example compiled in release version using bjam. The resulting code , stripped, is 176kb.
- nginx: A highly complex, very configureable, very efficient web-server. 500kb stripped.
- Trandsport Channel focused minimal middleware solution Zero MQ. libzmq 274k
I have written my own production RPC/middleware and I'm getting to a stage where I'm thinking I'll just write another one to meet my needs, layering on top of Boost. But I do not want to do this. I like RCF's design, it meets my needs. However, I can't justify the binary size of the simple programs, it should not produce such massive binaries.
I have two main concerns.
- The quality of the code-paths for rpc. I want low latency.
- The growth of the binary as I start coding my application arround it.
A reasonable explanation is that the library isn't designed for modularity, and instantiates everything upfront.
["The Question"]
I'd like some feedback from folks who design real-time data-processing systems on my concerns. Could you justify this size ?
["/The Question"]
I'd consider alternatives. ZMQ is nice, but its an aditional dependancy, misses SSL, doesn't provide a lot of middleware primitives, and doesn't provide named pipes (I need to verify connecting processes, and named pipes have security contexts)
What your command line is doing, is compiling RCF statically into the server and client executables. That makes the build process simple, but also means that both executables are carrying around their own copy of RCF. There are over 60000 lines of code in RCF 1.3, so it will definitely have an impact on executable size.
You can build RCF into a DLL, and link to it instead. You'll need to define RCF_BUILD_DLL when building the DLL, or nothing will be exported.
For a ballpark figure, on a Visual C++ 2008 build environment I have, this results in a 1.6 MB DLL. There will still be some code that ends up in the importing module, as RCF's marshaling code uses templates and templated code needs to be inlined in headers, so can't be exported from the DLL.
On your concerns:
(1) RCF was designed from the start with low-latency in mind, and the critical path for a remote call is highly optimized. There are no memory allocations at all for instance, and no copying of message data. If you're worried, you can write a simple client and server and see how many thousands of calls you can make per second (just remember to use a release build). For more information, have a look at the Performance section in the User Guide
(2) As with any library, there is some up front size overhead when you build it into your application. But there won't be any 'ongoing' overhead after that.