Tuesday, December 30, 2008

Working with other libraries, part 1: Loki performance testing in FastFormat

FastFormat's performance test programs are available from the command-line, via "make -e test.performance".

Since 0.2.1 alpha 2, the distribution has included support for testing against Boost's Boost.Format library. As long as you have an environment variable BOOST defined - under which the boost directory resides - then the above make command-line will provide you with performance tests including Boost.Format. That's reasonably easy to do, because Boost.Format is header-only.

With 0.2.1 beta 6, I needed to include Loki's SafeFormat library. This presented something of a challenge, however, because Loki comes as header+implementation, i.e. it has .cpp files.

FastFormat, like several other STLSoft-related, libraries builds an exhaustive set of configurations. For example, with Visual C++ 9, it builds debug multithreaded, debug multithreaded dll, release multithreaded, and release multithreaded dll. Loki's distribution includes VC++ project/solution files that only provide the multithreaded (not the multithreaded dll) configurations. Problem: how to use Loki.SafeFormat if Loki is detected (by presence of LOKI environment variable).

This problem had me somewhat vexed, so I did what I usually did when I can't think: I went for a ride.

Upon my return, I hit upon the solution: build a specific FastFormat-specific library containing only the source file for the SafeFormat part of Loki. If the makefile detects the definition of the LOKI variable, it will attempt to build the lib/loki.safefmt.ff.??? library (where ??? refers to the per-compiler/architecture/mode configuration).

If that library does not exist, it is linked from a corresponding object, which itself is built from a file src/loki.safefmt/loki.safefmt.cpp. If this file does not exist, it is automatically generated. This file contains exactly one (pre-processor) statement:

#include <../src/SafeFormat.cpp>

which includes the requisite file form the Loki source directory.

The reason this is done is to simplify the situation if the Loki source cannot be found. As you will be aware, failing to find a required file in a makefile-build can lead to less-then-clear error messages. By generating the file if it's not there, and by #include-ing the requisite Loki source file (SafeFormat.cpp), it'll be clearer to users if that file is missing, or in the wrong directory. It also seems preferable to distributing a Loki-related source file in the FastFormat distribution, merely to allow for comparative performance testing.

So, whether you use Loki or not, you can build and test FastFormat without needing any dependencies on it. All you need to include Loki.SafeFormat in the tests is to define the LOKI variable, in the same way as if you wish to include Boost.Format in the tests you define the BOOST variable.

Monday, December 29, 2008

Width/Alignment/Fill functionality for FastFormat (0.3) functionally complete

Work on FastFormat has been progressing substantially over the last few days, in preparation for:
  • A series of articles to feature in Overload in 09
  • Monolith
As part of this, the width/alignment/fill functionality has been proven in the (currently unreleased) 0.3 branch, so that minimum-width and/or maximum-width and/or alignment and/or fill may be specified. Let's consider a couple of examples.

1. Output a string that uses a single argument twice, with default formatting in each case:

ff::fmtln(std::cout, "x={0}; y={0};", "abc");

This prints x=abc; y=abc;

2. Specify a minimum width for the first parameter:

ff::fmtln(std::cout, "x={0}; y={0,10};", "abc");

This prints x=abc; y=       abc;

3. Specify a minimum width and right alignment (which is the default) for the first parameter:

ff::fmtln(std::cout, "x={0}; y={0,10,,>};", "abc");

This prints x=abc; y=       abc;

4. Specify a minimum width and left alignment for the first parameter:

ff::fmtln(std::cout, "x={0}; y={0,10,,<};", "abc");

This prints x=abc; y=abc       ;

5. Specify a minimum width and centre alignment for the first parameter:

ff::fmtln(std::cout, "x={0}; y={0,10,,^};", "abc");

This prints x=abc; y=   abc    ;

6. Specify a maximum width for the second parameter:

ff::fmtln(std::cout, "x={0}; y={0,,2};", "abc");

This prints x=abc; y=bc;

7. Specify a maximum width and left alignment for the second parameter:

ff::fmtln(std::cout, "x={0}; y={0,,2,<};", "abc");

This prints x=abc; y=ab;

