Page 1 of 2

PureMonitor for Windows

Posted: Sat Feb 09, 2013 10:22 pm
by Bisonte
Inspired by : http://purebasic.fr/english/viewtopic.p ... 09#p403309

A little tool I made to monitor the cpu and memory usage of a PureBasic project. It just requires one line of code in your app during testing in order to run it.

Features
  • Monitor the cpu and memory usage of your app/PureBasic project.
  • Save a log file of the average cpu and memory usage per minute.
  • Kill the app if it locks up when the debugger is not on.
  • Auto closes when your app is closed.
  • Option to automatically open the log file when your app is closed.
  • Stays on top of all windows, so it never goes out of view. That way you can still use your app and monitor it.
Put the following line in your code and edit the location for where ever you put the PureMonitor app.

Code: Select all

RunProgram(#PB_Compiler_Home + "PureMonitor.exe", Str(GetCurrentProcessId_()), "")
It also shows the icon (if one is selected at compiler options).

In the zip : x64,x86 version and a little demo.

Thx to J.Baker for idea and icon ;)

Download PureMonitor Source for Windows

Update : 30.04.2013 Update : 18.02.2013
  • Typo in resident (now : ShowResourceViewer())
  • Resident sourcefile included ;)
  • Killprocess Button fixed
  • sourcecode : see above
Update : 14.02.2013 - cause danilo's feedback ;)
  • Layout changed
  • Handles added
  • Resident File for the "ShowRessourceViewer()" Macro added
  • Logfile changed (stores prefs and logfile at : %APPDATA%\PureBasic\PureMonitor\)
  • Prefsfile to store "LogFile" and "LogEvery n minute" and some other things
  • sourcecode : see above
  • Image
Edit: Version (14.Feb.2013 - pm 07:34) I forgot to put the resident to the archiv. Now its present. Downlad again .... (sorry)

Re: PureMonitor for Windows

Posted: Sun Feb 10, 2013 1:04 am
by J. Baker
Cool! I'll have to try it on Windows later. Maybe someone will pick up a Linux version. ;)

Re: PureMonitor for Windows

Posted: Sun Feb 10, 2013 2:47 am
by Danilo
@Bisonte:
Good start, thank you!

Some suggestions:
1.) Please split the CPU info to number of CPUs + all CPUs (CPU 1: 100% CPU 2: 0% CPU 3: 0% CPU 4: 0% CPU ALL: 25%)
2.) Add CPU peak display, same as (1) but peak
3.) Make the CPU and CPU peak simple graphical bars. (You could join CPU and CPU peak into one image)

Code: Select all

Structure CpuInfo
    current.i
    peak.i
    falldown.i
    image.i
EndStructure

Global Dim CPU.CpuInfo(4)

