Tuesday, June 28, 2011

Restructured text table reports

Download: rst2pdf-read-only.tar.gz

I use rst2pdf to create PDF documents from reStructuredText (ReST). It is relatively easy to generate table reports from a database, like the ones shown below. In this example, the table does not fit into one page and spans two.




Although it is easy to execute statistical queries such as sum a column in a database table using SQL, it is not possible to add summary rows to each page when a table spans multiple pages. The shortcoming with ReST and rst2pdf is that you do not know how many rows will fit into a page because it depends on the page size (A4 etc), font size and table content. The modified version of rst2pdf I provide in this post allows you to attach additional rows (with sum of column information) onto the bottom of tables, automatically, and for each page.  In the example you can see how to insert current page sum of column, previous pages sum of column and total pages sum of column information into the summary row. The ":sum:" is a nonstandard interpreted text role, which means it will only work with this version of rst2pdf.

The syntax to generate the table is this:

.. list-table:: Title
   :widths: 15 10 30
   :header-rows: 1

   * - Description
     - Weight
     - Height
   * - A
     - 1
     - 2 
   * - B
     - 1
     - 2
   * - C
     - 1
     - 2
   * - D
     - 1
     - 2
   * - E
     - 1
     - 2
   * - F
     - 1
     - 2 
   * - G
     - 1
     - 2
   * - H
     - 1
     - 2
   * - I
     - 1
     - 2 
   * - J
     - 1
     - 2
   * - k
     - 1
     - 2
   * - L
     - 1
     - 2
   * - M
     - 1
     - 2
   * - N
     - 1
     - 2
   * - O
     - 1
     - 2
   * - P
     - 1
     - 2
   * - Q
     - 1
     - 2
   * - R
     - 1
     - 2
   * - Previous Total 
     - :sum:`previous_pages_col`
     - :sum:`previous_pages_col`
   * - Current Page Total 
     - :sum:`current_pages_col`
     - :sum:`current_pages_col`
   * - Total 
     - :sum:`total_pages_col`
     - :sum:`total_pages_col`


The command to create the table:

python createpdf.py --repeat-table-rows table.txt -o table.pdf

Wednesday, June 15, 2011

Benchmarking function call overhead in C++

Download: benchmark.tar.gz

The are two types of function calls I benchmark here:

1) Virtual functions
2) CRTP, used to simulate dynamic binding (with and without inlining)

One particular use of the CRTP is to simulate dynamic binding. The technique achieves a similar effect to the use of virtual functions, without the costs of dynamic polymorphism. The reason for this stems from the ability to inline function calls which is not possible with virtual functions bound at run-time. The use of CRTP is only worthwile when the cost of calling a funcion is not dominated by call and return overhead. Getter and Setter funcionts are good candidates for inlined CRTP.

Dynamic.h
#ifndef _Dynamic_H
#define _Dynamic_H

struct DynamicBase
{
    DynamicBase() {}
    virtual ~DynamicBase() {}
    virtual void function(long*) = 0;
};

DynamicBase* createDynamic();

#endif  /* _Dynamic_H */
Dynamic.cc
#include "Dynamic.h"
struct ImpOfDynamic : public DynamicBase
{
    void function(long* x);
};

void ImpOfDynamic::function(long* x) { ++*x; }

DynamicBase* createDynamic() {
    return new ImpOfDynamic;
}
Static.h
#ifndef _Static_H
#define _Static_H

template 
struct StaticBase
{
    void function(long* x)
    {
        static_cast(this)->function(x);
    }
};

struct ImpOfStatic : StaticBase
{
    // Without inlining  
    // void function(long* x);    

    // With inlining 
    inline void function(long* x);
};

void ImpOfStatic::function(long* x) { ++*x; }

#endif

main.cc
#include "Static.h"
#include "Dynamic.h"
#include 
#include 

Benchmark Results:

Without CRTP inlining:
6.01975 Virtual function (ns)
6.0212 CRTP function (ns)

With CRTP inlining:
6.16391 Virtual function (ns)
1.99611 CRTP function (ns)

There is no point in using CRTP instead of virtual functions unless inlining is used.