Skip to main content
Inspiring
August 22, 2008
Question

DateDiff doesn't support milliseconds

  • August 22, 2008
  • 22 replies
  • 3096 views
I want to simply output the time the page renders (without making debug info available to public), but amazingly, it seems CF8 lost support in DateDiff for milliseconds (which was the letter 'l' for the datepart)

Anyone know of a way to get page execution time?
    This topic has been closed for replies.

    22 replies

    Inspiring
    August 28, 2008
    > Is this correct?

    Yep.

    > Cause if I grasped the concept

    You seem to have.


    > (and can get it to do so),

    Well that's the proof in the pudding, innit?


    > it's GENIUS! :D

    I think you'll find you can generally do whatever you want to do with CF.
    It's just the working out how that takes some time, occasionally.

    --
    Adam
    Inspiring
    August 27, 2008
    Hmm. I'm not too familiar with the pageContext object. So I can have the footer output:

    !!!--!!!

    And then just search for that string and replace it with the value of the execution time after the entire response already completed, eh?

    If I understand it correctly:

    Create the entire page. We have the start tick count, and output a string that will be used in the replacement.

    On the end of the request, calculate the difference and create a var. Use PageContext to clear the buffer (after previously storing the buffer in a variable. Perform a replacement of that specialty string with the now-existing calculated difference, and then send that updated buffer back to the user?

    Is this correct? Cause if I grasped the concept (and can get it to do so), it's GENIUS! :D
    BKBK
    Community Expert
    Community Expert
    August 27, 2008
    Aegis Kleais,

    Another approach. It involves writing an extra page, timerPage.cfm:

    <cfset begin=getTickCount()>
    <cfinclude template="pageToBeTimed.cfm">
    Execution time: <cfoutput>#getTickCount()-begin#</cfoutput> ms

    Inspiring
    August 27, 2008
    > No. I don't want it to appear unprofessionally at the bottom of the page after
    > the templating has closed off </html>.

    Isn't this just some debug code? Sorry, I just presumed it was...


    > more I think of this problem, the more it sounds impossible to do without
    > needlessly re-requesting a lot of data subsequent times.

    Nah, it's easy.

    You can access the rendered output of the page via the pageContext object,
    thus:

    <cfset outputBuffer=getPageContext().getOut().getString()>


    So you'd then update the buffer:

    <cfset updatedBuffer = replaceNoCase(outputBuffer, "</html>",
    "#debugStuffHere#</html>")>

    Clear the existing buffer:
    <cfset getPageContext().getOut().clearBuffer()>

    Output the whole lot again, which repopulates the buffer
    <cfoutput>#updatedBuffer#</cfoutput>

    You might need to vary the replaceNoCase() bit with something more
    in-keeping withyour desired formatting, but that's the basic technique.


    Why do you want to output the request processing time if it's *not* just
    debug?

    --
    Adam
    Inspiring
    August 27, 2008
    No. I don't want it to appear unprofessionally at the bottom of the page after the templating has closed off </html>.

    This both invalidates my page as XHTML compliant and will not display the variable where I want to display it (inside my footer, styled to be themed with the page accordingly)

    I kind of need the variable to be captured after the request completes so that it has the difference stored in a variable, but that variable is called to be viewed BEFORE the request ends, so it understandably right now wouldn't exist.

    It's as if the process needs to complete fully (to capture the execution time) and then RE-DISPLAY to the page, but now with the variable in existence. The more I think of this problem, the more it sounds impossible to do without needlessly re-requesting a lot of data subsequent times.
    Inspiring
    August 27, 2008
    This seems to be getting more complicated than it needs to be.

    Application.cfc
    <cfcomponent>

    <cfset this.Name = "testRequestScope">

    <cffunction name="OnRequestStart">
    <cfset request.iStart = getTickCount()>
    <cfoutput>Timer @ start of request: [#request.iStart#]<br /></cfoutput>
    </cffunction>

    <cffunction name="OnRequestEnd">
    <cfset request.iEnd = getTickCount()>
    <cfoutput>
    Timer @ end of request: [#request.iEnd#]<br />
    Duration of request: [#request.iEnd-request.iStart#]<br />
    </cfoutput>
    </cffunction>

    </cfcomponent>

    myFile.cfm
    Hello World<br />
    <cfset createObject("java", "java.lang.Thread").sleep(100)>

    Ouptut:
    Timer @ start of request: [1219821121156]
    Hello World
    Timer @ end of request: [1219821121265]
    Duration of request: [109]

    Isn't that all you need to be doing?

    --
    Adam
    Inspiring
    August 27, 2008
    I'll try using the SESSION scope but I got a good feeling it'll be as useless as the others. It simply won't exist when referenced in the page template. What it will probably do is reference the LAST page's load times since they'll exists across requests, and that's useless to me.

    It would have to be:

    onRequestStart - check if SESSION.intDifference exists, and if it does, destroy it.
    onRequestStart - store GetTickCount in SESSION var
    onRequestStart - include template that references intDifference (errors)
    onRequestEnd - calculate difference between GetTickCount and SESSION var that stored it in onRequestStart. Store in SESSION.intDifference
    BKBK
    Community Expert
    Community Expert
    August 26, 2008
    So as I originally assumed, it's not possible to create a variable in onRequestEnd and then reference that same variable in an included file that was called in onRequestStart. The variable doesn't exist yet.

    That is as it should be, assuming you're still talking about request variables. Between onRequestEnd and the next call to onRequestStart, one request ends and another begins. Hence, two distinct request scopes. One way to measure the time span between two successive calls to onRequestStart is to use a scope that transcends the request scope, for example, session.

    Inspiring
    August 26, 2008
    So as I originally assumed, it's not possible to create a variable in onRequestEnd and then reference that same variable in an included file that was called in onRequestStart. The variable doesn't exist yet. Leaves me stuck at square 1.

    I have it working right now, but it's not true. I'm evaluating the time in the footer output, which is NEAR the end of the page request, but not truly the end of the request. Makes me wonder how such a task is done.
    BKBK
    Community Expert
    Community Expert
    August 26, 2008
    Except the code that is included is referencing the REQUEST scope variable that is created in onRequestEnd, and it says it doesn't exist.

    Indeed. That is the kind of surprise you can get when you use the request scope in onRequestEnd. It is more of a science in onSessionEnd and in onApplicationEnd. There you can explicitly pass the session scope and the application scope, respectively, as parameters.