Procedure RedrawCPUImage(cpu,value,falldown=#False)
    CPU(cpu)\current = value
    If CPU(cpu)\peak < CPU(cpu)\current
        CPU(cpu)\peak     = CPU(cpu)\current
        CPU(cpu)\falldown = CPU(cpu)\current
    Else
        If falldown = #True
            CPU(cpu)\falldown - 3
            If CPU(cpu)\falldown < CPU(cpu)\current
                CPU(cpu)\falldown = CPU(cpu)\current
            EndIf
        EndIf
    EndIf
    If CPU(cpu)\image = 0
        CPU(cpu)\image = CreateImage(#PB_Any,20,100,24)
    EndIf
    If CPU(cpu)\image And StartDrawing( ImageOutput( CPU(cpu)\image ) )
        Box(0,0,20,100,0)
        ;Box(0,100-CPU(cpu)\peak   ,20,100,RGB(255, 0 ,0))
        Box(0,100-CPU(cpu)\current,20,100,RGB(255,255,0))
        If falldown
            Box(0,100-CPU(cpu)\falldown,20,  2,RGB(0,255,0))
        EndIf
        Box(0,100-CPU(cpu)\peak   ,20,  2,RGB(255, 0 ,0))
        StopDrawing()
    EndIf
EndProcedure

If OpenWindow(0, 0, 0, 300, 200, "CPU", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ImageGadget(1, 10, 10, 20, 100, 0, #PB_Image_Border)
    ImageGadget(2, 35, 10, 20, 100, 0, #PB_Image_Border)
    ImageGadget(3, 60, 10, 20, 100, 0, #PB_Image_Border)
    ImageGadget(4, 85, 10, 20, 100, 0, #PB_Image_Border)

    AddWindowTimer(0,0,250)

    Repeat
        Select WaitWindowEvent()
            Case #PB_Event_CloseWindow
                End
            Case #PB_Event_Timer
                RedrawCPUImage(1, Random(80))
                SetGadgetState(1, ImageID(CPU(1)\image))
                RedrawCPUImage(2, Random(35))
                SetGadgetState(2, ImageID(CPU(2)\image))
                RedrawCPUImage(3, Random(100), #True)
                SetGadgetState(3, ImageID(CPU(3)\image))
                RedrawCPUImage(4, Random(70), #True)
                SetGadgetState(4, ImageID(CPU(4)\image))
        EndSelect
    ForEver
EndIf
4.) Monitor handles used by the process:

Code: Select all

#GR_GDIOBJECTS       = 0
#GR_GDIOBJECTS_PEAK  = 2
#GR_USEROBJECTS      = 1
#GR_USEROBJECTS_PEAK = 4

ProcessHandle = OpenProcess_(#PROCESS_QUERY_INFORMATION,#False,GetCurrentProcessId_())
If ProcessHandle
    Debug "GDI handles : "+Str( GetGuiResources_(ProcessHandle, #GR_GDIOBJECTS))
    
    If OSVersion() >= #PB_OS_Windows_7 ;Or OSVersion() >= #PB_OS_Windows_Server_2008_R2
        Debug "GDI (peak)  : "+Str( GetGuiResources_(ProcessHandle, #GR_GDIOBJECTS_PEAK))
    EndIf
    
    Debug "USER handles: "+Str( GetGuiResources_(ProcessHandle, #GR_USEROBJECTS))
    
    If OSVersion() >= #PB_OS_Windows_7 ;Or OSVersion() >= #PB_OS_Windows_Server_2008_R2
        Debug "USER (peak) : "+Str( GetGuiResources_(ProcessHandle, #GR_USEROBJECTS_PEAK))
    EndIf
    CloseHandle_(ProcessHandle)
EndIf
5.) Make a macro and compile it with /RESIDENT switch. Put it in "PureBasic\residents" folder.

Code: Select all

Macro ShowResourceViewer()
    RunProgram(#PB_Compiler_Home + "PureMonitor.exe", Str(GetCurrentProcessId_()), "")  
EndMacro
We just use ShowResourceViewer() in our sources (like ShowMemoryViewer() and ShowAssemblyViewer()).
It should also work with disabled debugger, the user can add "CompilerIf #PB_Compiler_Debugger" himself if he wants.

6.) Remember the window position (like ShowMemoryViewer() and ShowAssemblyViewer())
7.) Maybe make the window size-able, and remember the size.


EDIT:
8.) Of course also memory peak would be useful (how much memory was consumed at most)

9.) Please add general process handle count and peak for it (in addition to GDI/USER handles)

Code: Select all

Import "Kernel32.lib"
    GetProcessHandleCount(hProcess,pHandles.l)
EndImport


Procedure GetHandleCount()
    Protected handleCount.l
    ProcessHandle = OpenProcess_(#PROCESS_ALL_ACCESS,#False,GetCurrentProcessId_())
    If ProcessHandle
    
        GetProcessHandleCount(ProcessHandle,@handleCount)

        CloseHandle_(ProcessHandle)
    EndIf
    ProcedureReturn handleCount
EndProcedure


handles = GetHandleCount()
If handles > peak_handles
   peak_handles = handles
EndIf

Debug handles
Debug peak_handles

Re: PureMonitor for Windows

Posted: Sun Feb 10, 2013 11:17 am
by Michael Vogel
Looks nice, thanks for this!

It could also be nice to be able to set Logging on/off by additional start parameter flags, but more interesting would be a possibility to send commands from the observed program to the monitor. This would also allow to log the used memory in critical procedures etc.

Would also be interesting to see some snippets to see how it works.

Re: PureMonitor for Windows

Posted: Sun Feb 10, 2013 11:50 am
by Bisonte
@Danilo:
1) oha... to split the process cpuload to single cpu's i need help... I only can extract the cpu-load like the taskmanager.
2+3+6+7+8) sounds good... on todo list ;)
4+9) What are these handles ? But they looks like simple to integrate... (on todo list)
5) on todo list, but every user can made this by himself (see first post to start the monitor)

And the peak also shown in logfile ?

@J.Baker: Well one on Linux and all are satisfied ;)

@Michael Vogel: I will try to send and receive messages.... but I have no experience with that by now.

I think, a new field to change the log intervall needed... like Every x minutes...

Re: PureMonitor for Windows

Posted: Sun Feb 10, 2013 2:35 pm
by Danilo
Bisonte wrote:4+9) What are these handles ? But they looks like simple to integrate... (on todo list)
Opened files handles, GDI handles (images, brushes, ..), mutex handles, windows, gadgets, etc.

Re: PureMonitor for Windows

Posted: Sun Feb 10, 2013 9:08 pm
by yrreti
Thanks very much for this Bisonte.
When I saw the one for OS X, I was immediately wishing for one for windows too.
Thanks very much.

yrreti

Re: PureMonitor for Windows

Posted: Thu Feb 14, 2013 12:43 pm
by Bisonte
Update : 14.02.2013 - cause danilo's feedback ;)
  • Layout changed
  • Handles added
  • Resident File for the "ShowRessourceViewer()" Macro added
  • Logfile changed (stores prefs and logfile at : %APPDATA%\PureBasic\PureMonitor\)
  • Prefsfile to store "LogFile" and "LogEvery n minute" and some other things
  • Sourcecode see first post

Re: PureMonitor for Windows

Posted: Fri Feb 15, 2013 3:57 pm
by Danilo
Bisonte wrote:Update : 14.02.2013 - cause danilo's feedback ;)
  • Layout changed
  • Handles added
  • Resident File for the "ShowRessourceViewer()" Macro added
  • Logfile changed (stores prefs and logfile at : %APPDATA%\PureBasic\PureMonitor\)
  • Prefsfile to store "LogFile" and "LogEvery n minute" and some other things
  • Download PureMonitor für Windows
Thanks Bisonte! Tested with PB 5.00, the macro in resident didn't work (i think incompatible version), but it works now with PB 5.10.

One more suggestion:
Add a checkbox on bottom: "[X] Don't close window after program exit" (or something like that)
So your window stays open until I close. If it stays open and the process has ended, you could
change the PID display to "Program ended with ExitCode: 1" and disable the Kill process button.

The kill process button does not work here, even pressing it several times.

BTW: "Ressource" (double 's') is German. Should be "Resource" in English. (Resourcen oder Ressourcen?)
See: http://www.dict.cc/?s=ressource >> ressource / ressources [WRONG for: resource / resources]

Re: PureMonitor for Windows

Posted: Sun Feb 17, 2013 9:43 am
by Denis
Tks Bisonte

I have a question.
I don't know exactly what are GuiH and Guip. Handles (?) and process (?) of what ?

Re: PureMonitor for Windows

Posted: Sun Feb 17, 2013 10:26 am
by Danilo
Denis wrote:I have a question.
I don't know exactly what are GuiH and Guip. Handles (?) and process (?) of what ?
GuiH / UserH = Handles
GuiP / UserP = Peak count of Handles (highest count of Handles while running your process)

Re: PureMonitor for Windows

Posted: Sun Feb 17, 2013 11:12 am
by Denis
Thank you Danilo.

Re: PureMonitor for Windows

Posted: Mon Feb 18, 2013 9:21 am
by Bisonte
Update : 18.02.2013
  • Typo in resident (now : ShowResourceViewer())
  • Resident sourcefile included ;)
  • Killprocess Button fixed
  • Sourcecode see first post

Re: PureMonitor for Windows

Posted: Mon Feb 18, 2013 1:54 pm
by Danilo
Bisonte wrote:Update : 18.02.2013
Thanks Bisonte!
Bisonte wrote:
  • Killprocess button (only in function if log enabled)
Kill process works now, even without enabling log file.

Re: PureMonitor for Windows

Posted: Mon Feb 18, 2013 3:36 pm
by Bisonte
Danilo wrote:
Bisonte wrote:
  • Killprocess button (only in function if log enabled)
Kill process works now, even without enabling log file.
I mean : I fixed the "non functional button that has only function with log enabled" ;)
I edit the Updatemessage ;)