IDE profiler tab with just source and line number

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
PrincieD
Addict
Addict
Posts: 891
Joined: Wed Aug 10, 2005 2:08 pm
Location: Yorkshire, England
Contact:

IDE profiler tab with just source and line number

Post by PrincieD »

The graphs are pretty with the profiler but completely useless having to zoom in ridiculousness amounts and memorize the line number in question. Can we have just another tab please where we have catagaorized source includes with the actual line numbers and then a double click takes you to the source and line number?

When actually trying to resolve performance issues / bottlenecks this would be a godsend!

So what I think everyone would like is an ordered list in descending order from most accessed to least accessed where I can instantly click on the highest priority line of code and start optimising it - I think everyone would agree.

Currently with the graph implementation it's like trying to find a needle in a haystack - looks great - oh there's a big performance dip there (how the hell do I navigate to it), zoom in, zoom in, zoom in - I can just about figure out this line of code is being called a lot??

To be blunt, the profiler is a pretty toy at the moment. Just use the same data to create a nice ordered list.

(slightly ranty! I do appreciate all the excellent work gone into PB)

Cheers!

Chris.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
PrincieD
Addict
Addict
Posts: 891
Joined: Wed Aug 10, 2005 2:08 pm
Location: Yorkshire, England
Contact:

Re: IDE profiler tab with just source and line number

Post by PrincieD »

*bump! Loving the new features of the IDE and I think this would be a fantastic improvement too (with not too much work to implement hopefully). ProGUI V3 is currently at over 50,000 lines of code with multiple includes and I'm approaching the stage where I want to squeeze as much speed out of it as possible and identify any bottle necks but it's very tedious using the current profiler.

Thanks again for all the great work PB team :)

What are your guys thoughts?

Thanks!

Chris.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
User avatar
idle
Always Here
Always Here
Posts: 6154
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: IDE profiler tab with just source and line number

Post by idle »

you could use this to profile functions. it just outputs the time ms and avg cycles, 0 no rollover error
lower cycles is the target
CPU Frequency 2.72 ghz
foo sum time 999 ms avg cycles 2,713,995,125 0
bar sum time 100 ms avg cycles 272,185,515 0

Code: Select all

#ENABLE_PROFILE=1   ;Enables profiler or to disable ENABLE_PROFILE=0   
CompilerIf #ENABLE_PROFILE=1
  CompilerIf Defined(PB_Compiler_Backend,#PB_Constant) 
    CompilerIf #PB_Compiler_Backend=#PB_Backend_C
      CompilerIf #PB_Compiler_Processor = #PB_Processor_x64 Or #PB_Compiler_Processor = #PB_Processor_x86 
        Procedure.q GetRDTSC()
          Protected t.q
          !unsigned hi, lo;
          !__asm__ __volatile__ ("lfence\n rdtsc\n lfence" : "=a"(lo), "=d"(hi));
          !v_t =((unsigned long long)lo)|(((unsigned long long)hi)<<32 );
          ProcedureReturn t
        EndProcedure
      CompilerElseIf #PB_Compiler_Processor = #PB_Processor_Arm64 Or #PB_Compiler_Processor = #PB_Processor_Arm32 
        Procedure.q GetRDTSC()
        Protected pmuseren.l,pmcntenset.l,pmccntr.l;
        !asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(v_pmuseren));
        If pmuseren & 1 
          !asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(v_pmcntenset));
          If pmcntenset & $80000000 
            !asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(v_pmccntr));
            t = pmccntr
            ProcedureReturn t << 6 
          EndIf 
        EndIf 
        EndProcedure 
     CompilerEndIf 
    CompilerElse
      Procedure.q GetRDTSC()
        Protected hi.q,lo.q,res.q 
        DisableDebugger
        !lfence 
        !rdtsc
        !lfence
        !mov [p.v_hi], edx
        !mov [p.v_lo], eax 
        res = hi
        res << 32
        res | lo
        ProcedureReturn res
        EnableDebugger 
      EndProcedure
    CompilerEndIf
  CompilerElse
    Procedure.q GetRDTSC()
      Protected hi.q,lo.q,res.q 
      DisableDebugger
      !lfence 
      !rdtsc
      !lfence
      !mov [p.v_hi], edx
      !mov [p.v_lo], eax 
      res = hi
      res << 32
      res | lo
      EnableDebugger 
    EndProcedure
  CompilerEndIf  
  
  Procedure.q GetFrequency() 
    Protected t1.q,t2.q,result 
    Repeat     
      t1 = GetRDTSC()
      Delay(128) 
      t2 = GetRDTSC()
      If t2 - t1 > 0 
        result = ((t2-t1) / (128)) 
        Break  
      EndIf    
    ForEver 
    ProcedureReturn result 
  EndProcedure   
  
  Structure profile 
    count.i
    err.i
    sumtime.q 
    st.q
    et.q 
  EndStructure 
  
  Global NewMap prof.profile() 
  Global prof_msfreq.i = GetFrequency() 
  
  Macro BeginProfile(name) 
    prof(name)\count + 1 
    prof(name)\st = GetRDTSC() 
  EndMacro 
  
  Macro EndProfile(name) 
    prof(name)\et = GetRDTSC() 
    If prof(name)\et > prof(name)\st 
      prof()\sumtime + prof(name)\et - prof(name)\st
    Else  
      prof()\count - 1    ;ignore rollover if st > et    
      prof()\err + 1      ;indicates a timeing error     
    EndIf   
  EndMacro   
  
  Macro PrintProfile() 
    PrintN("CPU Frequency " + FormatNumber(prof_msfreq/1000000.0,2,".",",") + " ghz") 
    ForEach prof()  
      If prof()\count 
        PrintN(MapKey(prof())  + " sum time " + FormatNumber(prof()\sumtime / prof_msfreq ,0,".",",") + " ms avg cycles " + FormatNumber(prof()\sumtime / prof()\count,0,".",",") + " " + Str(prof()\err )) 
      EndIf   
    Next 
  EndMacro    
