A.6 Optimize for Efficiency

I l @ ve RuBoard

The design principles used for higher-level applications and GUI frameworks aren't necessarily appropriate for lower-levels of network programming toolkits. In particular, performance considerations often preclude the use of certain languages features, idioms, and patterns, as we describe in this section.

A.6.1 Design Wrapper Facades for Efficiency

Problem: Despite years of successful deployment, a belief persists in some application domains that object-oriented techniques and C++ are not suitable for performance-sensitive systems. For example, the dynamic binding and native exception handling features of object-oriented programming languages can be problematic in real-time embedded applications that require predictable run-time behavior, low latency, and small footprint. However, many real-time application domains, such as aerospace, call processing, process control, and distributed interactive simulation, can benefit from flexible and portable host infrastructure middleware. It's therefore essential that object-oriented software intended for these domains be designed carefully to avoid language features and patterns that add gratuitous overhead.

Solution Design wrapper facades for efficiency. ACE uses the following techniques to ensure that its wrapper facades are efficient:

  • Many ACE wrapper facades are concrete types; that is, their methods are nonvirtual. This design eliminates the overhead of dispatching dynamically bound methods , increases opportunities for method inlining, and enables objects to be placed in shared memory where appropriate.

  • All the ACE IPC wrapper facades contain explicit open () and close() methods and their destructors don't close handles. This design prevents subtle errors caused if I/O handles are closed prematurely when transferred by value from one object to another. ACE's wrapper facades purposely avoid the use of the Bridge pattern [GHJV95] since that would incur dynamic memory allocation and reduce efficiency, rather than improve it. Instead, the principle we apply in ACE is to not perform certain types of implicit operations towards the root of class hierarchies. Rather, higher layer abstracts provide these capabilities when needed. For example, the Logging_Server class on page 81 in Section 4.4.1 closes the acceptor socket handle in its destructor, which is the common use case at that level of abstraction.

A.6.2 Inline Performance-Critical Methods

Problem: Wrapper facades enhance the portability and type safety of native C-level function APIs by providing an additional level of abstraction. If these wrapper facades aren't implemented efficiently , however, many networked application developers won't use them in lieu of existing low-level C networking APIs. Networked applications are often time-sensitive, and their developers must be vigilant about reducing latency and improving responsiveness because the network itself already exacerbates these problems. Since OS platform calls are often in time-critical parts of the execution path , developers of networked applications tend to be leery of any overhead that may decrease performance.

Solution Inline performance-critical methods to minimize or eliminate any performance overhead resulting from increased type safety. ACE uses C++ inlining extensively to eliminate method call overhead stemming from the additional abstraction in its OS adaptation layer and C++ wrapper facades. Methods in the critical performance path, such as the recv() and send() methods of ACE_SOCK_Stream , are specified as C++ inline functions. Inlining is time and space efficient since these methods are short (e.g., 1 to 2 lines per method). In addition, virtual methods are used sparingly in the performance-critical parts of ACE since many C++ compiler optimizers don't fully eliminate virtual method overhead [HLS97].

A.6.3 Avoid Exception Handling in System-Level Toolkits

Problem: Experienced C++ programmers will notice that the class definitions throughout the book and in ACE don't contain exception specifications. This may seem a shortcoming at first glance since handling error indications in a call chain can be hard, and is a prime motivation for C++'s exception handling mechanisms. There are two problems, however, with using native C++ exception handling in system-level toolkits:

  1. Portability ” ACE began in 1991, well before exceptions were a part of the C++ standard. Even today, compilers are not uniform in their support of exceptions, nor can all end users migrate to new compilers due to legacy dependencies. Since ACE must run on a wide range of compilers and platforms, any dependencies on native exceptions would preclude its portable use in some environments.

  2. Performance ” The time and space overhead incurred by many compilers is unacceptable for certain types of applications. For example, the additional memory space and execution time incurred by native exception handling is prohibitive for real-time applications in embedded systems. Even if a platform supports native exception handling, therefore, real-time and embedded applications on that platform may be unable to use it.

Solution Avoid exception handling in system-level toolkits. ACE doesn't throw exceptions for the reasons outlined above. Internally, it uses the Thread-Specific Storage pattern [SSRB00] to convey error status information between caller and callee. This pattern allows sequential operations within a thread to access common data atomically without incurring locking overhead for each access. By placing error information into thread-specific storage, each thread can reliably set and test the status of operations within that thread without using additional locks or complex synchronization protocols.

For systems that want to use exceptions in their application software, ACE can be compiled with native C++ exception support. For platforms that use make to build ACE, simply add exceptions=1 to the command line or to the platform_macros.GNU file.

I l @ ve RuBoard


C++ Network Programming
C++ Network Programming, Volume I: Mastering Complexity with ACE and Patterns
ISBN: 0201604647
EAN: 2147483647
Year: 2001
Pages: 101

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net