6
\$\begingroup\$

Challenge

Write a complete program that prints out the time it took to execute a certain part of itself. That part must include a process whose total number of operations (and therefore execution time) is dependent on a user-substituted numeric value - this can be denoted in any way in your code (uppercase N for example) and doesn't count as a byte.

Unlike many code golf challenges, this one is a valid use case - in environments that allow executing code from command line, you may want to have a short code snippet to roughly compare performance across different systems.

Rules

  • Execution time is denoted as a nonnegative integer or decimal value, followed by the corresponding time unit (let's accept ns, µs/us, ms, s, m and h). A space between the number and unit is optional, more spaces are also allowed (but not newline characters).
  • Output must include the execution time exactly once. There can be additional text around it, as long as no part of it could be matched with the execution time itself. This allows using standard functions for timing code execution that may use various formats for printing out the execution time.
  • Output goes to STDOUT. Anything in STDERR is disregarded.
  • You can import any standard libraries before the actual code, without any cost to the total number of bytes, but you are not allowed to change the library name in the import declaration.
  • Do not just use sleep to control the execution time, as that does not increase the number of operations (and also doesn't work as a performance benchmark). The execution time must also depend on the user-substituted value linearly, exponentially or polynomially (before you ask, a constant polynomial doesn't count).

Scoring

This is code golf, so the shortest answer in bytes wins.

Example

This is an unnecessarily long program written in Python:

import time

start_time = time.time()

for i in range(N):
    pass

end_time = time.time()

print("%fs" % (end_time - start_time))

Program description:

  • imports the standard time library (this adds no bytes to the code size)
  • stores the current time in seconds
  • loops N times, does nothing each iteration
  • stores the time after the loop
  • prints the time difference in the correct format
\$\endgroup\$
  • \$\begingroup\$ Some potential examples would be great for this challenge, as that would help show people what their solution should look like. \$\endgroup\$ – Lyxal Jan 12 at 22:41
  • 1
    \$\begingroup\$ @Jono2906 I added an example program in Python. \$\endgroup\$ – Vojtěch Strnad Jan 12 at 23:12
  • \$\begingroup\$ Rather than have N as some user substituted value, why not just say that it is given as input? \$\endgroup\$ – Jo King Jan 13 at 0:37
  • 2
    \$\begingroup\$ Regarding input... of course different languages handle input differently? They also handle timing stuff differently, so that doesn't really seem like a valid excuse for why n can't just be input? \$\endgroup\$ – Jo King Jan 13 at 2:47
  • 4
    \$\begingroup\$ Having said that, I agree it's better to use an actual input next time, since it's the default. Hard-coded inputs aren't allowed by default. So for next challenges I would indeed advice to follow @JoKing's suggestion and just having input. But for this challenge (considering the amount of answers) I would just leave it as hardcoded (non-counting) \$n\$ for now. \$\endgroup\$ – Kevin Cruijssen Jan 13 at 10:11

14 Answers 14

7
\$\begingroup\$

Zsh, 14(?) bytes

If N is substituted in place of $1 (as described in the prompt), then 14 bytes. If N is given as an argument, then 16 bytes.


time (: {0..$1})

Try it online!

Uses the builtin time (you can verify that this is a Zsh builtin: run type time). The time to expand the brace expansion increases with the input.

You might think to use time sleep $1, but sleep is an external program, not pure Zsh.

\$\endgroup\$
6
\$\begingroup\$

APL (Dyalog Unicode), 12 bytesSBCS

Full program. Returns elapsed time in seconds, followed an "s". Runtime on TIO is roughly linear with N, with a coefficient of about 6×10-10. Uses the dfns library, but per OP, import isn't counted.

's',⍨cmpx'⍳N'

Try it online!

'⍳N' expression generating the ɩntegers 1 through N

cmpx time the execution of that expression

's',⍨ append "s"

\$\endgroup\$
  • \$\begingroup\$ It seems to me that DeLay does not increase the number of performed operations. \$\endgroup\$ – Vojtěch Strnad Jan 12 at 21:51
  • \$\begingroup\$ @VojtěchStrnad OK, it now performs N sleep operations of 1 second each. \$\endgroup\$ – Adám Jan 12 at 21:59
  • \$\begingroup\$ This now adheres to the challenge, however there is no need to use sleep. Isn't there a shorter way to perform N operations? \$\endgroup\$ – Vojtěch Strnad Jan 12 at 22:26
  • \$\begingroup\$ @VojtěchStrnad There certainly is a shorter way to perform N operations, but we also need to time these operations, and the sleep function has the benefit of coming with a built-in timing. \$\endgroup\$ – Adám Jan 12 at 22:27
  • 1
    \$\begingroup\$ @VojtěchStrnad OK, now it actually does something (counting) and uses a library function to time it. \$\endgroup\$ – Adám Jan 12 at 22:36
5
\$\begingroup\$

R, 29 28 bytes

cat(system.time(!1:9e6)[3],"s")

Try it online!

A full program printing the number of seconds elapsed complete with unit. The 9e6 is not counted per the rules and can be replaced with any other number. Thanks to @RobinRyder for saving a byte!

An alternative would be paste(system.time(!1:9e6),"s"), but this also prints our four other times (the correct one is in the middle).

\$\endgroup\$
  • \$\begingroup\$ Putting the program to sleep does not increase the number of operations. The idea behind this is to benchmark system performance, which this program does not. \$\endgroup\$ – Vojtěch Strnad Jan 12 at 21:35
  • 1
    \$\begingroup\$ @VojtěchStrnad I thought the key was the timing of execution, rather than what was done. Anyway, I’ve changed it to multiplying a sequence of integers by 2, which still scales with N and has the advantage of being shorter. \$\endgroup\$ – Nick Kennedy Jan 12 at 21:41
  • \$\begingroup\$ Excellent! I can't tell if this could be improved, but it looks really good. \$\endgroup\$ – Vojtěch Strnad Jan 12 at 21:48
  • 1
    \$\begingroup\$ To elaborate on what you wrote, yes, the key really is timing the execution. However there really is no point in timing a program whose running time you pretty much know already (when using sleep). \$\endgroup\$ – Vojtěch Strnad Jan 12 at 21:54
  • 3
    \$\begingroup\$ !1:9e6 would also work for -1 byte. \$\endgroup\$ – Robin Ryder Jan 12 at 23:02
4
\$\begingroup\$

PowerShell, 38 bytes

param($n)$a={1..$n};Measure-Command $a

Try it online!

\$\endgroup\$
4
\$\begingroup\$

05AB1E, 12 10 bytes

ƒžc})¥O's«