CompilerElse 
  Macro BeginProfile(name) : EndMacro 
  Macro EndProfile(name) : EndMacro 
  Macro PrintProfile() : EndMacro 
CompilerEndIf 
CompilerIf  #PB_Compiler_IsMainFile 
  
  Procedure foo() 
    
    BeginProfile(#PB_Compiler_Procedure) 
    
    Delay(1000) 
    
    EndProfile(#PB_Compiler_Procedure) 
    
  EndProcedure 
  
  Procedure bar() 
    
     BeginProfile(#PB_Compiler_Procedure) 
    
    Delay(100) 
    
    EndProfile(#PB_Compiler_Procedure) 
    
  EndProcedure   
  
  OpenConsole()
  
  foo() 
  bar() 
  
  PrintProfile() 
  
  Input() 
  CloseConsole() 
  
  
CompilerEndIf 
PrincieD
Addict
Addict
Posts: 891
Joined: Wed Aug 10, 2005 2:08 pm
Location: Yorkshire, England
Contact:

Re: IDE profiler tab with just source and line number

Post by PrincieD »

idle wrote: Wed Dec 17, 2025 9:59 pm you could use this to profile functions. it just outputs the time ms and avg cycles, 0 no rollover error
lower cycles is the target
CPU Frequency 2.72 ghz
foo sum time 999 ms avg cycles 2,713,995,125 0
bar sum time 100 ms avg cycles 272,185,515 0

Code: Select all

#ENABLE_PROFILE=1   ;Enables profiler or to disable ENABLE_PROFILE=0   
CompilerIf #ENABLE_PROFILE=1
  CompilerIf Defined(PB_Compiler_Backend,#PB_Constant) 
    CompilerIf #PB_Compiler_Backend=#PB_Backend_C
      CompilerIf #PB_Compiler_Processor = #PB_Processor_x64 Or #PB_Compiler_Processor = #PB_Processor_x86 
        Procedure.q GetRDTSC()
          Protected t.q
          !unsigned hi, lo;
          !__asm__ __volatile__ ("lfence\n rdtsc\n lfence" : "=a"(lo), "=d"(hi));
          !v_t =((unsigned long long)lo)|(((unsigned long long)hi)<<32 );
          ProcedureReturn t
        EndProcedure
      CompilerElseIf #PB_Compiler_Processor = #PB_Processor_Arm64 Or #PB_Compiler_Processor = #PB_Processor_Arm32 
        Procedure.q GetRDTSC()
        Protected pmuseren.l,pmcntenset.l,pmccntr.l;
        !asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(v_pmuseren));
        If pmuseren & 1 
          !asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(v_pmcntenset));
          If pmcntenset & $80000000 
            !asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(v_pmccntr));
            t = pmccntr
            ProcedureReturn t << 6 
          EndIf 
        EndIf 
        EndProcedure 
     CompilerEndIf 
    CompilerElse
      Procedure.q GetRDTSC()
        Protected hi.q,lo.q,res.q 
        DisableDebugger
        !lfence 
        !rdtsc
        !lfence
        !mov [p.v_hi], edx
        !mov [p.v_lo], eax 
        res = hi
        res << 32
        res | lo
        ProcedureReturn res
        EnableDebugger 
      EndProcedure
    CompilerEndIf
  CompilerElse
    Procedure.q GetRDTSC()
      Protected hi.q,lo.q,res.q 
      DisableDebugger
      !lfence 
      !rdtsc
      !lfence
      !mov [p.v_hi], edx
      !mov [p.v_lo], eax 
      res = hi
      res << 32
      res | lo
      EnableDebugger 
    EndProcedure
  CompilerEndIf  
  
  Procedure.q GetFrequency() 
    Protected t1.q,t2.q,result 
    Repeat     
      t1 = GetRDTSC()
      Delay(128) 
      t2 = GetRDTSC()
      If t2 - t1 > 0 
        result = ((t2-t1) / (128)) 
        Break  
      EndIf    
    ForEver 
    ProcedureReturn result 
  EndProcedure   
  
  Structure profile 
    count.i
    err.i
    sumtime.q 
    st.q
    et.q 
  EndStructure 
  
  Global NewMap prof.profile() 
  Global prof_msfreq.i = GetFrequency() 
  
  Macro BeginProfile(name) 
    prof(name)\count + 1 
    prof(name)\st = GetRDTSC() 
  EndMacro 
  
  Macro EndProfile(name) 
    prof(name)\et = GetRDTSC() 
    If prof(name)\et > prof(name)\st 
      prof()\sumtime + prof(name)\et - prof(name)\st
    Else  
      prof()\count - 1    ;ignore rollover if st > et    
      prof()\err + 1      ;indicates a timeing error     
    EndIf   
  EndMacro   
  
  Macro PrintProfile() 
    PrintN("CPU Frequency " + FormatNumber(prof_msfreq/1000000.0,2,".",",") + " ghz") 
    ForEach prof()  
      If prof()\count 
        PrintN(MapKey(prof())  + " sum time " + FormatNumber(prof()\sumtime / prof_msfreq ,0,".",",") + " ms avg cycles " + FormatNumber(prof()\sumtime / prof()\count,0,".",",") + " " + Str(prof()\err )) 
      EndIf   
    Next 
  EndMacro    
CompilerElse 
  Macro BeginProfile(name) : EndMacro 
  Macro EndProfile(name) : EndMacro 
  Macro PrintProfile() : EndMacro 
CompilerEndIf 
CompilerIf  #PB_Compiler_IsMainFile 
  
  Procedure foo() 
    
    BeginProfile(#PB_Compiler_Procedure) 
    
    Delay(1000) 
    
    EndProfile(#PB_Compiler_Procedure) 
    
  EndProcedure 
  
  Procedure bar() 
    
     BeginProfile(#PB_Compiler_Procedure) 
    
    Delay(100) 
    
    EndProfile(#PB_Compiler_Procedure) 
    
  EndProcedure   
  
  OpenConsole()
  
  foo() 
  bar() 
  
  PrintProfile() 
  
  Input() 
  CloseConsole() 
  
  
CompilerEndIf 
That's a nice set of routines mate but the trouble is you don't immediately know what the troublesome routines are (or where the bottle-necks are). Maybe this could work with a pre-processor tool wrapping every procedure?

Chris.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Post Reply