erekle's blog

By erekle, 3 years ago, In English

I want to offer a solution for the problem of measuring the execution time of code, especially when it needs to read data from standard input.

MacOS, Unix, Linux, Ubuntu

If you happen to be on MacOS or another Unix-like operating system, you are probably smiling right now. This is because you have available to you a handy little utility called time. Problem solved! time does exactly what we want. And is easy to use, if you do not mind redirecting standard input:

time mytask < in.txt

Windows

Windows 2003, released two years before I was born, apparently featured a similar utility called timeit. But Microsoft removed it from the next versions of Windows. This simple tool was replaced by a convoluted and largely unusable Measure-Command inside PowerShell.

Goal

I want to re-create timeit on Windows which will allow easily sending input data to my compiled program .exe, measure execution time with precision, show output, and report the exit code of my program.

For example, if I have a program add.cpp which takes three numbers from standard input and adds them up (see below), I want to be able to time its execution like this:

timeit add.exe 2 4 5

Solution

Of course, my first and natural impulse was to count Mississippily — something like https://youtu.be/_RP3DZNKJ28?t=142

But with time this evolved slightly into the following bat file

Windows Batch file

@echo off

REM By erekle https://codeforces.com/profile/erekle

REM ------------------------------------------
REM ------------------------------------------
REM This utility times execution of programmes
REM ------------------------------------------
REM ------------------------------------------


REM For usage and help, run this bat file without any arguments



REM -------- BEGIN: Read main parameters --------
set self=%~n0
set executable=%1
set flag=%2
set infile=%3
REM -------- BEGIN: Read main parameters --------


REM -------- BEGIN: Read command input --------
set params=%2
shift
shift
:loop1
if "%1"=="" goto after_loop
set params=%params% %1
shift
goto loop1
:after_loop
REM -------- E N D: Read command input --------


IF [%executable%]==[] (
	echo.
	echo %self%: Times execution of a program or a command
	echo.
	echo Usage:
	echo.        %self% prog.exe
	echo.        %self% prog.exe param1 param2 param3 ...
	echo.        %self% prog.exe -f input.txt
	exit /b
)

IF NOT EXIST %executable% (
	echo Program not found: %executable%
	exit /b
)

IF [%flag%]==[] (
	powershell -Command "$duration = Measure-Command { .\%executable% | Out-Default }; $seconds = $duration.TotalSeconds; Write-Host "`n____________________________________________" -ForegroundColor Cyan; Write-Host 'Execution time (seconds):' -NoNewline; Write-Host "`t$seconds" -ForegroundColor Cyan; exit $LastExitCode"
	GOTO checkerrors
	exit /b
)


IF [%flag%]==[-f] (
	IF [%infile%]==[] (
		echo Option -f should be followed by input file name, for example:
		echo.      %self% %executable% -f input.txt
		exit /b
	)
) ELSE (
	powershell -Command "$duration = Measure-Command { echo %params% | .\%executable% | Out-Default }; $seconds = $duration.TotalSeconds; Write-Host "`n____________________________________________" -ForegroundColor Cyan; Write-Host 'Execution time (seconds):' -NoNewline; Write-Host "`t$seconds" -ForegroundColor Cyan; exit $LastExitCode"
	GOTO checkerrors
	exit /b

)

REM Consider last option: %flag% is -f and %infile% was supplied

IF NOT EXIST %infile% (
	echo Input file not found: %infile%
	exit /b
)

powershell -Command "$duration = Measure-Command { .\%executable% | Out-Default }" < %infile%; $seconds = $duration.TotalSeconds; Write-Host "`n____________________________________________" -ForegroundColor Cyan; Write-Host 'Execution time (seconds):' -NoNewline; Write-Host "`t$seconds" -ForegroundColor Cyan; exit $LastExitCode

:checkerrors
IF NOT %errorlevel%==0 (
	echo Warning: Exit code:             %errorlevel%
) ELSE (
	echo Exit code:                      %errorlevel%
)

Usage

  • You can save this code in a text file with extension .bat (for example timeit.bat)
  • Do not use time.bat though, as time is an existing Windows command with different functionality
  • Place timeit.bat somewhere on Windows %PATH% so that it can be found from any directory
  • Now you can run timeit and it will report three different ways to use it

One option allows you to just put your input data right in the command line and your code will receive it on its standard input!

For example, if you execute the following command, add.exe will receive 2 4 5 on standard input:

timeit add.exe 2 4 5

This might even work if you manually enter 200,000 positive integers from the keyboard ;)

Here is the full example:

Final Standings

With this code, your situation on Windows might be even slightly better than the situation on a Mac or Linux.

I hope this brings some hope back to Windows users — at least until we save money for a Mac ;)

Full text and comments »

  • Vote: I like it
  • +80
  • Vote: I do not like it