-
Notifications
You must be signed in to change notification settings - Fork 148
timeIt
Nathaniel Sabanski edited this page Jan 20, 2016
·
7 revisions
Added by Sorin Ionescu
See the Boo benchmarks page for examples using this macro.
The original JIRA issue has the C# source for this macro. It has been converted to the boo code below (also, the name was changed):
#region license
// Copyright (c) 2004-2005, William P. Wood
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of William P. Wood nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
namespace Boo.Lang.Useful.Macros
import System
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
class TimeItMacro(AbstractAstMacro):
"""
Times a block of code.
@author William P. Wood
@author Sorin Ionescu
"""
override def Expand(macro as MacroStatement) as Statement:
argumentCount = macro.Arguments.Count
argumentIndex = 0
localIndex = _context.AllocIndex()
statement = Block(macro.LexicalInfo)
macroBlock = macro.Block
message = StringLiteralExpression(
macro.LexicalInfo,
'Elapsed time: ')
elapsed = ReferenceExpression(
macro.LexicalInfo,
"___elapsedTime${localIndex}")
start = ReferenceExpression(
macro.LexicalInfo,
"___startTime${localIndex}")
dateNow = AstUtil.CreateReferenceExpression('date.Now')
# loop
if argumentCount > argumentIndex and \
macro.Arguments[argumentIndex] isa IntegerLiteralExpression:
loopsCount = cast(
IntegerLiteralExpression,
macro.Arguments[argumentIndex]).Value
message = StringLiteralExpression(
macro.LexicalInfo,
"Elapsed time for ${loopsCount} executions: ")
++argumentIndex
# unroll
if argumentCount > argumentIndex and \
macro.Arguments[argumentIndex] isa IntegerLiteralExpression:
argument = \
macro.Arguments[argumentIndex] as IntegerLiteralExpression
++argumentIndex
macroBlock = CreateTimerBlock(
macro,
loopsCount,
argument.Value,
localIndex)
else:
macroBlock = CreateTimerBlock(macro, loopsCount, 8, localIndex)
# message
if argumentCount > argumentIndex and \
macro.Arguments[argumentIndex] isa StringLiteralExpression:
message = macro.Arguments[argumentIndex]
++argumentIndex
# elapsed
if argumentCount > argumentIndex and \
macro.Arguments[argumentIndex] isa ReferenceExpression:
elapsed = macro.Arguments[argumentIndex]
message = null
++argumentIndex
if argumentCount != argumentIndex:
raise ArgumentException(
"format is 'timeIt [loops [, unroll]] [, message] [, elapsed]'")
statement.Add(
BinaryExpression(
macro.LexicalInfo,
BinaryOperatorType.Assign,
start,
dateNow))
statement.Add(macroBlock)
elapsedCalculation = BinaryExpression(
macro.LexicalInfo,
BinaryOperatorType.Subtraction,
dateNow.CloneNode(),
start.CloneNode())
statement.Add(
BinaryExpression(
macro.LexicalInfo,
BinaryOperatorType.Assign,
elapsed,
elapsedCalculation))
if message != null:
statement.Add(
AstUtil.CreateMethodInvocationExpression(
macro.LexicalInfo,
AstUtil.CreateReferenceExpression('System.Console.Write'),
message))
statement.Add(
AstUtil.CreateMethodInvocationExpression(
macro.LexicalInfo,
AstUtil.CreateReferenceExpression(
'System.Console.WriteLine'),
elapsed))
return statement
private def CreateTimerBlock(
macro as MacroStatement,
loopsCount as int,
unroll as int,
localIndex):
statement = Block(macro.LexicalInfo)
whileStatement = WhileStatement(macro.LexicalInfo)
loopCounter = ReferenceExpression("___loopCounter${localIndex}")
unroll = 1 if unroll < 1
if loopsCount >= 2 * unroll:
statement.Add(
BinaryExpression(
macro.LexicalInfo,
BinaryOperatorType.Assign,
loopCounter,
IntegerLiteralExpression(macro.LexicalInfo, 0)))
loopsCount /= unroll
whileStatement.Condition = BinaryExpression(
macro.LexicalInfo,
BinaryOperatorType.LessThan,
loopCounter.CloneNode(),
IntegerLiteralExpression(
macro.LexicalInfo,
loopsCount))
whileStatement.Block.Add(
UnaryExpression(
LexicalInfo: macro.LexicalInfo,
Operator: UnaryOperatorType.Increment,
Operand: loopCounter.CloneNode()))
for index in range(unroll):
whileStatement.Block.Add(macro.Block.CloneNode())
loopsCount -= loopsCount * unroll
statement.Add(whileStatement)
for index in range(loopsCount, 0):
statement.Add(macro.Block.CloneNode())
return statement
See also the --profile option for the mono command line tool to profile your application for bottlenecks.