dm-script

Time elapse function to calculate the processing time of other function


I'd like to calculate the processing time of different functions. The 1st code below can achieve that. But is that possible to make it a function, and use other function name as input variable (like the 2nd code)? Other possible solution are also welcome.

Number time1, time2
time1 = GetCurrentTime()
// run some function
time2 = GetCurrentTime()
Result(CalcTimeUnitsBetween(time1, time2, 1) + "\n")
Void time_elapse(function_name)
{
Number time1, time2
time1 = GetCurrentTime()
function_name()
time2 = GetCurrentTime()
Result(CalcTimeUnitsBetween(time1, time2, 1) + "\n")
}

Solution

  • Why would you want to do that?

    Any additional code-execution to the to-be-measured code will just add to the measurement time.

    Is function_name really just the name? i.e. Will it be only used for functions that do not take any input parameters?

    I'm not convinced that what you are aiming for is in any way beneficial. You could do it using the following, though:

    Void time_elapse(string function_call)
    {
        Number startVal = GetHighResTickCount()
        if (ExecuteScriptString(function_call)) Throw("Script call failed") 
        number time = GetHighResTickCount() - startVal
        time /= GetHighResTicksPerSecond()
        Result("\nCall took "+Format(time,"%5.9f")+" sec.")
    }
    
    string call = "sleep(0.1)"
    time_elapse(call)
    

    As for better measurements:

    1. To get a good idea of actual processing time, you do need statistics. A single execution measurement can widely deviate from the average due to other CPU tasks (within and without DigitalMicrograph) being active at the same time.

    2. You may want to use GetHighResTicks() and GetHighResTicksPerSecond() for higher precision measurements.

    3. A "convenient" way of adding a time is to make it into a class, where the constructor and the destructor perform the measurement. Just be aware that - as with your idea - a bit of overhead stems from the construction itself. However, the convenience of such a Sentry-Class stems from the fact that object-destruction happens automatically when leaving the code-block of the local variable. Example:

    class CTimerSentry
    {
        string nameOp
        number startVal, prec
        
        CTimerSentry(object self){
            startVal=GetHighResTickCount()
            nameOP="Operation"
            prec = 3
        }
        ~CTimerSentry(object self){
            number time = GetHighResTickCount() - startVal
            time /= GetHighResTicksPerSecond()
            Result("\n"+nameOP+" took "+Format(time,"%5."+prec+"f")+" sec.")
            }
            
        object init(object self, string name, number precision)
        {
            nameOP = name
            prec = precision
            return self
        }
    }
    
    // Any code you want to time
    {
        object timer = Alloc(CTimerSentry).Init("Test sleep(0.1)",3)
        sleep(0.1)
        for (number i=0;i<10;i++)
        {
            object timer2 = Alloc(CTimerSentry).Init("Test loop sleep(0.1)",3)
            sleep(0.1)
        }
    }