The precise semantics of the alignment and fill (not shown above) options may still be changed, but the basis of the parameter syntax (four fields: index, min-width, max-width, alignment-and-fill) seem to work out well.

And the really great news late last night was that this new functionality has no appreciable cost over 0.2, so FastFormat is still head and shoulders ahead of Boost.Format, Loki.SafeFormat, and the IOStreams in performance (as it also is in robustness, expressiveness and flexibility).

I've released beta 7 of 0.2.1 today, and hope to be releasing an alpha of 0.3 in the next couple of weeks.

FastFormat now performance tested against Loki

As of 0.2.1 beta 6, FastFormat's performance test programs now also compare against Andrei Alexandrescu's Loki library's SafeFormat component. The results clearly demonstrate FastFormat's performance superiority over this library, as they do over C++'s standard IOStreams and Boost.Format.

Given the fact that FastFormat is more robust and more flexible than these other libraries, and is highly expressive, I think it's fair to now claim that it is the pre-eminent formatting library for C++. All that remains is to provide the planned width+alignment+fill functionality, and it'll be effectively complete.

I'll be looking for input/assistance in the new year for packaging and porting. If anyone wants to volunteer, you'll be most welcome.

Wednesday, December 24, 2008

Merry Christmas ... and a busy New Year

Just wanted to wish everyone a Merry Christmas, and a happy, and busy, New Year.

Definites in the coming year:
  • publication of Breaking Up The Monolith; I've been writing like a crazy thing the last week, and now have Part 2 95+% complete and Part 3 ~33% complete
  • non-beta release of Pantheios 1.0, followed swiftly by new features
  • release of FastFormat 0.3, which will allow width/alignment specification in the format strings
  • release of xCover, a code coverage library for C++ (which is already being used in the preparation of STLSoft 1.10)
  • release of STLSoft 1.10, which will include new features, and a lot of tidying up and rationalising of the libraries 
  • a brand new website for Synesis Software, including tutorials and blogs
  • new articles and columns from me 
See you then.


Saturday, December 13, 2008

recls 1.9 alpha process begun

I've finally got around to enhancing the old stalwart, recls, which (if you don't know) is a platform-independent file-system recursive-search library.

So, far, I've finished a source-file renaming process that I started over a year ago, and now I'm having a go at the tracing functionality. This was formerly implemented in terms of syslog() on UNIX and OutputDebugString() on Windows. Now, as may be obvious if you follow STLSoft-related library news, I'm thinking it'll be implemented in terms of Pantheios.

The issue here, though, is that there should be no unnecessary coupling between libraries, and I think it would be wrong to couple recls to Pantheios just to provide good logging facilities. So the challenge will be to work out a way to allow the two to work together if required, and to not do so if not. Preprocessor options, function pointers, callbacks, and all manner of other ideas are under consideration.

I'll let you know how it goes. (And you'll be able to see it, as I'm planning to release recls 1.9 alpha 1 as soon as the logging is done.)

Friday, December 12, 2008

simple_string evolution

I'm finally putting some time into getting stlsoft::(basic_)simple_string finished - it's only been, er, 6 years. :$

Anyhow, here's the thinking:
  1. Round out all the currently-missing std::basic_string equivalency methods, so that it can act as a full functional replacement
  2. Define its purpose. This is something that has confused STLSoft users over the years.
  3. Provide compile-time selection of its nature, facilitating user-selected customisations of its implementation
The second point can be expressed as two main notions:
  • It has a documented footprint, equivalent to a single char*, which is consistent across platforms/architectures/operating systems, allowing, for example, a user to pass a std::vector<stlsoft::simple_string> to a function taking an array of C-style strings
  • It is, in some circumstances, more efficient than std::basic_string. Please note that superior efficiency is not a main design feature of the component, nor is it claimed in any general sense.
These changes will be included in forthcoming alpha releases of STLSoft 1.10.

Radio silence ...

Having had a protracted break from STLSoft-related blogging, I'm back.

I've been busy with clients, and with various coding and writing projects, of which more in the coming posts.

I'll be attempting to post daily for the next few weeks, as I make my way through the following tasks: