Threads with high CPU usage

Hi, in an application of mine I start a long-running operation in a thread via forkIO so that the UI process doesn't get blocked. It just so happens, that the long-running process also takes the CPU to nearly 100% while it runs. During that time the run-time system does *not* switch back and forth between the UI-process and the long-running task, it seems that the UI process only gets woken up *after* the high CPU thread finishes completely. To the effect of course that it makes no difference at all to the UIs responsiveness whether I use forkIO or not. The long running process is pretty atomic, it's a single query to the database which takes up to a minute to complete so I don't see a chance to squeeze a "mainIteration" in there. What can I do? Günther

redcom:
Hi,
in an application of mine I start a long-running operation in a thread via forkIO so that the UI process doesn't get blocked. It just so happens, that the long-running process also takes the CPU to nearly 100% while it runs.
During that time the run-time system does *not* switch back and forth between the UI-process and the long-running task, it seems that the UI process only gets woken up *after* the high CPU thread finishes completely.
To the effect of course that it makes no difference at all to the UIs responsiveness whether I use forkIO or not.
The long running process is pretty atomic, it's a single query to the database which takes up to a minute to complete so I don't see a chance to squeeze a "mainIteration" in there.
How are you compiling this code (-O -threaded ?) and what does the forkIO'd thread do? Does it allocate? Would increasing the runtime scheduling ticks help? (Perhaps , if the UI is mostly sleeping). -- Don

On 2008 Dec 21, at 16:47, Don Stewart wrote:
redcom:
The long running process is pretty atomic, it's a single query to the database which takes up to a minute to complete so I don't see a chance to squeeze a "mainIteration" in there.
How are you compiling this code (-O -threaded ?) and what does the forkIO'd thread do? Does it allocate?
Sounds to me like it's making FFI calls to a database library. I smell bound threads, especially if the UI also makes FFI calls. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Hi Günter Günther Schmidt wrote:
Hi,
in an application of mine I start a long-running operation in a thread via forkIO so that the UI process doesn't get blocked. It just so happens, that the long-running process also takes the CPU to nearly 100% while it runs.
During that time the run-time system does *not* switch back and forth between the UI-process and the long-running task, it seems that the UI process only gets woken up *after* the high CPU thread finishes completely.
To the effect of course that it makes no difference at all to the UIs responsiveness whether I use forkIO or not.
The long running process is pretty atomic, it's a single query to the database which takes up to a minute to complete so I don't see a chance to squeeze a "mainIteration" in there.
It could be the database library, as it may use unsafe foreign calls. Unsafe foreign calls blocks all other threads, even if you compile with the -threaded option. See http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurren... . I cannot claim to know how all Haskell database libraries are implemented, but at least some of them use unsafe foreign calls. So which database library is you using?
What can I do?
If the problem has to do with unsafe foreign calls, then you can implement the database calls in a separate process. Not the easiest options, but I can think of no other.
Günther
/Mads Lindstrøm

Hi Günther,
Hi Mads,
I'm using HDBC with sqlite3
Looking at http://software.complete.org/software/repositories/entry/hdbc-sqlite3/Databa... and http://software.complete.org/software/repositories/entry/hdbc-sqlite3/Databa... you can see that HDBC-sqlite's foreign calls are indeed marked unsafe. /Mads
Günther
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Mads,
I just noticed that too.
I had been wondering why this problem does not occur with the sample app
from RWH eventhough I was employing the same technics as they did.
It just occured to me that all the DB interactions in their app are fairly
short and thus the problem never becomes apparent.
Thanks everyone, I was going crazy here, couldn't figure out what I was
doing wrong.
Would anyone happen to know of a "safe" alternative to HDBC?
Günther
Am 21.12.2008, 23:39 Uhr, schrieb Mads Lindstrøm
Hi Günther,
Hi Mads,
I'm using HDBC with sqlite3
Looking at http://software.complete.org/software/repositories/entry/hdbc-sqlite3/Databa... and http://software.complete.org/software/repositories/entry/hdbc-sqlite3/Databa... you can see that HDBC-sqlite's foreign calls are indeed marked unsafe.
/Mads
Günther
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

redcom:
Hi Mads,
I just noticed that too.
I had been wondering why this problem does not occur with the sample app from RWH eventhough I was employing the same technics as they did.
It just occured to me that all the DB interactions in their app are fairly short and thus the problem never becomes apparent.
Thanks everyone, I was going crazy here, couldn't figure out what I was doing wrong.
Would anyone happen to know of a "safe" alternative to HDBC?
Modify the 'unsafe' inports to be 'safe'? I don't think HDBC is going to call back in, so should be fine. John? That said, we use Takusen or sqlite3 at work, without troubles. -- Don

Hi Don,
Modify the 'unsafe' inports to be 'safe'? I don't think HDBC is going to call back in, so should be fine. John?
Sorry, total noob here, could you be more specific? Günther
That said, we use Takusen or sqlite3 at work, without troubles.
I might also check into that.
-- Don

