Forum: Ruby Slowing threads

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
37ee5fa90f5eaeef62553629382497f7?d=identicon&s=25 Leslie Viljoen (Guest)
on 2006-05-10 21:50
(Received via mailing list)
Hi!

I have written a program that simulates three "consoles" that accept
keyboard input and run concurrently. You can type commands which each
run at different speeds without interfering with other commands. It
works but it's complex and I think it can be simpler if I have each
command run in it's own thread - at the moment I don't use threads at
all.

So I have been creating threads to test and playing with priorities.
I'd like to be able to control the speed at which processes run but if
I set a thread to just one priority higher than another, it is
scheduled tens of thousands of times more often.

So:

1. What do the priorities actually mean?
2. If I have to slow one thread just a little, that means messy
sleep() commands on every second line. Is there a way I can call just
parts of a passed-in block?
ie. can I do something similar to this:

def sleeper(&block)
        block.each_command do |c|
              eval(c)
              sleep(0.5)
        end
end

sleeper do
        puts "one"
        puts "two"
        puts "three"
end

If it's too much magic I'll just intersperse with sleep, just thought
there might be a better way.
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-05-10 22:02
(Received via mailing list)
On May 10, 2006, at 3:48 PM, Leslie Viljoen wrote:

> I'd like to be able to control the speed at which processes run but if
>
>        puts "three"
> end
>
> If it's too much magic I'll just intersperse with sleep, just thought
> there might be a better way.
>

If you really want this much fine grained control over the thread
scheduler it probably means patching ruby itself. OTOH that would
probably be cool.
481b8eedcc884289756246e12d1869c1?d=identicon&s=25 Francis Cianfrocca (Guest)
on 2006-05-10 23:38
(Received via mailing list)
It's rarely a good idea to modify the priorities of threads in Unix
systems.
Almost all thread-schedulers will never schedule a thread if there is at
least one runnable thread with a higher priority, which explains the
results
you describe. Your lower-priority threads will basically only get
scheduled
when they're lucky enough to find the highest-priority thread
non-runnable.
If you mess with priorities, you also face the risk of priority
inversions,
where a high-priority thread requires a resource held by a
lower-priority
thread, and they lock each other.

Keep it simple. Sounds like the semantics of your application is to
simulate
users working at different rates. There's nothing there that implies a
dependence among the threads. I'd use random sleep intervals.
37ee5fa90f5eaeef62553629382497f7?d=identicon&s=25 Leslie Viljoen (Guest)
on 2006-05-11 00:21
(Received via mailing list)
On 5/10/06, Francis Cianfrocca <garbagecat10@gmail.com> wrote:
> users working at different rates. There's nothing there that implies a
> dependence among the threads. I'd use random sleep intervals.

Thanks. I'll probably have a command put together a list of
"micro-tasks" and "execute" each one with a random sleep afterwards.
Not too bad.

Like so:

def command_ls(processorLoad)
	microCommands = [] << makeReadDiskMicroCommands(10)

	filesText = getFiles.join("\n")
	microCommands = << filesText.makeWritelineMicroCommands

	loop do
		doMicroCommand(microCommands.shift)
		sleep(rand(processorLoad))
		break if microCommands.empty?
	end
end
49ab3ce5a4922b4747d1d6f330784629?d=identicon&s=25 Jake McArthur (Guest)
on 2006-05-11 18:04
(Received via mailing list)
Insert the following code somewhere in your main thread:

class Thread
   attr_accessor :execution_speed
end

def set_execution_speed(seconds_per_line)
   Thread.current.execution_speed = seconds_per_line
   set_trace_func proc { |event, file, line, id, binding, classname|
     if event == "line" and !Thread.current.execution_speed.nil?
       sleep Thread.current.execution_speed
     end
   }
end

Then, at the beginning of any thread you want slowed down, call the
set_execution_speed method. This will limit the rate that each line
of code in the thread is executed. You can also modify the method so
that it limits based on other criteria such as method calls.

- Jake McArthur
58479f76374a3ba3c69b9804163f39f4?d=identicon&s=25 Eric Hodel (Guest)
on 2006-05-11 20:09
(Received via mailing list)
On May 11, 2006, at 9:00 AM, Jake McArthur wrote:

>       sleep Thread.current.execution_speed
>     end
>   }
> end
>
> Then, at the beginning of any thread you want slowed down, call the
> set_execution_speed method. This will limit the rate that each line
> of code in the thread is executed. You can also modify the method
> so that it limits based on other criteria such as method calls.

set_trace_proc will make your program run much slower than you expect.

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com
37ee5fa90f5eaeef62553629382497f7?d=identicon&s=25 Leslie Viljoen (Guest)
on 2006-05-13 00:33
(Received via mailing list)
On 5/11/06, Jake McArthur <jake.mcarthur@gmail.com> wrote:
>        sleep Thread.current.execution_speed
>      end
>    }
> end
>
> Then, at the beginning of any thread you want slowed down, call the
> set_execution_speed method. This will limit the rate that each line
> of code in the thread is executed. You can also modify the method so
> that it limits based on other criteria such as method calls.

Thanks Jake, this is a very cool idea! Pretty sure it won't be fast
enough (this is for a game) - but I have been playing with
set_trace_func quite a bit since your post.
This topic is locked and can not be replied to.