Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#5367 closed bug (wontfix)

Program in (-N1) runs 10 times slower than it with two threads (-N2)

Reported by: wuxb Owned by: simonmar
Priority: high Milestone: 7.4.1
Component: Runtime System Version: 7.0.4
Keywords: thread ffi Cc:
Operating System: Linux Architecture: x86_64 (amd64)
Type of failure: Runtime performance bug Test Case:
Blocked By: Blocking:
Related Tickets: Differential Revisions:

Description

Initially I want to do some test on threads, I wrote this program(see below) to test the performance when two thread operates on same memory location.
but with (-N2) rts options, it works normally, but with (-N1), the CPU work load became vary low (30%~40%). it uses much more time to finish.

no -threaded : 3.7s (wall clock time)
-N2 : 4.0s (wall clock time)
-N1 : 20.0s(wall clock time)

(forkIO/FFI/MVar/Ptr are used in this program).
(fedora-15/ghc-7.0.4; windows-64/ghc-7.0.3).

source code & log messages will be in attached files.

Attachments (1)

two.hs (3.3 KB) - added by wuxb 4 years ago.
source & log

Download all attachments as: .zip

Change History (5)

Changed 4 years ago by wuxb

source & log

comment:1 Changed 4 years ago by simonmar

  • Milestone set to 7.4.1
  • Owner set to simonmar
  • Priority changed from normal to high

Thanks, I'll take a look.

comment:2 Changed 4 years ago by daniel.is.fischer

I can reproduce the behaviour with 7.0.4 and 6.12.3. However, occasionally -N2 is as slow as -N1.

comment:3 Changed 4 years ago by simonmar

  • Resolution set to wontfix
  • Status changed from new to closed

I've made it slightly faster (patch coming shortly), but the basic problem here is safe foreign calls. In the threaded RTS, a safe foreign call wakes up a second OS thread just in case the call blocks, so that the other Haskell threads can continue running. Often the second OS thread will find nothing to do, and will just go to sleep again. In the program here, there are two Haskell threads, so the when the second OS thread runs there is a Haskell thread on the run queue, and with a high probability the original OS thread is in the middle of a foreign call so the second OS thread "steals" the RTS and starts running the other Haskell thread. Result is a lot of context-switching of OS threads, which is expensive.

With -N2 we're back in the situation where the newly woken OS thread has nothing to do again, so it doesn't steal the RTS, and we don't get a lot of context switching.

The fix is easy: put unsafe on your foreign calls, unless you really need them to be safe.

I don't know of a way to improve this without more OS support. If we had scheduler activations (Windows 7 has these) we could do this properly and avoid the unnecessary context switching.

comment:4 Changed 4 years ago by marlowsd@…

commit 78e6b615329dd8ea4527b499107048693c87f895

Author: Simon Marlow <[email protected]>
Date:   Wed Aug 3 13:41:33 2011 +0100

    small optimisation for the program in #5367: if the worker thread
    being woken already has its wakeup flag set, don't bother signalling
    its condition variable again.

 rts/Capability.c |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)
Note: See TracTickets for help on using tickets.