Don Stewart
Modify the 'unsafe' inports to be 'safe'? I don't think HDBC is going to call back in, so should be fine. John?
For those who are puzzled, Don is suggesting that foreign import ccall unsafe "foo" :: Bar -> Baz should simply be changed to foreign import ccall safe "foo" :: Bar -> Baz And in case anyone is wondering whether fiddling with safety declarations is entirely wise: "unsafe" means I, the programmer, guarantee that this foreign function cannot call back into Haskell land, so you, the compiler, are free to do unsafe things when implementing the call. "safe" means I the programmer, cannot guarantee that this foreign function is safe, so please, you the compiler, make sure that you add extra checks and assurances to ensure that the call really will be safe in case it calls back into Haskell land. The terminology seems counter-intuitive, but in other other words, a "safe" call is slower but more flexible, an "unsafe" call is fast and dangerous. Therefore it is always OK to convert an "unsafe" declaration into a "safe" one, but never OK to convert from "safe" to "unsafe" without looking at what the foreign side actually does. Regards, Malcolm

On Mon, 2008-12-22 at 10:30 +0000, Malcolm Wallace wrote:
For those who are puzzled, Don is suggesting that foreign import ccall unsafe "foo" :: Bar -> Baz should simply be changed to foreign import ccall safe "foo" :: Bar -> Baz
And in case anyone is wondering whether fiddling with safety declarations is entirely wise:
"unsafe" means I, the programmer, guarantee that this foreign function cannot call back into Haskell land, so you, the compiler, are free to do unsafe things when implementing the call.
"safe" means I the programmer, cannot guarantee that this foreign function is safe, so please, you the compiler, make sure that you add extra checks and assurances to ensure that the call really will be safe in case it calls back into Haskell land.
The terminology seems counter-intuitive, but in other other words, a "safe" call is slower but more flexible, an "unsafe" call is fast and dangerous. Therefore it is always OK to convert an "unsafe" declaration into a "safe" one, but never OK to convert from "safe" to "unsafe" without looking at what the foreign side actually does.
And in general we would not even bother with considering using "unsafe" for calls that are already expensive. It's only worth considering when the length of the call is always very short. For example in a database library it might make sense to use 'unsafe' on the data-access functions that extract data from a local query result but we should always use 'safe' on any DB function that might want to talk to the network (eg to get more query results). Duncan

Duncan Coutts wrote:
On Mon, 2008-12-22 at 10:30 +0000, Malcolm Wallace wrote:
The terminology seems counter-intuitive, but in other other words, a "safe" call is slower but more flexible, an "unsafe" call is fast and dangerous. Therefore it is always OK to convert an "unsafe" declaration into a "safe" one, but never OK to convert from "safe" to "unsafe" without looking at what the foreign side actually does.
And in general we would not even bother with considering using "unsafe" for calls that are already expensive. It's only worth considering when the length of the call is always very short.
For example in a database library it might make sense to use 'unsafe' on the data-access functions that extract data from a local query result but we should always use 'safe' on any DB function that might want to talk to the network (eg to get more query results).
It's difficult to anticipate the needs here. For instance, some people may be using a few very-long-running queries measured in minutes, such as the original poster. Other people, such as web app developers, may be issuing literally millions of queries, right after another, where the difference matters. I had initially used "unsafe" because of the documented performance benefit, plus I certainly am not expecting Sqlite to call back into the Haskell runtime. It seems to me strange that using "unsafe" instead of "safe" would have negative implications for threading. After all, as Malcolm said above, "it is always OK to convert an unsafe declaration into a safe one". So could the compiler be made to be smart enough to do so when it is advantageous for threading purposes? What's the best way to make this suitable for both people with many queries and those with long-running queries? I should also add that I suspect the C calls that are bothering the original poster here are the standard ones for reading results, and could be called many, many times on even a single query. -- John

