|  | The GDB Performance Testsuite | 
|  | ============================= | 
|  |  | 
|  | This README contains notes on hacking on GDB's performance testsuite. | 
|  | For notes on GDB's regular testsuite or how to run the performance testsuite, | 
|  | see ../README. | 
|  |  | 
|  | Generated tests | 
|  | *************** | 
|  |  | 
|  | The testcase generator lets us easily test GDB on large programs. | 
|  | The "monster" tests are mocks of real programs where GDB's | 
|  | performance has been a problem.  Often it is difficult to build | 
|  | these monster programs, but when measuring performance one doesn't | 
|  | need the "real" program, all one needs is something that looks like | 
|  | the real program along the axis one is measuring; for example, the | 
|  | number of CUs (compilation units). | 
|  |  | 
|  | Structure of generated tests | 
|  | **************************** | 
|  |  | 
|  | Generated tests consist of a binary and potentially any number of | 
|  | shared libraries.  One of these shared libraries, called "tail", is | 
|  | special.  It is used to provide mocks of system provided code, and | 
|  | contains no generated code.  Typically system-provided libraries | 
|  | are searched last which can have significant performance consequences, | 
|  | so we provide a means to exercise that. | 
|  |  | 
|  | The binary and the generated shared libraries can have a mix of | 
|  | manually written and generated code.  Manually written code is | 
|  | specified with the {binary,gen_shlib}_extra_sources config parameters, | 
|  | which are lists of source files in testsuite/gdb.perf.  Generated | 
|  | files are controlled with various configuration knobs. | 
|  |  | 
|  | Once a large test program is built, it makes sense to use it as much | 
|  | as possible (i.e., with multiple tests).  Therefore perf data collection | 
|  | for generated tests is split into two passes: the first pass builds | 
|  | all the generated tests, and the second pass runs all the performance | 
|  | tests.  The first pass is called "build-perf" and the second pass is | 
|  | called "check-perf".  See ../README for instructions on running the tests. | 
|  |  | 
|  | Generated test directory layout | 
|  | ******************************* | 
|  |  | 
|  | All output lives under testsuite/gdb.perf in the build directory. | 
|  |  | 
|  | Because some of the tests can get really large (and take potentially | 
|  | minutes to compile), parallelism is built into their compilation. | 
|  | Note however that we don't run the tests in parallel as it can skew | 
|  | the results. | 
|  |  | 
|  | To keep things simple and stay consistent, we use the same | 
|  | mechanism used by "make check-parallel".  There is one catch: we need | 
|  | one .exp for each "worker" but the .exp file must come from the source | 
|  | tree.  To avoid generating .exp files for each worker we invoke | 
|  | lib/build-piece.exp for each worker with different arguments. | 
|  | The file build.piece.exp lives in "lib" to prevent dejagnu from finding | 
|  | it when it goes to look for .exp scripts to run. | 
|  |  | 
|  | Another catch is that each parallel build worker needs its own directory | 
|  | so that their gdb.{log,sum} files don't collide.  On the other hand | 
|  | its easier if their output (all the object files and shared libraries) | 
|  | are in the same directory. | 
|  |  | 
|  | The above considerations yield the resulting layout: | 
|  |  | 
|  | $objdir/testsuite/gdb.perf/ | 
|  |  | 
|  | gdb.log, gdb.sum: result of doing final link and running tests | 
|  |  | 
|  | workers/ | 
|  |  | 
|  | gdb.log, gdb.sum: result of gen-workers step | 
|  |  | 
|  | $program_name/ | 
|  |  | 
|  | ${program_name}-0.worker | 
|  | ... | 
|  | ${program_name}-N.worker: input to build-pieces step | 
|  |  | 
|  | outputs/ | 
|  |  | 
|  | ${program_name}/ | 
|  |  | 
|  | ${program_name}-0/ | 
|  | ... | 
|  | ${program_name}-N/ | 
|  |  | 
|  | gdb.log, gdb.sum: for each build-piece worker | 
|  |  | 
|  | pieces/ | 
|  |  | 
|  | generated sources, object files, shlibs | 
|  |  | 
|  | ${run_name_1}: binary for test config #1 | 
|  | ... | 
|  | ${run_name_N}: binary for test config #N | 
|  |  | 
|  | Generated test configuration knobs | 
|  | ********************************** | 
|  |  | 
|  | The monster program generator provides various knobs for building various | 
|  | kinds of monster programs.  For a list of the knobs see function | 
|  | GenPerfTest::init_testcase in testsuite/lib/perftest.exp. | 
|  | Most knobs are self-explanatory. | 
|  | Here is a description of the less obvious ones. | 
|  |  | 
|  | binary_extra_sources | 
|  |  | 
|  | This is the list of non-machine generated sources that go | 
|  | into the test binary.  There must be at least one: the one | 
|  | with main. | 
|  |  | 
|  | class_specs | 
|  |  | 
|  | List of pairs of keys and values. | 
|  | Supported keys are: | 
|  | count: number of classes | 
|  | Default: 1 | 
|  | name: list of namespaces and class name prefix | 
|  | E.g., { ns0 ns1 foo } -> ns0::ns1::foo_<cu#>_{0,1,...} | 
|  | There is no default, this value must be specified. | 
|  | nr_members: number of members | 
|  | Default: 0 | 
|  | nr_static_members: number of static members | 
|  | Default: 0 | 
|  | nr_methods: number of methods | 
|  | Default: 0 | 
|  | nr_inline_methods: number of inline methods | 
|  | Default: 0 | 
|  | nr_static_methods: number of static methods | 
|  | Default: 0 | 
|  | nr_static_inline_methods: number of static inline methods | 
|  | Default: 0 | 
|  |  | 
|  | E.g., | 
|  | class foo {}; | 
|  | namespace ns1 { class bar {}; } | 
|  | would be represented as: | 
|  | { | 
|  | { count 1 name { foo } } | 
|  | { count 1 name { ns1 bar } } | 
|  | } | 
|  |  | 
|  | The naming of each class is "class_<cu_nr>_<class_nr>", | 
|  | where <cu_nr> is the number of the compilation unit the | 
|  | class is defined in. | 
|  |  | 
|  | There's currently no support for nesting classes in classes, | 
|  | or for specifying baseclasses or templates. | 
|  |  | 
|  | Misc. configuration knobs | 
|  | ************************* | 
|  |  | 
|  | These knobs control building or running of the test and are specified | 
|  | like any global Tcl variable. | 
|  |  | 
|  | CAT_PROGRAM | 
|  |  | 
|  | Default is /bin/cat, you shouldn't need to change this. | 
|  |  | 
|  | SHA1SUM_PROGRAM | 
|  |  | 
|  | Default is /usr/bin/sha1sum. | 
|  |  | 
|  | PERF_TEST_COMPILE_PARALLELISM | 
|  |  | 
|  | An integer, specifies the amount of parallelism in the builds. | 
|  | Akin to make's -j flag.  The default is 10. | 
|  |  | 
|  | Writing a generated test program | 
|  | ******************************** | 
|  |  | 
|  | The best way to write a generated test program is to take an existing | 
|  | one as boilerplate.  Two good examples are gmonster1.exp and gmonster2.exp. | 
|  | gmonster1.exp builds a big binary with various custom manually written | 
|  | code, and gmonster2 is (essentially) the equivalent binary split up over | 
|  | several shared libraries. | 
|  |  | 
|  | Writing a performance test that uses a generated program | 
|  | ******************************************************** | 
|  |  | 
|  | The best way to write a test is to take an existing one as boilerplate. | 
|  | Good examples are gmonster1-*.exp and gmonster2-*.exp. | 
|  |  | 
|  | The naming used thus far is that "foo.exp" builds the test program | 
|  | and there is one "foo-bar.exp" file for each performance test | 
|  | that uses test program "foo". | 
|  |  | 
|  | In addition to writing the test driver .exp script, one must also | 
|  | write a python script that is used to run the test. | 
|  | This contents of this script is defined by the performance testsuite | 
|  | harness.  It defines a class, which is a subclass of one of the | 
|  | classes in gdb.perf/lib/perftest/perftest.py. | 
|  | See gmonster-null-lookup.py for an example. | 
|  |  | 
|  | Note: Since gmonster1 and gmonster2 are treated as being variations of | 
|  | the same program, each test shares the same python script. | 
|  | E.g., gmonster1-null-lookup.exp and gmonster2-null-lookup.exp | 
|  | both use gmonster-null-lookup.py. | 
|  |  | 
|  | Running performance tests for generated programs | 
|  | ************************************************ | 
|  |  | 
|  | There are two steps: build and run. | 
|  |  | 
|  | Example: | 
|  |  | 
|  | bash$ make -j10 build-perf RUNTESTFLAGS="gmonster1.exp" | 
|  | bash$ make -j10 check-perf RUNTESTFLAGS="gmonster1-null-lookup.exp" \ | 
|  | GDB_PERFTEST_MODE=run |