-2 bytes thanks to @ExpiredData.

Either add the \$n\$ as leading portion (i.e. 100ƒžc})¥O's«) or simply use \$n\$ as STDIN input.
Outputs the execution time in whole seconds (without space).

Try it online.

Explanation:

ƒ            # Loop in the range [0, n]:
 žd          #  Push the current time in seconds
   })        # After the loop: wrap all values on the stack into a list
     ¥       # Get the deltas (paired differences) of this list
      O      # And sum those (to get the difference between the first and last times)
       's«  '# And append a trailing "s" (without space)
             # (after which this is output implicitly to STDOUT)
\$\endgroup\$
4
\$\begingroup\$

J, 16 14 19 bytes (20 - 1 for N)

echo's',~":6!:2'i.N'

Try it online!

-2 bytes thanks to Adam -- after looking at his answer I realized I didn't need to sum the integers, just generate them

+6 bytes thanks to Adam for pointing out I missed the unit

Generates the integers 0..N-1, times it, and prints it to stdout. 's',~ prepends the unit s for seconds.

\$\endgroup\$
  • 3
    \$\begingroup\$ you need to print a unit \$\endgroup\$ – Adám Jan 13 at 7:08
3
\$\begingroup\$

Raku (18 or 25)

Depending on one's definition of a "standard" library for Raku...

use Timer; # uncounted import line
say timer {[+] ^N}

or

[+] ^N;say now -BEGIN now
$/=now;[+] ^N;say now -$/

[+] ^N sums all numbers from 0 to N, so the bigger it gets, the more ops it does. The now - BEGIN now bit is a common idiom in Raku that virtually makes such libraries unnecessary (the phaserless alternative is as long or longer).

\$\endgroup\$
3
\$\begingroup\$

Python 2.7 - 32 20 bytes

print t(number=N),'s'

We can take advantage of the different scoring rules here. timeit.timeit has been in the standard library since 2.6, so we get to ignore the from timeit import timeit as t and hence 31 bytes that would have cost.

timeit is designed to be able to take a statement for execution as a parameter, but has a default of pass. So the pass statement will be executed N times, and that is what will be timed.

EDIT:

As @Johnathan pointed out there was more to milk out of the import statement exception. While the rules state no renaming imports, technically aliasing isn't renaming.

To make the case that aliasing isn't renaming

>>> from timeit import timeit as t
>>> t.__name__
'timeit'
\$\endgroup\$
  • \$\begingroup\$ Given the allowance of free imports I would imagine you can save 11 with from timeit import timeit as t and do print t(number=N),'s' \$\endgroup\$ – Jonathan Allan Jan 13 at 18:47
  • \$\begingroup\$ Thanks for pointing that out! I was hesitant on aliasing because of the "you are not allowed to change the library name in the import" but aliasing doesn't change the name of anything technically. \$\endgroup\$ – Joe Habel Jan 13 at 19:53
  • 1
    \$\begingroup\$ I think as t clearly counts as changing the name, which would make this answer invalid. \$\endgroup\$ – pppery Jan 14 at 3:20