Hi,
I am not yet 100% certain that the unsafe calls are indeed the cause of
the problem, eventhough I strongly suspect there are.
I can tell you more once I have managed to rewrite all "unsafe" calls into
"safe" once, reinstall HDBC.Sqlite3 and then run my app again to see the
effects. My first attempt doing so was not successful, I'm not certain
whether I missed an "unsafe" call or the app is using an old version of
HDBC.Sqlite3 or whatever.
I understand that Takusen does not use "unsafe" calls and would like to
try it with that one then, but haven't find enough docs yet on how to use
Takusen.
Günther
Am 22.12.2008, 15:15 Uhr, schrieb John Goerzen
Duncan Coutts wrote:
On Mon, 2008-12-22 at 10:30 +0000, Malcolm Wallace wrote:
The terminology seems counter-intuitive, but in other other words, a "safe" call is slower but more flexible, an "unsafe" call is fast and dangerous. Therefore it is always OK to convert an "unsafe" declaration into a "safe" one, but never OK to convert from "safe" to "unsafe" without looking at what the foreign side actually does.
And in general we would not even bother with considering using "unsafe" for calls that are already expensive. It's only worth considering when the length of the call is always very short.
For example in a database library it might make sense to use 'unsafe' on the data-access functions that extract data from a local query result but we should always use 'safe' on any DB function that might want to talk to the network (eg to get more query results).
It's difficult to anticipate the needs here. For instance, some people may be using a few very-long-running queries measured in minutes, such as the original poster. Other people, such as web app developers, may be issuing literally millions of queries, right after another, where the difference matters.
I had initially used "unsafe" because of the documented performance benefit, plus I certainly am not expecting Sqlite to call back into the Haskell runtime.
It seems to me strange that using "unsafe" instead of "safe" would have negative implications for threading. After all, as Malcolm said above, "it is always OK to convert an unsafe declaration into a safe one". So could the compiler be made to be smart enough to do so when it is advantageous for threading purposes?
What's the best way to make this suitable for both people with many queries and those with long-running queries?
I should also add that I suspect the C calls that are bothering the original poster here are the standard ones for reading results, and could be called many, many times on even a single query.
-- John _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Günther Schmidt wrote:
Hi,
I am not yet 100% certain that the unsafe calls are indeed the cause of the problem, eventhough I strongly suspect there are.
I can tell you more once I have managed to rewrite all "unsafe" calls into "safe" once, reinstall HDBC.Sqlite3 and then run my app again to see the effects. My first attempt doing so was not successful, I'm not certain whether I missed an "unsafe" call or the app is using an old version of HDBC.Sqlite3 or whatever.
That is an interesting data point indeed. You might try to isolate the problem into some small section of code that reproduces it, so that we can do some more testing on our own systems. -- John
I understand that Takusen does not use "unsafe" calls and would like to try it with that one then, but haven't find enough docs yet on how to use Takusen.
Günther
Am 22.12.2008, 15:15 Uhr, schrieb John Goerzen
: Duncan Coutts wrote:
On Mon, 2008-12-22 at 10:30 +0000, Malcolm Wallace wrote:
The terminology seems counter-intuitive, but in other other words, a "safe" call is slower but more flexible, an "unsafe" call is fast and dangerous. Therefore it is always OK to convert an "unsafe" declaration into a "safe" one, but never OK to convert from "safe" to "unsafe" without looking at what the foreign side actually does. And in general we would not even bother with considering using "unsafe" for calls that are already expensive. It's only worth considering when the length of the call is always very short.
For example in a database library it might make sense to use 'unsafe' on the data-access functions that extract data from a local query result but we should always use 'safe' on any DB function that might want to talk to the network (eg to get more query results). It's difficult to anticipate the needs here. For instance, some people may be using a few very-long-running queries measured in minutes, such as the original poster. Other people, such as web app developers, may be issuing literally millions of queries, right after another, where the difference matters.
I had initially used "unsafe" because of the documented performance benefit, plus I certainly am not expecting Sqlite to call back into the Haskell runtime.
It seems to me strange that using "unsafe" instead of "safe" would have negative implications for threading. After all, as Malcolm said above, "it is always OK to convert an unsafe declaration into a safe one". So could the compiler be made to be smart enough to do so when it is advantageous for threading purposes?
What's the best way to make this suitable for both people with many queries and those with long-running queries?
I should also add that I suspect the C calls that are bothering the original poster here are the standard ones for reading results, and could be called many, many times on even a single query.
-- John _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

John Goerzen schrieb:
Günther Schmidt wrote:
Hi,
I am not yet 100% certain that the unsafe calls are indeed the cause of the problem, eventhough I strongly suspect there are.
I can tell you more once I have managed to rewrite all "unsafe" calls into "safe" once, reinstall HDBC.Sqlite3 and then run my app again to see the effects. My first attempt doing so was not successful, I'm not certain whether I missed an "unsafe" call or the app is using an old version of HDBC.Sqlite3 or whatever.
That is an interesting data point indeed. You might try to isolate the problem into some small section of code that reproduces it, so that we can do some more testing on our own systems.
-- John
I'd love to provide you with it but you'd have to manage a query that takes a long time to finish yourself.

From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Günther Schmidt
I understand that Takusen does not use "unsafe" calls and would like to try it with that one then, but haven't find enough docs yet on how to use Takusen.
Not a lot of detailed examples exist for Takusen. I'm hoping the documentation for Database.Enumerator is a reasonable place to start. http://darcs.haskell.org/takusen/doc/html/Database-Enumerator.html I just reviewed the Takusen code and, for no apparent reason, the ODBC module specifies unsafe for all of its FFI imports, but the other modules do not (so they get the default, which I assume is safe). I also was not aware of unsafe calls blocking other threads. I'll change the ODBC imports to be safe (or rather, unspecified). Alistair ***************************************************************** Confidentiality Note: The information contained in this message, and any attachments, may contain confidential and/or privileged material. It is intended solely for the person(s) or entity to which it is addressed. Any review, retransmission, dissemination, or taking of any action in reliance upon this information by persons or entities other than the intended recipient(s) is prohibited. If you received this in error, please contact the sender and delete the material from any computer. *****************************************************************

