Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added an optional feature which times the performance of snippet eval…

…uation
  • Loading branch information...
commit 66f5f7c67848baaa9969abe52c9a5e438766e153 1 parent b72bff7
Noel Kennedy authored
6 contributors.md
Source Rendered
@@ -65,3 +65,9 @@ Francis Rhys-Jones
65 65
66 66 ### Email: ###
67 67 francis.rhys-jones at guardian dot co dot uk
  68 +
  69 +### Name: ###
  70 +Noel Kennedy
  71 +
  72 +### Email: ###
  73 +nkennedy@rvc.ac.uk
5 web/webkit/src/main/scala/net/liftweb/http/LiftSession.scala
@@ -1686,10 +1686,11 @@ class LiftSession(private[http] val _contextPath: String, val uniqueId: String,
1686 1686
1687 1687 val ret: NodeSeq =
1688 1688 try {
1689   -
1690 1689 snippetName.map{snippet =>
1691 1690 val (cls, method) = splitColonPair(snippet)
1692   - S.doSnippet(snippet)(
  1691 + val snippetTimer = SnippetTimer.evaluate(snippet)
  1692 +
  1693 + snippetTimer apply S.doSnippet(snippet)(
1693 1694 runWhitelist(snippet, cls, method, kids){(S.locateMappedSnippet(snippet).map(_(kids)) or
1694 1695 locSnippet(snippet)).openOr(
1695 1696 S.locateSnippet(snippet).map(_(kids)) openOr {
39 web/webkit/src/main/scala/net/liftweb/http/SnippetTimer.scala
... ... @@ -0,0 +1,39 @@
  1 +package net.liftweb.http
  2 +
  3 +import xml.NodeSeq
  4 +import net.liftweb.util.TimeHelpers._
  5 +import net.liftweb.util.Props
  6 +
  7 +/**
  8 + * Times the performance of evaluating of individual snippets
  9 + */
  10 +object SnippetTimer {
  11 +
  12 + /**
  13 + * The configured snippet timing function. Defaults to not timing snippets.
  14 + */
  15 + lazy val evaluate: String => (=> NodeSeq) => NodeSeq = {
  16 + if(Props.getBool("run.timesnippets",defVal = false))
  17 + timeSnippet _
  18 + else
  19 + noTiming _
  20 + }
  21 +
  22 + /**
  23 + * Times the evaluation of a snippet
  24 + * @param snippetName String The name of the snippet
  25 + * @param f The snippet function
  26 + * @return NodeSeq The result of evaluating f
  27 + */
  28 + def timeSnippet(snippetName:String)(f: => NodeSeq) = {
  29 + logTime("Snippet %s (and children) evaluation" format snippetName, f)
  30 + }
  31 +
  32 + /**
  33 + * A function which doesn't time a snippet but just evaluates it
  34 + * @param snippetName String Name of the snippet which is ignored
  35 + * @param f The snippet function
  36 + * @return NodeSeq The result of evaluating f
  37 + */
  38 + def noTiming(snippetName:String)(f: => NodeSeq) = f
  39 +}

0 comments on commit 66f5f7c

Antonio Salazar Cardozo

Why wrap this here instead of around S.doSnippet?

Noel Kennedy

Ok, so if it is done in S.doSnippet there will be two timings for each snippet. Once for the evaluation of the outer element which contains the snippet tag (this is what I wanted to profile). And then another timing which reports when the closing element is encountered. This second timing will accumulate all the timings for any inner child snippets as well as the initial timing for the opening element. It will also be printed even if there are no inner children snippets which is usually done so quickly that the timings are identical and can appear to be duplicate recordings in the output.

You could go either way with this one but I felt it was easier to understand the output if the time reported for evaluating a snippet was just for that snippet. It doesn't seem right that timings for child snippets are 'double counted' into parent snippets' timings.

Antonio Salazar Cardozo

Hm. Ok, I'm all right with doing it this way for now. Last thing: let's make this a LiftRules thing. Something like LiftRules.snippetTimer { ... } or somesuch. I would definitely drop the apply and substitute it for braces, as that makes it clearer that you're passing a function in.

In LiftRules, I'd make snippetTimer a FactoryMaker as well (see noCometSessionCmd at https://github.com/lift/framework/blob/master/web/webkit/src/main/scala/net/liftweb/http/LiftRules.scala#L622 ). So then you'd use LiftRules.snippetTimer.vend { ... }. The purpose here is that you could then turn snippet timer logging off altogether except for a certain session (say you're debugging slowness with a particular user), or a certain request (if you want to debug slowness in a certain path), etc. Also it's in LiftRules so that people can exchange the logging for, say, a metrics instrumentation.

Noel Kennedy

Sure! That sounds like a much more configurable way of doing it. I will hopefully have some time this week/next so will amend and resubmit. Could you advise on where I need to add the documentation? Is the best place on Assembla?

Antonio Salazar Cardozo

The wiki on Assembla is a good place, the Lift cookbook is another solid place. Documenting the property in LiftRules is the most basic docs you should add though.

Please sign in to comment.
Something went wrong with that request. Please try again.