diff options
-rw-r--r-- | progs/tests/api_speed.c | 146 | ||||
-rwxr-xr-x | progs/tests/api_speed.py | 143 |
2 files changed, 289 insertions, 0 deletions
diff --git a/progs/tests/api_speed.c b/progs/tests/api_speed.c new file mode 100644 index 00000000000..f42c73dfc90 --- /dev/null +++ b/progs/tests/api_speed.c @@ -0,0 +1,146 @@ +/* + * (C) Copyright IBM Corporation 2002 + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file api_speed.c + * Simple test to measure the overhead of making GL calls. + * + * The main purpose of this test is to measure the difference in calling + * overhead of different dispatch methods. Since it uses asm/timex.h to + * access the Pentium's cycle counters, it will probably only compile on + * Linux (though most architectures have a get_cycles function in timex.h). + * That is why it isn't in the default Makefile. + * + * \author Ian Romanick <[email protected]> + */ + +#include <stdio.h> +#include <stdlib.h> +#define GL_GLEXT_PROTOTYPES +#include <GL/gl.h> +#include <GL/glext.h> +#include <GL/glut.h> + +#define inline __inline__ +#include <asm/timex.h> + +static float Width = 400; +static float Height = 400; +static unsigned count = 1000000; + + +static void Idle( void ) +{ + glutPostRedisplay(); +} + +#define DO_FUNC(f,p) \ + do { \ + t0 = get_cycles(); \ + for ( i = 0 ; i < count ; i++ ) { \ + f p ; \ + } \ + t1 = get_cycles(); \ + printf("%u calls to % 20s required %llu cycles.\n", count, # f, t1 - t0); \ + } while( 0 ) + +/** + * Main display function. This is the place to add more API calls. + */ +static void Display( void ) +{ + int i; + const float v[3] = { 1.0, 0.0, 0.0 }; + cycles_t t0; + cycles_t t1; + + glBegin(GL_TRIANGLE_STRIP); + + DO_FUNC( glColor3fv, (v) ); + DO_FUNC( glNormal3fv, (v) ); + DO_FUNC( glTexCoord2fv, (v) ); + DO_FUNC( glTexCoord3fv, (v) ); + DO_FUNC( glMultiTexCoord2fv, (GL_TEXTURE0, v) ); + DO_FUNC( glMultiTexCoord2f, (GL_TEXTURE0, 0.0, 0.0) ); + DO_FUNC( glFogCoordfv, (v) ); + DO_FUNC( glFogCoordf, (0.5) ); + + glEnd(); + + exit(0); +} + + +static void Reshape( int width, int height ) +{ + Width = width; + Height = height; + glViewport( 0, 0, width, height ); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glOrtho(0.0, width, 0.0, height, -1.0, 1.0); + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); +} + + +static void Key( unsigned char key, int x, int y ) +{ + (void) x; + (void) y; + switch (key) { + case 27: + exit(0); + break; + } + glutPostRedisplay(); +} + + +int main( int argc, char *argv[] ) +{ + glutInit( &argc, argv ); + glutInitWindowSize( (int) Width, (int) Height ); + glutInitWindowPosition( 0, 0 ); + + glutInitDisplayMode( GLUT_RGB ); + + glutCreateWindow( argv[0] ); + + if ( argc > 1 ) { + count = strtoul( argv[1], NULL, 0 ); + if ( count == 0 ) { + fprintf( stderr, "Usage: %s [iterations]\n", argv[0] ); + exit(1); + } + } + + glutReshapeFunc( Reshape ); + glutKeyboardFunc( Key ); + glutDisplayFunc( Display ); + glutIdleFunc( Idle ); + + glutMainLoop(); + return 0; +} diff --git a/progs/tests/api_speed.py b/progs/tests/api_speed.py new file mode 100755 index 00000000000..d209676261f --- /dev/null +++ b/progs/tests/api_speed.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python2 + +# (C) Copyright IBM Corporation 2004 +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# Authors: +# Ian Romanick <[email protected]> + + +# This script is used to run api_speed against several different libGL +# libraries and compare the results. See the show_usage function for more +# details on how to use it. + + +import re, os, sys, getopt + +class results: + def process_file(self, f): + self.cycles = {} + self.iterations = -1 + + for line in f.readlines(): + m = re.match("(\d+) calls to (.{20}) required (\d+) cycles.", line) + + if self.iterations != -1 and int(m.group(1)) != self.iterations: + raise + + # This could be done with lstrip, but the version of + # the Python library on my system doesn't have it. + # The installed version of Python is quite old. :( + + temp = m.group(2) + function_name = None + for i in range(len(temp)): + if temp[i] != ' ': + function_name = temp[i:] + break + + if function_name == None: + raise + + self.cycles[ function_name ] = int(m.group(3)) + self.iterations = int(m.group(1)) + + + def show_results(self): + for name in self.cycles: + print "%s -> %f" % (name, float(self.cycles[name]) / self.iterations) + + + def compare_results(self, other): + for name in self.cycles: + if other.cycles.has_key(name): + a = float(self.cycles[name]) / self.iterations + b = float(other.cycles[name]) / other.iterations + p = (100.0 * b / a) - 100.0 + print "%- 20s %7.2f - %7.2f = % -6.2f (%+.1f%%)" % (name, a, b, a - b, p) + return + + +def make_execution_string(lib, iterations): + if lib == None: + return "./api_speed %u" % (iterations) + else: + return "LD_PRELOAD=%s ./api_speed %u" % (lib, iterations) + + +def show_usage(): + print """Usage: %s [-i iterations] {library ...} + +The full path to one or more libGL libraries (including the full name of the +library) can be included on the command-line. Each library will be tested, +and the results compared. The first library listed will be used as the +"base line" for all comparisons.""" % (sys.argv[0]) + sys.exit(1) + + +if __name__ == '__main__': + try: + (args, trail) = getopt.getopt(sys.argv[1:], "i:") + except Exception,e: + show_usage() + + iterations = 1000000 + try: + for (arg,val) in args: + if arg == "-i": + iterations = int(val) + except Exception,e: + show_usage() + + + result_array = [] + names = [] + + + # If no libraries were specifically named, just run the test against + # the default system libGL. + + if len(trail) == 0: + s = make_execution_string( None, iterations ) + r = results() + r.process_file( os.popen(s) ) + result_array.append(r) + else: + for lib in trail: + s = make_execution_string( lib, iterations ) + r = results() + r.process_file( os.popen(s) ) + names.append(lib) + result_array.append(r) + + + # If the test was only run against one library, just show the results + # of the test run. Otherwise, compare each successive run against + # the first run. + + if len( result_array ) == 1: + result_array[0].show_results() + else: + for i in range(1, len( result_array )): + print "%s vs. %s" % (names[0], names[i]) + result_array[0].compare_results( result_array[i] ) + print "" |