Hello Alistair, Monday, December 22, 2008, 7:28:03 PM, you wrote:
safe). I also was not aware of unsafe calls blocking other threads.
they don't to it directly. but without -threaded +RTS -N (or forkOS) there is only 1 OS thread that runs all haskell threads. unsafe call blocks it untill call finished, while safe call allows to reuse it for other haskell threads execution. i've attached old ghc commentary on this topic, although things may be significantly changed ATM -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Hi Alistair, what does it take to install Takusen on Win32 with Sqlite backend? I did manage to install *plain* Takusen via cabal install by downgrading to Cabal-1.4 but when I want to cabal-install takusen -fsqlite it complains about a missing sqlite3. What do I need to fix? Günther

From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Günther Schmidt
what does it take to install Takusen on Win32 with Sqlite backend?
I did manage to install *plain* Takusen via cabal install by downgrading to Cabal-1.4 but when I want to
cabal-install takusen -fsqlite
it complains about a missing sqlite3.
Setup.hs tries to find the location of your sqlite installation by looking for sqlite3.exe, so you need this (and sqlite.dll) in your path. Alistair ***************************************************************** Confidentiality Note: The information contained in this message, and any attachments, may contain confidential and/or privileged material. It is intended solely for the person(s) or entity to which it is addressed. Any review, retransmission, dissemination, or taking of any action in reliance upon this information by persons or entities other than the intended recipient(s) is prohibited. If you received this in error, please contact the sender and delete the material from any computer. *****************************************************************

Thanks Alistair, inspiration had stuck me meanwhile and that's exactly what I did. Günther Bayley, Alistair schrieb:
From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Günther Schmidt
what does it take to install Takusen on Win32 with Sqlite backend?
I did manage to install *plain* Takusen via cabal install by downgrading to Cabal-1.4 but when I want to
cabal-install takusen -fsqlite
it complains about a missing sqlite3.
Setup.hs tries to find the location of your sqlite installation by looking for sqlite3.exe, so you need this (and sqlite.dll) in your path.
Alistair ***************************************************************** Confidentiality Note: The information contained in this message, and any attachments, may contain confidential and/or privileged material. It is intended solely for the person(s) or entity to which it is addressed. Any review, retransmission, dissemination, or taking of any action in reliance upon this information by persons or entities other than the intended recipient(s) is prohibited. If you received this in error, please contact the sender and delete the material from any computer. *****************************************************************

On Mon, Dec 22, 2008 at 04:28:03PM -0000, Bayley, Alistair wrote:
From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Günther Schmidt
I understand that Takusen does not use "unsafe" calls and would like to try it with that one then, but haven't find enough docs yet on how to use Takusen.
Not a lot of detailed examples exist for Takusen. I'm hoping the documentation for Database.Enumerator is a reasonable place to start. http://darcs.haskell.org/takusen/doc/html/Database-Enumerator.html
I just reviewed the Takusen code and, for no apparent reason, the ODBC module specifies unsafe for all of its FFI imports, but the other modules do not (so they get the default, which I assume is safe). I also was not aware of unsafe calls blocking other threads. I'll change the ODBC imports to be safe (or rather, unspecified).
Makes sense. I will make the similar change in all HDBC backends. -- John

Hi guys,
I just tried to forkIO-off the database code to keep the UI responsive
using Takusen with Sqlite this time.
The problem persists though, the UI freezes.
AFAIK the sqlite-Takusen code does not use unsafe ccall which would block
the thread, so that might not be the cause of the problem after all.
Before you guys make the effort to "fix" this you might see if you can
reproduce the problem maybe uploading a 50 MB file into an Sqlite
database, for instance, or something else that will keep the database busy
for some time in a row.
I did not use -threaded and forkOS though.
Günther
Am 22.12.2008, 21:59 Uhr, schrieb John Goerzen
On Mon, Dec 22, 2008 at 04:28:03PM -0000, Bayley, Alistair wrote:
From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Günther Schmidt
I understand that Takusen does not use "unsafe" calls and would like to try it with that one then, but haven't find enough docs yet on how to use Takusen.
Not a lot of detailed examples exist for Takusen. I'm hoping the documentation for Database.Enumerator is a reasonable place to start. http://darcs.haskell.org/takusen/doc/html/Database-Enumerator.html
I just reviewed the Takusen code and, for no apparent reason, the ODBC module specifies unsafe for all of its FFI imports, but the other modules do not (so they get the default, which I assume is safe). I also was not aware of unsafe calls blocking other threads. I'll change the ODBC imports to be safe (or rather, unspecified).
Makes sense. I will make the similar change in all HDBC backends.
-- John

On Mon, 2008-12-22 at 22:12 +0100, Günther Schmidt wrote:
Hi guys,
I just tried to forkIO-off the database code to keep the UI responsive using Takusen with Sqlite this time.
The problem persists though, the UI freezes.
You might need to provide us more details on the GUI code. As I understand if you're using gtk2hs. You need to make sure that you're not blocking the GUI event loop by making blocking calls in event handlers. All blocking stuff has to be run via forkIO and the event handler must be allowed to return so that Gtk+ can redraw windows etc. In this context, by "blocking" I mean blocking a single Haskell thread, which is of course different from the safe/unsafe foreign calls which blocks a whole OS thread and thus all the Haskell threads. Duncan

