Find the Run Time of Select Ruby Code - ruby

Problem
Howdy guys, so I want to find the run time of a block of code in Ruby, but I am not entirely sure as to how I could do it. I want to run some code, and then output how long it took to run that code because I have a super huge program and the run time changes a lot. I want to make sure it always has a consistent run time (I could do it by sleeping it for a fraction of a second) but that isn't my problem. I want to find out how long the run time actually is so the program can know if it needs to slow things down or speed things up.
My Thoughts
So, I have an idea as to how it could work. I have never used Time in ruby but I have an idea as to how I could use that. I could have a variable equal to the time (in milliseconds) and then another variable that I make at the end of the code block that does it again, and then I just subtract them, but I have (1) never used Time and (2) I don't actually know if that is the best way.
Thanks in advance!

Ruby has the Benchmark module for timing how long things take. I've never used this outside of seeing if a method is taking too long to run, etc. in development, not sure if this is 'recommended' for production code or for keeping things above a minimum runtime (as it sounds like you might be doing), but take a look and see how it feels for your use case.
It also sounds like you might be interested in the Timeout module as well (for making sure things don't take longer than a set amount of time).
If you really have a use case for making sure something takes a minimum amount of time, timing the code (either using a Benchmark method or just Time or another solution) and then sleep the difference is the only thing that comes to mind.

It is simple. Look at your watch (Time.now) and remember the time, run the code, look at your watch again, subtract.
t0 = Time.now
# your block of code
puts Time.now - t0

[http://ruby-doc.org/core-1.9.3/Time.html
You want to to use the Time object. (Time Docs)
For example,
start = Time.now
# code to time
finish = Time.now
diff = finish - start
diff would be in seconds, as a floating point number.
EDIT: end is reserved.
or you can use
require 'benchmark'
def foo
time = Benchmark.measure {
code to test
}
puts time.real #or save it to logs
end
Sample output:
2.2.3 :001 > foo
5.230000 0.020000 5.250000 ( 5.274806)
Values are CPU time, system time, total and real elapsed time.
[http://ruby-doc.org/stdlib-2.0.0/libdoc/benchmark/rdoc/Benchmark.html#method-c-bm
Source: Ruby docs.

Related

How can 'behave' be used to test time constraints?

I couldn't work out if Stack Overflow is an appropriate site to ask this and if not then what the appropriate site would be! There are so many stack exchange sites now and I didn't want to go through 200 sites :S
When I try and test whether my functions run within X seconds using behave (ie gherkin feature files and behave test steps), the code takes longer to run with behave testing than it would on its own. Especially at the beginning of the test but also in other parts.
Has anybody tested time constraints with behave before and know a workaround to adjust for the extra time that behave adds?
Is this even possible?
EDIT: To show how I'm timing the tests:
#when("the Python script provides images to the model")
def step_impl(context):
context.x_second_requirement = 5
# TODO: Investigate why this takes so long, when I'm not using behave I can use a 0.8 second timing constraint
context.start_time = time.time()
context.car_brain.tick()
context.end_time = time.time()
#then("the model must not take more than X seconds to produce output")
def step_impl(context):
assert context.end_time - context.start_time < context.x_second_requirement
Cheers,
Milan

Ruby poor performance in thread

I have a function that does IO/computation. I made a demo function which copies ~300MB from here to there. If I run it in a thread which I immediately join, it is much slower than if I run it without a thread. I checked with:
def cp
start = Time.now
FileUtils.cp_r("C:/tmp", "C:/tmp1")
fin = Time.now - start
p fin
end
Comparing these:
cp
Thread.new{cp}.join
the first cp call is always two to four times faster than the threaded call. The same happens if I do
cp
Thread.new{cp}
sleep 200
I heard about GIL, etc., but here, only one thread runs at a time, so no race for running time. Any ideas on how I can make it faster or why that is happening?
Threading isn't a guarantee that things will run faster, or even the same speed, as non-threaded code, at least currently with MRI. JRuby might be better. Your cp isn't getting the full attention of the CPU, which is why doing it without threading, and allowing it to block until done, is faster.
Consider using fork instead.
"A dozen (or so) ways to start sub-processes in Ruby: Part 1" looks useful. Also "How do you spawn a child process in Ruby?".

Calling Maple in Unix-shell without shell time overwriting

I have a question: I want to time some calculations using the UNIX-time command and I figured out that Maple (I use version 16) on Ubuntu 12.04 LTS (and some other machines I tested, including Macs) has some odd properties.
calling
time maple < testCalc.txt
where testCalc.txt contains the following code:
with(DETools):
DFactor(mult(x^5*d^5 + 6*x*d +1,x^5*d^5 + x^2*d^2 +7,[d,x]),[d,x]);
results in the following output:
memory used=65.5MB, alloc=72.9MB, time=0.69
memory used=199.6MB, alloc=149.9MB, time=1.84
memory used=312.4MB, alloc=149.9MB, time=2.97
memory used=592.3MB, alloc=312.4MB, time=5.63
memory used=854.7MB, alloc=312.4MB, time=9.80
["The Result (long)"]
memory used=1132.9MB, alloc=312.4MB, time=13.06
But the additional three lines of "time" say
real 0m47.872s
user 0m0.016s
sys 0m0.000s
Clearly, the user and sys time is wrong, as maple spend 13 seconds according to its own time measurement.
It seems to me that maple uses the same sources as the time command and resets the timer every time it uses it, such that the unix-time command only captures the time since the last call of maple to this source.
This is very inconvenient, and I would like to "forbid" maple doing that. Does anyone know how to do that? Is there some flag for calling maple that lets maple not measure the timestamps on its own?
Thanks in advance for an answer.
Albert
Ugly hack coming up.
As I said in my comment, the problem is that Maple is launching a sub-process to do all of the computations. So, I created a shell script called "mserver" in my bin that looks like
#!/bin/sh
/usr/bin/time "REPLACE WITH PATH TO MSERVER ON YOUR MACHINE/mserver" $* 2> log
I then invoked Maple as
maple --kernel-binary=/Users/me/bin/mserver
At the end of a run, the file log contains the correct "time" output for the computation.
Edit: I should point out that if the Maple protocols use stderr for anything, then this will eventually cause Maple to break. I haven't seen any sign of it but I've only just played with this now.

Kanwei minheap slow ruby

I had an implementation of a min heap in ruby that I wanted to test against more professional code but I cannot get Kanwei's MinHeap to work properly.
This:
mh = Containers::MinHeap.new # Min_Binary_Heap.new
for i in 0..99999
mh.push(rand(9572943))
end
t = Time.now
for i in 0..99999
mh.pop
end
t = Time.now - t
print "#{t}s"
The version I have performs the same popping operations on 100,000 values in ~2.2s, which I thought was extremely slow, but this won't even finish running. Is that expected or am I doing something wrong?
I don't think you are doing something wrong.
Looking at the source (https://github.com/kanwei/algorithms/blob/master/lib/containers/heap.rb), put a puts statement for when you finish setting up the heap. It looks like a very memory intensive operation to put the elements in (potentially resorting each time), so it might help you working through it.
I'm also not sure about him creating a node class for each actual node. Since they won't get cleaned up, there's going to be around 100,000 objects in memory by the time you are done.
Not sure how much help that is, maybe see how the source differs from your attempt?

Run rake script for specific time range

i need to run rake script for specific time. For example 10 minutes, 1 hour, etc., and if the script it's not finished stop it anyway.
Why i need this ? Because after some hours the memory is full!
Any suggestion ?
Thanks
I think you should first consider what is making this script use up so much memory.
(one thing would be loading up lots of records from the database, and appending them to an array)
But assuming you have already done everything you can,
I'd do something like this.
LIVE_FOR = 1.hour
def run!
finish_before = LIVE_FOR.from_now
array = get_the_array # some big collection to operate on
array.each do |object|
while Time.now < finish_before
...
end
end
end
But really, i'd first try to tackle why you have a memory leak.

Resources