PTypes: Portability and Performance Issues

Top: Portability and performance issues

64-bit integers: most compilers provide long long type modifier for declaring 64-bit integers, but at least two of them, Microsoft C/C++ and Borland C/C++, use quite unaesthetic keyword __int64. PTypes offers its own wrapper type large (in <pport.h>), which is a portable signed 64-bit integer. Unsigned large or ularge are also available. For portable 64-bit string conversions use itostring() and stringto*() declared in <ptypes.h>.

Another incompatibility exists for printf-style formatted output routines: Windows uses "I64" type modifier for 64-bit integers, whereas standard-compliant libraries recognize "ll" (ell-ell). PTypes solves this problem in its outstm::putf() method: you can safely use "ll" modifier on all platforms.

End-of-line sequences: PTypes input stream routines automatically recognize three types of EOL sequences: LF (UNIX), CR (Mac) and CR-LF (DOS/Win) and set instm::eol property accordingly.

As for output streams, unlike many Windows-based C run-time libraries, PTypes does NOT make any translations and always sends your data as is. In order to generate an EOL sequence appropriate to the target platform (i.e. the system your application is running on), use outstm::puteol() and outstm::putline(string). Some protocols and data formats, however, require some predetermined EOL sequence regardless of the target platform, e.g. HTTP always uses CR-LF, PostScript uses CR, etc. In such cases you can use standard C escape sequences to send appropriate codes to the output stream, e.g. "\r\n" or "\r".

File names: you can always use UNIX-style path names (with slash '/') when working with files through PTypes streaming classes. Since drive specifiers in path names are specific only to Windows, try to use relative paths in your program whenever possible. For additional notes on pipe naming, please see introduction for the namedpipe class.

Arithmetic operations and multithreading: a simple increment and decrement operation (i++ and i--) in a multithreaded application may NOT be thread-safe on most RISC CPU's and on i386-based multiprocessor systems. Even if you are not interested in the resulting value of an increment/decrement operation, still use PTypes pincrement() and pdecrement() on variables shared between threads.

Performance of dynamic strings: most of the string operations rely on dynamic memory reallocation. PTypes tries to avoid frequent use of physical reallocation by aligning the dynamic string buffers on 16, 32, 64 ... 4096-byte boundaries, depending on the logical size of a string. Physical reallocation highly depends on the performance of the standard realloc() function, which may vary from OS to OS. Linux, for example, performs reallocations up to 30 times faster than Windows on a similar computer. PTypes dynamic strings also depend on the performance of the atomic increment and decrement functions (see below).

Performance of atomic increment/decrement/exchange operations: on SPARC, PowerPC and i386-based platforms PTypes implements atomic operations using CPU instructions. On all other platforms these operations use slower mutex locking (see src/patomic.cxx).

Reentrancy of synchronization objects: the POSIX standard does not specify whether synchronization objects should be reentrant or not. For instance, if you use recursive locks on a mutex object the behaviour of your application may vary on different systems. Most POSIX systems, such like Linux, provide a faster but non-reentrant implementation of synchronization primitives.

Read/write lock portability issues: the rwlock class is built on top of the POSIX rwlock interface, wherever available, or uses the internal implementation (see src/rwlock.cxx). Various system-level implementations use different prioritization schemes: they may be 'fair' with respect to both reader and writer threads, or a higher priority may be given to one of them. Unfortunately the behaviour of rwlock is not standardized yet. PTypes' internal implementation uses the 'fair' scheme which we believe is the best and the only DoS-proof (denial-of-service) among other algorithms. On the other hand, replacing the system-level rwlock with our own implementation on all systems would lead to a preformance penalty compared to using 'native' objects. We set this issue aside for some time and we are open to discuss it with interested/experienced developers.

See also: String Conversion, outstm, namedpipe, string, Multithreading Utilities

PTypes home