Hi,
I put in on hpaste:
http://hpaste.org/13264
slightly simplified
Günther
Am 22.12.2008, 22:36 Uhr, schrieb Duncan Coutts
On Mon, 2008-12-22 at 22:12 +0100, Günther Schmidt wrote:
Hi guys,
I just tried to forkIO-off the database code to keep the UI responsive using Takusen with Sqlite this time.
The problem persists though, the UI freezes.
You might need to provide us more details on the GUI code. As I understand if you're using gtk2hs. You need to make sure that you're not blocking the GUI event loop by making blocking calls in event handlers. All blocking stuff has to be run via forkIO and the event handler must be allowed to return so that Gtk+ can redraw windows etc.
In this context, by "blocking" I mean blocking a single Haskell thread, which is of course different from the safe/unsafe foreign calls which blocks a whole OS thread and thus all the Haskell threads.
Duncan

On Mon, 2008-12-22 at 22:55 +0100, Günther Schmidt wrote:
Hi,
I put in on hpaste:
slightly simplified
Ok, that works fine when the action is something like threadDelay so it's clearly not blocking the UI. Duncan

Hi Duncan, are you saying then that the db-code is what's blocking the UI? Günther Duncan Coutts schrieb:
On Mon, 2008-12-22 at 22:55 +0100, Günther Schmidt wrote:
Hi,
I put in on hpaste:
slightly simplified
Ok, that works fine when the action is something like threadDelay so it's clearly not blocking the UI.
Duncan

You shouldn't need forkOS, but without -threaded (and related RTS
switches to enable multithreading) I think you are sunk. Without
enabling multithreading support, you are saying that your program
(which might use concurrency features of Haskell) will run on a single
OS thread. During a foreign call that never calls back into Haskell,
then, there's no place for the RTS to pre-empt and switch back to
Haskell code.
It's kind of confusing with multiple things named threads; call a
Haskell thread a "lightweight" thread, and an OS thread a "heavy"
thread. Each heavy thread can either be executing Haskell lightweight
threads, or inside a foreign out-call. Once you jump across to
foreign-land, the heavy thread can't do anything (even for a "safe"
out-call) until the out-call either makes an in-call back into Haskell
code, or returns.
Enabling -threaded allows the Haskell runtime to create more heavy
threads; even without -threaded you can make as many lightweight
threads as you like and the runtime will handle scheduling them for
you; a heavy thread can carry many light threads. But a foreign call
takes a whole heavy thread no matter what.
-- ryan
On Mon, Dec 22, 2008 at 1:12 PM, Günther Schmidt
Hi guys,
I just tried to forkIO-off the database code to keep the UI responsive using Takusen with Sqlite this time.
The problem persists though, the UI freezes.
AFAIK the sqlite-Takusen code does not use unsafe ccall which would block the thread, so that might not be the cause of the problem after all.
Before you guys make the effort to "fix" this you might see if you can reproduce the problem maybe uploading a 50 MB file into an Sqlite database, for instance, or something else that will keep the database busy for some time in a row.
I did not use -threaded and forkOS though.
Günther
Am 22.12.2008, 21:59 Uhr, schrieb John Goerzen
: On Mon, Dec 22, 2008 at 04:28:03PM -0000, Bayley, Alistair wrote:
From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Günther Schmidt
I understand that Takusen does not use "unsafe" calls and would like to try it with that one then, but haven't find enough docs yet on how to use Takusen.
Not a lot of detailed examples exist for Takusen. I'm hoping the documentation for Database.Enumerator is a reasonable place to start. http://darcs.haskell.org/takusen/doc/html/Database-Enumerator.html
I just reviewed the Takusen code and, for no apparent reason, the ODBC module specifies unsafe for all of its FFI imports, but the other modules do not (so they get the default, which I assume is safe). I also was not aware of unsafe calls blocking other threads. I'll change the ODBC imports to be safe (or rather, unspecified).
Makes sense. I will make the similar change in all HDBC backends.
-- John
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Ryan,
BINGO!
that did it.
Thanks a lot. It certainly works now, finally, eventhough I don't really
know what the implications are.
Günther
Am 23.12.2008, 02:14 Uhr, schrieb Ryan Ingram
You shouldn't need forkOS, but without -threaded (and related RTS switches to enable multithreading) I think you are sunk. Without enabling multithreading support, you are saying that your program (which might use concurrency features of Haskell) will run on a single OS thread. During a foreign call that never calls back into Haskell, then, there's no place for the RTS to pre-empt and switch back to Haskell code.
It's kind of confusing with multiple things named threads; call a Haskell thread a "lightweight" thread, and an OS thread a "heavy" thread. Each heavy thread can either be executing Haskell lightweight threads, or inside a foreign out-call. Once you jump across to foreign-land, the heavy thread can't do anything (even for a "safe" out-call) until the out-call either makes an in-call back into Haskell code, or returns.
Enabling -threaded allows the Haskell runtime to create more heavy threads; even without -threaded you can make as many lightweight threads as you like and the runtime will handle scheduling them for you; a heavy thread can carry many light threads. But a foreign call takes a whole heavy thread no matter what.
-- ryan
On Mon, Dec 22, 2008 at 1:12 PM, Günther Schmidt
wrote: Hi guys,
I just tried to forkIO-off the database code to keep the UI responsive using Takusen with Sqlite this time.
The problem persists though, the UI freezes.
AFAIK the sqlite-Takusen code does not use unsafe ccall which would block the thread, so that might not be the cause of the problem after all.
Before you guys make the effort to "fix" this you might see if you can reproduce the problem maybe uploading a 50 MB file into an Sqlite database, for instance, or something else that will keep the database busy for some time in a row.
I did not use -threaded and forkOS though.
Günther
Am 22.12.2008, 21:59 Uhr, schrieb John Goerzen
: On Mon, Dec 22, 2008 at 04:28:03PM -0000, Bayley, Alistair wrote:
From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Günther Schmidt
I understand that Takusen does not use "unsafe" calls and would like to try it with that one then, but haven't find enough docs yet on how to use Takusen.
Not a lot of detailed examples exist for Takusen. I'm hoping the documentation for Database.Enumerator is a reasonable place to start. http://darcs.haskell.org/takusen/doc/html/Database-Enumerator.html
I just reviewed the Takusen code and, for no apparent reason, the ODBC module specifies unsafe for all of its FFI imports, but the other modules do not (so they get the default, which I assume is safe). I also was not aware of unsafe calls blocking other threads. I'll change the ODBC imports to be safe (or rather, unspecified).
Makes sense. I will make the similar change in all HDBC backends.
-- John
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Thanks to you all for inspiration. My web app (which otherwise ran ok) was getting stuck while getting harassed by ab (apache-benchmark) after receiving some 800+ requests in short succession (not less, never gotten to 900, what was weird that running like 500 reqs - pause - 500 reqs ... went ok). After compiling with -threaded and running with +RTS -N2 it handles 10k+ requests (with 10 concurrent request running at once) without missing a beat. Well, at least I double checked everything else ;-)))

