util: Remove homegrown Windows KM profiler.
authorJosé Fonseca <jfonseca@vmware.com>
Tue, 3 Nov 2009 19:47:51 +0000 (19:47 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Wed, 4 Nov 2009 12:15:29 +0000 (12:15 +0000)
It's not sampling based so its results are biased towards functions called
many times.

bin/win32kprof.py [deleted file]
scons/gallium.py
scons/generic.py
src/gallium/auxiliary/util/SConscript
src/gallium/auxiliary/util/u_debug.h
src/gallium/auxiliary/util/u_debug_profile.c [deleted file]

diff --git a/bin/win32kprof.py b/bin/win32kprof.py
deleted file mode 100755 (executable)
index c36317d..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-#!/usr/bin/env python
-##########################################################################
-# 
-# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
-# 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 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 TUNGSTEN GRAPHICS 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.
-# 
-##########################################################################
-
-
-import sys
-import optparse
-import re
-import struct
-
-from gprof2dot import Call, Function, Profile
-from gprof2dot import CALLS, SAMPLES, TIME, TIME_RATIO, TOTAL_TIME, TOTAL_TIME_RATIO
-from gprof2dot import DotWriter, TEMPERATURE_COLORMAP
-
-
-__version__ = '0.1'
-
-
-class ParseError(Exception):
-    pass
-
-
-class MsvcDemangler:
-    # http://www.kegel.com/mangle.html
-
-    def __init__(self, symbol):
-        self._symbol = symbol
-        self._pos = 0
-
-    def lookahead(self):
-        return self._symbol[self._pos]
-
-    def consume(self):
-        ret = self.lookahead()
-        self._pos += 1
-        return ret
-    
-    def match(self, c):
-        if self.lookahead() != c:
-            raise ParseError
-        self.consume()
-
-    def parse(self):
-        self.match('?')
-        name = self.parse_name()
-        qualifications = self.parse_qualifications()
-        return '::'.join(qualifications + [name])
-
-    def parse_name(self):
-        if self.lookahead() == '?':
-            return self.consume() + self.consume()
-        else:
-            name = self.parse_id()
-            self.match('@')
-            return name
-
-    def parse_qualifications(self):
-        qualifications = []
-        while self.lookahead() != '@':
-            name = self.parse_id()
-            qualifications.append(name)
-            self.match('@')
-        return qualifications
-
-    def parse_id(self):
-        s = ''
-        while True:
-            c = self.lookahead()
-            if c.isalnum() or c in '_':
-                s += c
-                self.consume()
-            else:
-                break
-        return s
-
-
-def demangle(name):
-    if name.startswith('_'):
-        name = name[1:]
-        idx = name.rfind('@')
-        if idx != -1 and name[idx+1:].isdigit():
-            name = name[:idx]
-        return name
-    if name.startswith('?'):
-        demangler = MsvcDemangler(name)
-        return demangler.parse()
-    return name
-
-
-class Reader:
-
-    def __init__(self):
-        self.symbols = []
-        self.symbol_cache = {}
-        self.base_addr = None
-    
-    def read_map(self, mapfile):
-        # See http://msdn.microsoft.com/en-us/library/k7xkk3e2.aspx
-        last_addr = 0
-        last_name = 0
-        for line in file(mapfile, "rt"):
-            fields = line.split()
-            try:
-                section_offset, name, addr, type, lib_object = fields
-            except ValueError:
-                continue
-            if type != 'f':
-                continue
-            section, offset = section_offset.split(':')
-            addr = int(offset, 16)
-            self.symbols.append((addr, name))
-            last_addr = addr
-            last_name = name
-
-        # sort symbols
-        self.symbols.sort(key = lambda (addr, name): addr)
-
-    def lookup_addr(self, addr):
-        try:
-            return self.symbol_cache[addr]
-        except KeyError:
-            pass
-
-        tolerance = 4196
-        s, e = 0, len(self.symbols)
-        while s != e:
-            i = (s + e)//2
-            start_addr, name = self.symbols[i]
-            try:
-                end_addr, next_name = self.symbols[i + 1]
-            except IndexError:
-                end_addr = start_addr + tolerance
-            if addr < start_addr:
-                e = i
-                continue
-            if addr == end_addr:
-                return next_name, addr - start_addr
-            if addr > end_addr:
-                s = i
-                continue
-            return name, addr - start_addr
-        raise ValueError
-
-    def lookup_symbol(self, name):
-        for symbol_addr, symbol_name in self.symbols:
-            if name == symbol_name:
-                return symbol_addr
-        return 0
-
-    def read_data(self, data):
-        profile = Profile()
-
-        fp = file(data, "rb")
-        entry_format = "IIII"
-        entry_size = struct.calcsize(entry_format)
-        caller = None
-        caller_stack = []
-        while True:
-            entry = fp.read(entry_size)
-            if len(entry) < entry_size:
-                break
-            caller_addr, callee_addr, samples_lo, samples_hi = struct.unpack(entry_format, entry)
-            if caller_addr == 0 and callee_addr == 0:
-                continue
-
-            if self.base_addr is None:
-                ref_addr = self.lookup_symbol('___debug_profile_reference@0')
-                if ref_addr:
-                    self.base_addr = (caller_addr - ref_addr) & ~(options.align - 1)
-                else:
-                    self.base_addr = 0
-                sys.stderr.write('Base addr: %08x\n' % self.base_addr)
-
-            samples = (samples_hi << 32) | samples_lo
-            
-            try:
-                caller_raddr = caller_addr - self.base_addr
-                caller_sym, caller_ofs = self.lookup_addr(caller_raddr)
-
-                try:
-                    caller = profile.functions[caller_sym]
-                except KeyError:
-                    caller_name = demangle(caller_sym)
-                    caller = Function(caller_sym, caller_name)
-                    profile.add_function(caller)
-                    caller[CALLS] = 0
-                    caller[SAMPLES] = 0
-            except ValueError:
-                caller = None
-
-            if not callee_addr:
-                if caller:
-                    caller[SAMPLES] += samples
-            else:
-                callee_raddr = callee_addr - self.base_addr
-                callee_sym, callee_ofs = self.lookup_addr(callee_raddr)
-
-                try:
-                    callee = profile.functions[callee_sym]
-                except KeyError:
-                    callee_name = demangle(callee_sym)
-                    callee = Function(callee_sym, callee_name)
-                    profile.add_function(callee)
-                    callee[CALLS] = samples
-                    callee[SAMPLES] = 0
-                else:
-                    callee[CALLS] += samples
-
-                if caller is not None:
-                    try:
-                        call = caller.calls[callee.id]
-                    except KeyError:
-                        call = Call(callee.id)
-                        call[CALLS] = samples
-                        caller.add_call(call)
-                    else:
-                        call[CALLS] += samples
-            
-            if options.verbose:
-                if not callee_addr:
-                    sys.stderr.write('%s+%u: %u\n' % (caller_sym, caller_ofs, samples))
-                else:
-                    sys.stderr.write('%s+%u -> %s+%u: %u\n' % (caller_sym, caller_ofs, callee_sym, callee_ofs, samples))
-
-        # compute derived data
-        profile.validate()
-        profile.find_cycles()
-        profile.aggregate(SAMPLES)
-        profile.ratio(TIME_RATIO, SAMPLES)
-        profile.call_ratios(CALLS)
-        profile.integrate(TOTAL_TIME_RATIO, TIME_RATIO)
-
-        return profile
-
-
-def main():
-    parser = optparse.OptionParser(
-        usage="\n\t%prog [options] [file] ...",
-        version="%%prog %s" % __version__)
-    parser.add_option(
-        '-a', '--align', metavar='NUMBER',
-        type="int", dest="align", default=16,
-        help="section alignment")
-    parser.add_option(
-        '-m', '--map', metavar='FILE',
-        type="string", dest="map",
-        help="map file")
-    parser.add_option(
-        '-b', '--base', metavar='FILE',
-        type="string", dest="base",
-        help="base addr")
-    parser.add_option(
-        '-n', '--node-thres', metavar='PERCENTAGE',
-        type="float", dest="node_thres", default=0.5,
-        help="eliminate nodes below this threshold [default: %default]")
-    parser.add_option(
-        '-e', '--edge-thres', metavar='PERCENTAGE',
-        type="float", dest="edge_thres", default=0.1,
-        help="eliminate edges below this threshold [default: %default]")
-    parser.add_option(
-        '-v', '--verbose',
-        action="count",
-        dest="verbose", default=0,
-        help="verbose output")
-
-    global options
-    (options, args) = parser.parse_args(sys.argv[1:])
-
-    reader = Reader()
-    if options.base is not None:
-        reader.base_addr = int(options.base, 16)
-    if options.map is not None:
-        reader.read_map(options.map)
-    for arg in args:
-        profile = reader.read_data(arg)
-        profile.prune(options.node_thres/100.0, options.edge_thres/100.0)
-        output = sys.stdout
-        dot = DotWriter(output)
-        colormap = TEMPERATURE_COLORMAP
-        dot.graph(profile, colormap)
-
-
-if __name__ == '__main__':
-    main()
-
index a6d69fd16d5342cee065173a25975c2b9c8f7dd0..483bd5d29eb7fd8716ca820f825a0c851b8fa8c1 100644 (file)
@@ -392,11 +392,6 @@ def generate(env):
                 '/O2', # optimize for speed
                 #'/fp:fast', # fast floating point 
             ]
