From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17419 invoked by alias); 8 Sep 2011 22:36:15 -0000 Received: (qmail 16993 invoked by uid 22791); 8 Sep 2011 22:36:12 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from elasmtp-dupuy.atl.sa.earthlink.net (HELO elasmtp-dupuy.atl.sa.earthlink.net) (209.86.89.62) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 08 Sep 2011 22:35:56 +0000 Received: from [70.170.59.51] (helo=macbook2.local) by elasmtp-dupuy.atl.sa.earthlink.net with esmtpa (Exim 4.67) (envelope-from ) id 1R1nCN-0004xs-67 for gdb-patches@sourceware.org; Thu, 08 Sep 2011 18:35:55 -0400 Message-ID: <4E69434C.2080907@earthlink.net> Date: Thu, 08 Sep 2011 22:47:00 -0000 From: Stan Shebs User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:6.0.2) Gecko/20110902 Thunderbird/6.0.2 MIME-Version: 1.0 To: gdb-patches Subject: [PATCH] Tracepoint speed test Content-Type: multipart/mixed; boundary="------------060207040807000009020307" X-ELNK-Trace: ae6f8838ff913eba0cc1426638a40ef67e972de0d01da940bab7a3a941dcdd5ce8ce6a5b73baba12350badd9bab72f9c350badd9bab72f9c350badd9bab72f9c X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-09/txt/msg00153.txt.bz2 This is a multi-part message in MIME format. --------------060207040807000009020307 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1025 This patch adds a test of tracepoint speed to the testsuite. It's a little complicated, because it exercises both slow and fast tracepoints, it attempts to adjust its looping time to accommodate different kinds of hardware, and the test program is set up to be useful for interactive experimentation as well. So I'm going to leave it up for review for a week or so, in case anybody has any questions or comments. There are a couple things to note: 1) it adjusts loop iterations by simply doubling the number until the test loops run for at least a second each, with a couple checks to keep it from getting out of hand, and 2) it uses getrusage to compute CPU time. While it seems appropriate to conditionalize this from configure, I note that our test cases never seem to use configury, instead just letting the compilation fail and the test return early. Stan stan@codesourcery.com 2011-09-08 Stan Shebs * gdb.trace/tspeed.exp: New file. * gdb.trace/tspeed.c: New file. --------------060207040807000009020307 Content-Type: text/plain; x-mac-type="0"; x-mac-creator="0"; name="tspeed-patch-1" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="tspeed-patch-1" Content-length: 9744 Index: gdb.trace/tspeed.c =================================================================== RCS file: gdb.trace/tspeed.c diff -N gdb.trace/tspeed.c *** /dev/null 1 Jan 1970 00:00:00 -0000 --- gdb.trace/tspeed.c 8 Sep 2011 22:11:35 -0000 *************** *** 0 **** --- 1,184 ---- + /* This testcase is part of GDB, the GNU debugger. + + Copyright 2010, 2011 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + + /* This program tests tracepoint speed. It consists of two identical + loops, which in normal execution will run for exactly the same + amount of time. A tracepoint in the second loop will slow it down + by some amount, and then the program will report the slowdown + observed. */ + + /* While primarily designed for the testsuite, it can also be used + for interactive testing. */ + + #include + #include + #include + #include + + int trace_speed_test (void); + + /* We mark these globals as volatile so the speed-measuring loops + don't get totally emptied out at high optimization levels. */ + + volatile int globfoo, globfoo2, globfoo3; + + volatile short globarr[80000]; + + int init_iters = 10 * 1000; + + int iters; + + int max_iters = 1000 * 1000 * 1000; + + int numtps = 1; + + unsigned long long now2, now3, now4, now5; + int total1, total2, idelta, mindelta, nsdelta; + int nspertp = 0; + + /* Return CPU usage (both user and system - trap-based tracepoints use + a bunch of system time). */ + + unsigned long long + myclock () + { + struct timeval tm, tm2; + struct rusage ru; + getrusage (RUSAGE_SELF, &ru); + tm = ru.ru_utime; + tm2 = ru.ru_stime; + return (((unsigned long long) tm.tv_sec) * 1000000) + tm.tv_usec + + (((unsigned long long) tm2.tv_sec) * 1000000) + tm2.tv_usec; + } + + int + main(int argc, char **argv) + { + int problem; + + iters = init_iters; + + while (1) + { + numtps = 1; /* set pre-run breakpoint here */ + + /* Keep trying the speed test, with more iterations, until + we get to a reasonable number. */ + while (problem = trace_speed_test()) + { + /* If iteration isn't working, give up. */ + if (iters > max_iters) + { + printf ("Gone over %d iterations, giving up\n", max_iters); + break; + } + if (problem < 0) + { + printf ("Negative times, giving up\n", max_iters); + break; + } + + iters *= 2; + printf ("Doubled iterations to %d\n", iters); + } + + printf ("Tracepoint time is %d ns\n", nspertp); + + /* This is for the benefit of interactive testing and attaching, + keeps the program from pegging the machine. */ + sleep (1); /* set post-run breakpoint here */ + + /* Issue a little bit of output periodically, so we can see if + program is alive or hung. */ + printf ("%s keeping busy, clock=%llu\n", argv[0], myclock ()); + } + return 0; + } + + int + trace_speed_test (void) + { + int i; + + /* Overall loop run time deltas under 1 ms are likely noise and + should be ignored. */ + mindelta = 1000; + + // The bodies of the two loops following must be identical. + + now2 = myclock (); + globfoo2 = 1; + for (i = 0; i < iters; ++i) + { + globfoo2 *= 45; + globfoo2 += globfoo + globfoo3; + globfoo2 *= globfoo + globfoo3; + globfoo2 -= globarr[4] + globfoo3; + globfoo2 *= globfoo + globfoo3; + globfoo2 += globfoo + globfoo3; + } + now3 = myclock (); + total1 = now3 - now2; + + now4 = myclock (); + globfoo2 = 1; + for (i = 0; i < iters; ++i) + { + globfoo2 *= 45; + globfoo2 += globfoo + globfoo3; /* set tracepoint here */ + globfoo2 *= globfoo + globfoo3; + globfoo2 -= globarr[4] + globfoo3; + globfoo2 *= globfoo + globfoo3; + globfoo2 += globfoo + globfoo3; + } + now5 = myclock (); + total2 = now5 - now4; + + /* Report on the test results. */ + + nspertp = 0; + + idelta = total2 - total1; + + printf ("Loops took %d usec and %d usec, delta is %d usec, %d iterations\n", + total1, total2, idelta, iters); + + /* If the second loop seems to run faster, things are weird so give up. */ + if (idelta < 0) + return -1; + + if (idelta > mindelta + /* Total test time should be between 2 and 5 seconds. */ + && (total1 + total2) > (2 * 1000000) + && (total1 + total2) < (5 * 1000000)) + { + nsdelta = (((unsigned long long) idelta) * 1000) / iters; + printf ("Second loop took %d ns longer per iter than first\n", nsdelta); + nspertp = nsdelta / numtps; + printf ("%d ns per tracepoint\n", nspertp); + printf ("Base iteration time %d ns\n", + ((int) (((unsigned long long) total1) * 1000) / iters)); + printf ("Total test time %d secs\n", ((int) ((now5 - now2) / 1000000))); + + /* Speed test ran with no problem. */ + return 0; + } + + /* The test run was too brief, or otherwise not useful. */ + return 1; + } Index: gdb.trace/tspeed.exp =================================================================== RCS file: gdb.trace/tspeed.exp diff -N gdb.trace/tspeed.exp *** /dev/null 1 Jan 1970 00:00:00 -0000 --- gdb.trace/tspeed.exp 8 Sep 2011 22:11:35 -0000 *************** *** 0 **** --- 1,140 ---- + # Copyright 2011 + # Free Software Foundation, Inc. + + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation; either version 3 of the License, or + # (at your option) any later version. + # + # This program is distributed in the hope that it will be useful, + # but WITHOUT ANY WARRANTY; without even the implied warranty of + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + # GNU General Public License for more details. + # + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + + load_lib "trace-support.exp" + + set testfile "tspeed" + set srcfile ${testfile}.c + set executable $testfile + set binfile $objdir/$subdir/$executable + + set ipalib $objdir/../gdbserver/libinproctrace.so + + if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \ + executable [concat {debug nowarnings c} libs=$ipalib]] != "" } { + untested tspeed.exp + return -1 + } + + # Typically we need a little extra time for this test. + set timeout 180 + + set ws "\[\r\n\t \]+" + set cr "\[\r\n\]+" + + # + # Utility procs + # + + proc prepare_for_trace_test {} { + global executable + + clean_restart $executable + + runto_main + + set testline [gdb_get_line_number "set pre-run breakpoint here"] + + gdb_test "break $testline" ".*" "" + + set testline [gdb_get_line_number "set post-run breakpoint here"] + + gdb_test "break $testline" ".*" "" + } + + proc run_trace_experiment {} { + + gdb_test "continue" \ + ".*Breakpoint \[0-9\]+, main .*" \ + "advance to trace begin" + + gdb_test_no_output "tstart" "start trace experiment" + + gdb_test "continue" \ + ".*Breakpoint \[0-9\]+, main .*" \ + "advance through tracing" + + gdb_test "tstatus" ".*Trace .*" "check on trace status" + + gdb_test "tstop" "" "" + } + + proc gdb_slow_trace_speed_test { } { + + gdb_delete_tracepoints + + gdb_test "print iters = init_iters" ".* = .*"; + + set testline [gdb_get_line_number "set tracepoint here"] + + gdb_test "trace $testline if (globfoo != 12 && globfoo2 == 45)" \ + "Tracepoint \[0-9\]+ at .*" \ + "set slow tracepoint" + + # Begin the test. + run_trace_experiment + } + + proc gdb_fast_trace_speed_test { } { + + gdb_delete_tracepoints + + gdb_test "print iters = init_iters" ".* = .*"; + + set run_ftrace 0 + + set testline [gdb_get_line_number "set tracepoint here"] + + gdb_test_multiple "ftrace $testline if (globfoo != 12 && globfoo2 == 45)" \ + "set conditional fast tracepoint" { + -re "Fast tracepoint \[0-9\]+ at .*" { + pass "set conditional fast tracepoint, done" + set run_ftrace 1 + } + -re "May not have a fast tracepoint at .*" { + pass "set conditional fast tracepoint, not allowed at line" + } + } + + # If the fast tracepoint couldn't be set, don't bother with the run. + if { $run_ftrace == 1 } then { + + # Begin the test. + run_trace_experiment + } + } + + proc gdb_trace_collection_test {} { + + prepare_for_trace_test + + gdb_slow_trace_speed_test + + gdb_fast_trace_speed_test + } + + clean_restart $executable + runto_main + + # We generously give ourselves one "pass" if we successfully + # detect that this test cannot be run on this target! + if { ![gdb_target_supports_trace] } then { + pass "Current target does not support trace" + return 1; + } + + # Body of test encased in a proc so we can return prematurely. + gdb_trace_collection_test --------------060207040807000009020307--