On Tue, 2008-12-23 at 03:56 +0100, wman wrote:
Thanks to you all for inspiration.
My web app (which otherwise ran ok) was getting stuck while getting harassed by ab (apache-benchmark) after receiving some 800+ requests in short succession (not less, never gotten to 900, what was weird that running like 500 reqs - pause - 500 reqs ... went ok).
After compiling with -threaded and running with +RTS -N2 it handles 10k+ requests (with 10 concurrent request running at once) without missing a beat.
How about compiled with -threaded and running with just +RTS -N1 ? I would expect the crucial thing is the -threaded not the number of cpus running Haskell code concurrently (-threaded uses a pool of OS threads to make blocking foreign calls effectively non-blocking). Duncan

Duncan Coutts wrote:
On Tue, 2008-12-23 at 03:56 +0100, wman wrote:
Thanks to you all for inspiration.
My web app (which otherwise ran ok) was getting stuck while getting harassed by ab (apache-benchmark) after receiving some 800+ requests in short succession (not less, never gotten to 900, what was weird that running like 500 reqs - pause - 500 reqs ... went ok).
After compiling with -threaded and running with +RTS -N2 it handles 10k+ requests (with 10 concurrent request running at once) without missing a beat.
How about compiled with -threaded and running with just +RTS -N1 ?
I would expect the crucial thing is the -threaded not the number of cpus running Haskell code concurrently (-threaded uses a pool of OS threads to make blocking foreign calls effectively non-blocking).
Exactly - adding another virtual CPU with +RTS -N2 should never turn a deadlocked program into a responsive one (unless there are threads busy not allocating anything, that is). Cheers, Simon