-        if env['profile']:
-            ccflags += [
-                '/Gh', # enable _penter hook function
-                '/GH', # enable _pexit hook function
-            ]
         ccflags += [
             '/W3', # warning level
             #'/Wp64', # enable 64 bit porting warnings
index a3b73b09b9e3ed0edfdb59a7c79369f2407c95d6..859bf2ae64ea494683f7d0d1f688b3a982896f34 100644 (file)
@@ -406,8 +406,6 @@ def generate(env):
             ccflags += ['-O0', '-g3'] # mingw 4.2.1 optimizer is broken
         else:
             ccflags += ['-O3', '-g0']
-        if env['profile']:
-            ccflags += ['-pg']
         if env['machine'] == 'x86':
             ccflags += [
                 '-m32',
@@ -450,11 +448,6 @@ def generate(env):
               '/Ot', # favor code speed
               #'/fp:fast', # fast floating point 
             ]
-        if env['profile']:
-            ccflags += [
-                '/Gh', # enable _penter hook function
-                '/GH', # enable _pexit hook function
-            ]
         ccflags += [
             '/W3', # warning level
             #'/Wp64', # enable 64 bit porting warnings
index 2187935fa40f0fc699bd8d13aa241fe7c12ae822..8d99106d0b852b252fb62110cadf46437fc8bd0e 100644 (file)
@@ -28,7 +28,6 @@ util = env.ConvenienceLibrary(
                'u_debug.c',
                'u_debug_dump.c',
                'u_debug_memory.c',
-               'u_debug_profile.c',
                'u_debug_stack.c',
                'u_debug_symbol.c',
                'u_draw_quad.c',
index b8c56fd600c552e2cf7f5f343b4c484dbb801d6e..abd834c741a693560bd97a3dbd62348baf9a300c 100644 (file)
@@ -351,17 +351,6 @@ void
 debug_memory_end(unsigned long beginning);
 
 
-#if defined(PROFILE) && defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
-
-void
-debug_profile_start(void);
-
-void 
-debug_profile_stop(void);
-
-#endif
-
-
 #ifdef DEBUG
 struct pipe_surface;
 struct pipe_transfer;
diff --git a/src/gallium/auxiliary/util/u_debug_profile.c b/src/gallium/auxiliary/util/u_debug_profile.c
deleted file mode 100644 (file)
index d765b50..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
- * 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 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 TUNGSTEN GRAPHICS 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.
- * 
- **************************************************************************/
-
-/**
- * @file
- * Poor-man profiling.
- * 
- * @author José Fonseca <jrfonseca@tungstengraphics.com>
- * 
- * @sa http://blogs.msdn.com/joshpoley/archive/2008/03/12/poor-man-s-profiler.aspx
- * @sa http://www.johnpanzer.com/aci_cuj/index.html
- */
-
-#include "pipe/p_config.h" 
-
-#if defined(PROFILE) && defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY)
-
-#include <windows.h>
-#include <winddi.h>
-
-#include "util/u_debug.h" 
-#include "util/u_string.h" 
-
-
-#define PROFILE_TABLE_SIZE (1024*1024)
-#define FILE_NAME_SIZE 256
-
-struct debug_profile_entry
-{
-   uintptr_t caller;
-   uintptr_t callee;
-   uint64_t samples;
-};
-
-static unsigned long enabled = 0;
-
-static WCHAR wFileName[FILE_NAME_SIZE] = L"\\??\\c:\\00000000.prof";
-static ULONG_PTR iFile = 0;
-
-static struct debug_profile_entry *table = NULL;
-static unsigned long free_table_entries = 0;
-static unsigned long max_table_entries = 0;
-
-uint64_t start_stamp = 0;
-uint64_t end_stamp = 0;
-
-
-static void
-debug_profile_entry(uintptr_t caller, uintptr_t callee, uint64_t samples)
-{
-   unsigned hash = ( caller + callee ) & PROFILE_TABLE_SIZE - 1;
-   
-   while(1) {
-      if(table[hash].caller == 0 && table[hash].callee == 0) {
-         table[hash].caller = caller;
-         table[hash].callee = callee;
-         table[hash].samples = samples;
-         --free_table_entries;
-         break;
-      }
-      else if(table[hash].caller == caller && table[hash].callee == callee) {
-         table[hash].samples += samples;
-         break;
-      }
-      else {
-         ++hash;
-      }
-   }
-}
-
-
-static uintptr_t caller_stack[1024];
-static unsigned last_caller = 0;
-
-
-static int64_t delta(void) {
-   int64_t result = end_stamp - start_stamp;
-   if(result > UINT64_C(0xffffffff))
-      result = 0;
-   return result;
-}
-
-
-static void __cdecl 
-debug_profile_enter(uintptr_t callee)
-{
-   uintptr_t caller = last_caller ? caller_stack[last_caller - 1] : 0;
-                
-   if (caller)
-      debug_profile_entry(caller, 0, delta());
-   debug_profile_entry(caller, callee, 1);
-   caller_stack[last_caller++] = callee;
-}
-
-
-static void __cdecl
-debug_profile_exit(uintptr_t callee)
-{
-   debug_profile_entry(callee, 0, delta());
-   if(last_caller)
-      --last_caller;
-}
-   
-   
-/**
- * Called at the start of every method or function.
- * 
- * @sa http://msdn.microsoft.com/en-us/library/c63a9b7h.aspx
- */
-void __declspec(naked) __cdecl 
-_penter(void) {
-   _asm {
-      push eax
-      mov eax, [enabled]
-      test eax, eax
-      jz skip
-
-      push edx
-      
-      rdtsc
-      mov dword ptr [end_stamp], eax
-      mov dword ptr [end_stamp+4], edx
-
-      xor eax, eax
-      mov [enabled], eax
-
-      mov eax, [esp+8]
-
-      push ebx
-      push ecx
-      push ebp
-      push edi
-      push esi
-
-      push eax
-      call debug_profile_enter
-      add esp, 4
-
-      pop esi
-      pop edi
-      pop ebp
-      pop ecx
-      pop ebx
-
-      mov eax, 1
-      mov [enabled], eax 
-
-      rdtsc
-      mov dword ptr [start_stamp], eax
-      mov dword ptr [start_stamp+4], edx
-      
-      pop edx
-skip:
-      pop eax
-      ret
-   }
-}
-
-
-/**
- * Called at the end of Calls the end of every method or function.
- * 
- * @sa http://msdn.microsoft.com/en-us/library/xc11y76y.aspx
- */
-void __declspec(naked) __cdecl 
-_pexit(void) {
-   _asm {
-      push eax
-      mov eax, [enabled]
-      test eax, eax
-      jz skip
-
-      push edx
-      
-      rdtsc
-      mov dword ptr [end_stamp], eax
-      mov dword ptr [end_stamp+4], edx
-
-      xor eax, eax
-      mov [enabled], eax
-
-      mov eax, [esp+8]
-
-      push ebx
-      push ecx
-      push ebp
-      push edi
-      push esi
-
-      push eax
-      call debug_profile_exit
-      add esp, 4
-
-      pop esi
-      pop edi
-      pop ebp
-      pop ecx
-      pop ebx
-
-      mov eax, 1
-      mov [enabled], eax 
-
-      rdtsc
-      mov dword ptr [start_stamp], eax
-      mov dword ptr [start_stamp+4], edx
-      
-      pop edx
-skip:
-      pop eax
-      ret
-   }
-}
-
-
-/**
- * Reference function for calibration. 
- */
-void __declspec(naked) 
-__debug_profile_reference(void) {
-   _asm {
-      call _penter
-      call _pexit
-      ret
-   }
-}
-
-
-void
-debug_profile_start(void)
-{
-   WCHAR *p;
-
-   /* increment starting from the less significant digit */
-   p = &wFileName[14];
-   while(1) {
-      if(*p == '9') {
-         *p-- = '0';
-      }
-      else {
-         *p += 1;
-         break;
-      }
-   }
-
-   table = EngMapFile(wFileName, 
-                      PROFILE_TABLE_SIZE*sizeof(struct debug_profile_entry), 
-                      &iFile);
-   if(table) {
-      unsigned i;
-      
-      free_table_entries = max_table_entries = PROFILE_TABLE_SIZE;
-      memset(table, 0, PROFILE_TABLE_SIZE*sizeof(struct debug_profile_entry));
-      
-      table[0].caller = (uintptr_t)&__debug_profile_reference;
-      table[0].callee = 0;
-      table[0].samples = 0;
-      --free_table_entries;
-
-      _asm {
-         push edx
-         push eax
-      
-         rdtsc
-         mov dword ptr [start_stamp], eax
-         mov dword ptr [start_stamp+4], edx
-         
-         pop edx
-         pop eax
-      }
-
-      last_caller = 0;
-      
-      enabled = 1;
-
-      for(i = 0; i < 8; ++i) {
-         _asm {
-            call __debug_profile_reference
-         }
-      }
-   }
-}
-
-
-void 
-debug_profile_stop(void)
-{
-   enabled = 0;
-
-   if(iFile)
-      EngUnmapFile(iFile);
-   iFile = 0;
-   table = NULL;
-   free_table_entries = max_table_entries = 0;
-}
-
-#endif /* PROFILE */