2
\$\begingroup\$

C (gcc), 59 bytes

main(c,a){a=clock();for(c=100;c--;);printf("%dus",clock()-a);}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Java 5/6, 99 98 78 bytes

import static java.lang.System.*;
enum A{A;{long s=nanoTime();for(int i=#;i-->0;);out.print(nanoTime()-s+"ns");}}

Loops the given \$n\$ amount of times without doing anything in the loop body.

Java 11, 128 122 121 101 bytes

import static java.lang.System.*;
interface M{static void main(String[]a){var s=nanoTime();"x".repeat(#);out.print(nanoTime()-s+"ns");}}

Creates a String of \$n\$ amount of "x" with the Java 11 String#repeat(int) builtin.

Try it online.

In both programs, replace the # for the actual number.
And both will output the execution time in nanoseconds (without space).

-20 bytes thanks to @Holger for remembering me to (ab)use the rule "You can import any standard libraries before the actual code, without any cost to the total number of bytes, but you are not allowed to change the library name in the import declaration." by using a static import for System.

\$\endgroup\$
  • 1
    \$\begingroup\$ Doesn’t “you can import any standard libraries before the actual code” of the challenge imply that you could use import static java.lang.System.*;? Then, you don’t need the System S=null; trick. \$\endgroup\$ – Holger Jan 13 at 15:33
  • \$\begingroup\$ @Holger Ah, good call. Thanks! \$\endgroup\$ – Kevin Cruijssen Jan 13 at 22:10
0
\$\begingroup\$

SAS, 37 bytes

option stimer;data;do i=1to N;end;run;

This increments a loop counter i and outputs the final value N to a SAS dataset. This is not optimised out, so the run time is linearly dependent on N.

\$\endgroup\$
0
\$\begingroup\$

Wolfram Language (Mathematica), 40 29 28 26 bytes

First@Timing@Do[,N]~Print~s

Try it online!

Replace N with number of times to do the operation. Does null N times (doing nothing is an operation in this case, as you can observe by increasing N and time increases).

\$\endgroup\$
0
\$\begingroup\$

MathGolf, 10 9 (or 12?) bytes

{t}]│Σûms

With \$n\$ as STDIN input.

Try it online.

If this is not allowed, it would be 3 bytes longer instead:

"#"i{t}]│Σûms

Where the # is replaced with the integer \$n\$ (i.e. "100"i{t}]│Σûms).

Try it online.

Both answers output the execution time in milliseconds without space.

Explanation:

Uses a similar approach as my 05AB1E answer.

               #  Use the (implicit) input-integer
               # Or alternatively:
"#"            #  Push the integer-string
   i           #  And convert it from a string to an integer
    { }        # Loop that many times
     t         # Push the current timestamp in milliseconds
       ]       # After the loop, wrap all times in a list
        |      # Get the forward differences of this list
         Σ     # Sum those differences
          ûms  # Push the string "ms"
               # (after which the entire stack joined together is output implicitly)

NOTE: Simply using 100 instead of "100" would add three digits (1,0,0) to the stack instead, which is why I have to do the "100"i to make it universal for all possible \$n\$.

]│Σ could alternatively be ⌐-Þ for the same byte-count: Try it online.

       ⌐        # Rotate all values on the stack clockwise
        -       # Subtract the top two values on the stack
         Þ      # Discard everything from the stack, except for the top item
\$\endgroup\$
  • \$\begingroup\$ "#" doesn't count as bytes anyway: That part must include a process whose total number of operations (and therefore execution time) is dependent on a user-substituted numeric value - this can be denoted in any way in your code (uppercase N for example) and doesn't count as a byte. \$\endgroup\$ – Lyxal Jan 13 at 21:00
0
\$\begingroup\$

PHP, 62 bytes

<?php $t=microtime(1);for(;$i<N;$i++);echo microtime(1)-$t.'s';

Try it online!

This is my first try in codeGolf, hope I get this right!

Some explanations:

  • microtime(true) gets timestamp in seconds as a float with the precision of microseconds
  • taking advatange that errors are discarded, so $i is not initialized
  • using automatic type conversions
\$\endgroup\$
  • \$\begingroup\$ Welcome to the site. How is input taken for this program? \$\endgroup\$ – Post Rock Garf Hunter Jan 13 at 17:46
  • 1
    \$\begingroup\$ That part must include a process whose total number of operations (and therefore execution time) is dependent on a user-substituted numeric value - this can be denoted in any way in your code (uppercase N for example) and doesn't count as a byte. -- seems like input can be hardcoded. \$\endgroup\$ – Lyxal Jan 13 at 20:59

Not the answer you're looking for? Browse other questions tagged or ask your own question.