Thanks John! I've been running into this quite a bit with the ODBC backend
as well. Having an entire server app freeze because MS SQL Server decides to
deadlock is rather unpleasant.
Cheers,
Sterl.
On Mon, Dec 22, 2008 at 3:59 PM, John Goerzen
On Mon, Dec 22, 2008 at 04:28:03PM -0000, Bayley, Alistair wrote:
From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Günther Schmidt
I understand that Takusen does not use "unsafe" calls and would like to try it with that one then, but haven't find enough docs yet on how to use Takusen.
Not a lot of detailed examples exist for Takusen. I'm hoping the documentation for Database.Enumerator is a reasonable place to start. http://darcs.haskell.org/takusen/doc/html/Database-Enumerator.html
I just reviewed the Takusen code and, for no apparent reason, the ODBC module specifies unsafe for all of its FFI imports, but the other modules do not (so they get the default, which I assume is safe). I also was not aware of unsafe calls blocking other threads. I'll change the ODBC imports to be safe (or rather, unspecified).
Makes sense. I will make the similar change in all HDBC backends.
-- John
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hello John, Monday, December 22, 2008, 5:15:46 PM, you wrote:
And in general we would not even bother with considering using "unsafe" for calls that are already expensive. It's only worth considering when the length of the call is always very short.
the other way to look at it is to measure overhead of safe call. on 1 GHz Duron i measured 66.000 calls of trivial safe function per second, meaning 16.000 cpu ticks per call (ghc 6.8). it's rather large overhead for many trivial functions, but for calls to sql engine it seems rather small -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On Mon, 2008-12-22 at 08:15 -0600, John Goerzen wrote:
Duncan Coutts wrote:
On Mon, 2008-12-22 at 10:30 +0000, Malcolm Wallace wrote:
The terminology seems counter-intuitive, but in other other words, a "safe" call is slower but more flexible, an "unsafe" call is fast and dangerous. Therefore it is always OK to convert an "unsafe" declaration into a "safe" one, but never OK to convert from "safe" to "unsafe" without looking at what the foreign side actually does.
And in general we would not even bother with considering using "unsafe" for calls that are already expensive. It's only worth considering when the length of the call is always very short.
For example in a database library it might make sense to use 'unsafe' on the data-access functions that extract data from a local query result but we should always use 'safe' on any DB function that might want to talk to the network (eg to get more query results).
It's difficult to anticipate the needs here. For instance, some people may be using a few very-long-running queries measured in minutes, such as the original poster. Other people, such as web app developers, may be issuing literally millions of queries, right after another, where the difference matters.
The cost of a safe call is not really that high. In comparison to something a C function that just extracts a member from a structure it's high, but compared to executing even a simple SQL query I expect it's not even measurable.
I had initially used "unsafe" because of the documented performance benefit, plus I certainly am not expecting Sqlite to call back into the Haskell runtime.
It seems to me strange that using "unsafe" instead of "safe" would have negative implications for threading. After all, as Malcolm said above, "it is always OK to convert an unsafe declaration into a safe one". So could the compiler be made to be smart enough to do so when it is advantageous for threading purposes?
I think it could only do it by turning all "unsafe" functions into "safe" ones. As I understand it, the ability to switch rts capability is the more expensive of the properties that "safe" provides (compared to allowing the function to be re-entrant) because it involves pthread mutexes.
What's the best way to make this suitable for both people with many queries and those with long-running queries?
If the squlite API distinguishes executing a query (potentially long running) from extracting data from the result set (always quick) then it would be possible to mark the former safe and the latter unsafe and still not impose any great overhead on any user. Duncan

John Goerzen wrote:
Duncan Coutts wrote:
On Mon, 2008-12-22 at 10:30 +0000, Malcolm Wallace wrote:
The terminology seems counter-intuitive, but in other other words, a "safe" call is slower but more flexible, an "unsafe" call is fast and dangerous. Therefore it is always OK to convert an "unsafe" declaration into a "safe" one, but never OK to convert from "safe" to "unsafe" without looking at what the foreign side actually does. And in general we would not even bother with considering using "unsafe" for calls that are already expensive. It's only worth considering when the length of the call is always very short.
For example in a database library it might make sense to use 'unsafe' on the data-access functions that extract data from a local query result but we should always use 'safe' on any DB function that might want to talk to the network (eg to get more query results).
It's difficult to anticipate the needs here. For instance, some people may be using a few very-long-running queries measured in minutes, such as the original poster. Other people, such as web app developers, may be issuing literally millions of queries, right after another, where the difference matters.
I'd be really interested to know whether you can actually measure a difference between safe and unsafe foreign calls for something complicated like a database query. Do you have any figures? If it turns out that "safe" calls are a bottleneck, then there might be room for optimisation there.
I had initially used "unsafe" because of the documented performance benefit, plus I certainly am not expecting Sqlite to call back into the Haskell runtime.
It seems to me strange that using "unsafe" instead of "safe" would have negative implications for threading. After all, as Malcolm said above, "it is always OK to convert an unsafe declaration into a safe one". So could the compiler be made to be smart enough to do so when it is advantageous for threading purposes?
It's not possible to make the choice at runtime without compromising the efficiency of "unsafe" calls. An "unsafe" call is just an inline call to the C function, whereas a "safe" call is wrapped in a couple of calls into the RTS to save/restore the Haskell state. Cheers, Simon

Hello Günther, Monday, December 22, 2008, 1:57:22 AM, you wrote: try -threaded, +RTS -N2, and forkOS simultaneously. it may work - i don't see reasons why other threads should be freezd why one does unsafe call nother solution is to compile library with unsafe call changed to safe. this change is always safe but make call ~10mcs slower :)
Hi Mads,
I just noticed that too.
I had been wondering why this problem does not occur with the sample app from RWH eventhough I was employing the same technics as they did.
It just occured to me that all the DB interactions in their app are fairly short and thus the problem never becomes apparent.
Thanks everyone, I was going crazy here, couldn't figure out what I was doing wrong.
Would anyone happen to know of a "safe" alternative to HDBC?
Günther
Am 21.12.2008, 23:39 Uhr, schrieb Mads Lindstrøm
:
Hi Günther,
Hi Mads,
I'm using HDBC with sqlite3
Looking at http://software.complete.org/software/repositories/entry/hdbc-sqlite3/Databa... and http://software.complete.org/software/repositories/entry/hdbc-sqlite3/Databa... you can see that HDBC-sqlite's foreign calls are indeed marked unsafe.
/Mads
Günther
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Bulat Ziganshin wrote:
Hello Günther,
Monday, December 22, 2008, 1:57:22 AM, you wrote:
try -threaded, +RTS -N2, and forkOS simultaneously. it may work - i don't see reasons why other threads should be freezd why one does unsafe call
Please don't suggest using forkOS - it will probably harm performance and do nothing else, unless you actually need it (i.e. you're using OpenGL). Cheers, Simon

Would forkOS instead of forkIO help in this case?
On Sun, Dec 21, 2008 at 11:16 PM, Mads Lindstrøm
Hi Günter
Günther Schmidt wrote:
Hi,
in an application of mine I start a long-running operation in a thread via forkIO so that the UI process doesn't get blocked. It just so happens, that the long-running process also takes the CPU to nearly 100% while it runs.
During that time the run-time system does *not* switch back and forth between the UI-process and the long-running task, it seems that the UI process only gets woken up *after* the high CPU thread finishes completely.
To the effect of course that it makes no difference at all to the UIs responsiveness whether I use forkIO or not.
The long running process is pretty atomic, it's a single query to the database which takes up to a minute to complete so I don't see a chance to squeeze a "mainIteration" in there.
It could be the database library, as it may use unsafe foreign calls. Unsafe foreign calls blocks all other threads, even if you compile with the -threaded option. See
http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurren....
I cannot claim to know how all Haskell database libraries are implemented, but at least some of them use unsafe foreign calls. So which database library is you using?
What can I do?
If the problem has to do with unsafe foreign calls, then you can implement the database calls in a separate process. Not the easiest options, but I can think of no other.
Günther
/Mads Lindstrøm
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Peter, Peter Verswyvelen wrote:
Would forkOS instead of forkIO help in this case?
No, according to http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurren... : "Using forkOS instead of forkIO makes no difference at all to the scheduling behaviour of the Haskell runtime system. It is a common misconception that you need to use forkOS instead of forkIO to avoid blocking all the Haskell threads when making a foreign call; this isn't the case. To allow foreign calls to be made without blocking all the Haskell threads (with GHC), it is only necessary to use the -threaded option when linking your program, and to make sure the foreign import is not marked unsafe." /Mads
On Sun, Dec 21, 2008 at 11:16 PM, Mads Lindstrøm
wrote: Hi Günter Günther Schmidt wrote: > Hi, > > in an application of mine I start a long-running operation in a thread via > forkIO so that the UI process doesn't get blocked. > It just so happens, that the long-running process also takes the CPU to > nearly 100% while it runs. > > During that time the run-time system does *not* switch back and forth > between the UI-process and the long-running task, it seems that the UI > process only gets woken up *after* the high CPU thread finishes completely. > > To the effect of course that it makes no difference at all to the UIs > responsiveness whether I use forkIO or not. > > The long running process is pretty atomic, it's a single query to the > database which takes up to a minute to complete so I don't see a chance to > squeeze a "mainIteration" in there.
It could be the database library, as it may use unsafe foreign calls. Unsafe foreign calls blocks all other threads, even if you compile with the -threaded option. See http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurren... .
I cannot claim to know how all Haskell database libraries are implemented, but at least some of them use unsafe foreign calls. So which database library is you using?
> > What can I do?
If the problem has to do with unsafe foreign calls, then you can implement the database calls in a separate process. Not the easiest options, but I can think of no other.
> > Günther >
/Mads Lindstrøm
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Tried running the program with +RTS -Nn where n = 2 or more? that should use
more OS threads
On Sun, Dec 21, 2008 at 10:43 PM, Günther Schmidt
Hi,
in an application of mine I start a long-running operation in a thread via forkIO so that the UI process doesn't get blocked. It just so happens, that the long-running process also takes the CPU to nearly 100% while it runs.
During that time the run-time system does *not* switch back and forth between the UI-process and the long-running task, it seems that the UI process only gets woken up *after* the high CPU thread finishes completely.
To the effect of course that it makes no difference at all to the UIs responsiveness whether I use forkIO or not.
The long running process is pretty atomic, it's a single query to the database which takes up to a minute to complete so I don't see a chance to squeeze a "mainIteration" in there.
What can I do?
Günther
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (16)
-
Andrea Vezzosi
-
Bayley, Alistair
-
Brandon S. Allbery KF8NH
-
Bulat Ziganshin
-
Don Stewart
-
Duncan Coutts
-
Guenther Schmidt
-
Günther Schmidt
-
John Goerzen
-
Mads Lindstrøm
-
Malcolm Wallace
-
Peter Verswyvelen
-
Ryan Ingram
-
Simon Marlow
-
Sterling Clover
-
wman