Multi-threading.

classic Classic list List threaded Threaded
58 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Multi-threading.

Roushan Ali
Hello all,
          Can we use single sqlite_open handle(global) across threads(
if all database operations are serialized by using semaphore) ? Please
help.
           
 

Regards,
Roushan    
       

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

D. Richard Hipp
On Fri, 2005-07-15 at 16:41 +0530, Roushan Ali wrote:
> Hello all,
>           Can we use single sqlite_open handle(global) across threads(
> if all database operations are serialized by using semaphore) ? Please
> help.
>            

Opening a database connection in one thread and using it in another
will work on some operating systems but not on others.  You are
advised not to do it.  See http://www.sqlite.org/cvstrac/tktview?tn=1272
and http://www.sqlite.org/cvstrac/chngview?cn=2521.

Actually, this seems like a good opportunity to repeat my
oft-ignored advice to not use more than one thread in a single
address space.  If you need multiple threads, create multiple
processes.  This has nothing to do with SQLite = it is just
good programming advice.  I have worked on countless multi-
threaded programs over the years, and I have yet to see a
single one that didn't contain subtle, hard to reproduce,
and very hard to troubleshoot bugs related to threading issues.

I am constantly amazed at the prevailing idea (exemplified
by Java) that software should be strongly typed and should
not use goto statement or pointers - all in the name of
reducing bugs - but that it is OK to use multiple threads
within the same address space.  Strong typing helps prevent
only bugs that are trivially easy to locate and fix.  The
use of goto statements and pointers likewise results in
deterministic problems that are easy to test for and
relatively easy to track down and correct.  But threading
bugs tend to manifest themselves as timing-dependent
glitches and lock-ups that are hardware and platform
dependent, that never happen the same way twice, and that
only appear for customers after deployment and never in a
testing environment.
--
D. Richard Hipp <[hidden email]>

Reply | Threaded
Open this post in threaded view
|

sqlite3_errmsg

Marco Bambini
Have I to free the string buffer returned by sqlite3_errmsg?

If I write something like:

char *err;
err = (char *) sqlite3_errmsg(db);
if (err) sqlite3_free(err);
or
if (err) free(err);

then, OSX gives me a "Deallocation of a pointer not malloced" error...
So it seems that I haven't to free it, right?

Any help?

Thanks,
Marco Bambini
Reply | Threaded
Open this post in threaded view
|

RE: Multi-threading.

Cariotoglou Mike
In reply to this post by Roushan Ali
which gives me the opportunity to repear my oft-ignored reply :)

what you say is true, provided the OS is geared towards multiple
processes. which is not true for windows, but is true for *ix, as400 and
other environments. if you need, say, a server that handles 500
sessions, and attempt to do this with spawning processes on windows, you
are probably dead,
memory and cpu-wise. on Linux, this is nothing, it can handle it easily.
otoh, 500 threads for windows is business as usual, but threading on
Linux, is , I hear, iffy at best.

so, although this is good advice, it is not unconditionally applicable.

> -----Original Message-----
> From: D. Richard Hipp [mailto:[hidden email]]
> Sent: Friday, July 15, 2005 3:27 PM
> To: [hidden email]
> Subject: Re: [sqlite] Multi-threading.
>
> On Fri, 2005-07-15 at 16:41 +0530, Roushan Ali wrote:
> > Hello all,
> >           Can we use single sqlite_open handle(global)
> across threads(
> > if all database operations are serialized by using
> semaphore) ? Please
> > help.
> >            
>
> Opening a database connection in one thread and using it in
> another will work on some operating systems but not on
> others.  You are advised not to do it.  See
> http://www.sqlite.org/cvstrac/tktview?tn=1272
> and http://www.sqlite.org/cvstrac/chngview?cn=2521.
>
> Actually, this seems like a good opportunity to repeat my
> oft-ignored advice to not use more than one thread in a
> single address space.  If you need multiple threads, create
> multiple processes.  This has nothing to do with SQLite = it
> is just good programming advice.  I have worked on countless
> multi- threaded programs over the years, and I have yet to
> see a single one that didn't contain subtle, hard to
> reproduce, and very hard to troubleshoot bugs related to
> threading issues.
>
> I am constantly amazed at the prevailing idea (exemplified by
> Java) that software should be strongly typed and should not
> use goto statement or pointers - all in the name of reducing
> bugs - but that it is OK to use multiple threads within the
> same address space.  Strong typing helps prevent only bugs
> that are trivially easy to locate and fix.  The use of goto
> statements and pointers likewise results in deterministic
> problems that are easy to test for and relatively easy to
> track down and correct.  But threading bugs tend to manifest
> themselves as timing-dependent glitches and lock-ups that are
> hardware and platform dependent, that never happen the same
> way twice, and that only appear for customers after
> deployment and never in a testing environment.
> --
> D. Richard Hipp <[hidden email]>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Roushan Ali
In reply to this post by D. Richard Hipp
Thanks Richard for your reply.

Actually, we have written a windows application which uses four threads.
Each thread may have to add/delete thousands of entries in the database(
for performance reason , we don't want to open/close  the database for
each insertion/deletion) .If we use different sqlite_open handle for
each thread , then one thread has to do busy looping until other threads
complete their operation, which is not desirable according to the
application requirement. That's why we opened global database handle for
the lifetime of the application and each thread used the handle serially
and it worked.

Thanking you again,
Roushan
 
 
On Fri, 2005-07-15 at 17:57, D. Richard Hipp wrote:

> On Fri, 2005-07-15 at 16:41 +0530, Roushan Ali wrote:
> > Hello all,
> >           Can we use single sqlite_open handle(global) across threads(
> > if all database operations are serialized by using semaphore) ? Please
> > help.
> >            
>
> Opening a database connection in one thread and using it in another
> will work on some operating systems but not on others.  You are
> advised not to do it.  See http://www.sqlite.org/cvstrac/tktview?tn=1272
> and http://www.sqlite.org/cvstrac/chngview?cn=2521.
>
> Actually, this seems like a good opportunity to repeat my
> oft-ignored advice to not use more than one thread in a single
> address space.  If you need multiple threads, create multiple
> processes.  This has nothing to do with SQLite = it is just
> good programming advice.  I have worked on countless multi-
> threaded programs over the years, and I have yet to see a
> single one that didn't contain subtle, hard to reproduce,
> and very hard to troubleshoot bugs related to threading issues.
>
> I am constantly amazed at the prevailing idea (exemplified
> by Java) that software should be strongly typed and should
> not use goto statement or pointers - all in the name of
> reducing bugs - but that it is OK to use multiple threads
> within the same address space.  Strong typing helps prevent
> only bugs that are trivially easy to locate and fix.  The
> use of goto statements and pointers likewise results in
> deterministic problems that are easy to test for and
> relatively easy to track down and correct.  But threading
> bugs tend to manifest themselves as timing-dependent
> glitches and lock-ups that are hardware and platform
> dependent, that never happen the same way twice, and that
> only appear for customers after deployment and never in a
> testing environment.

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Dennis Jenkins
Roushan Ali wrote:

>Thanks Richard for your reply.
>
>Actually, we have written a windows application which uses four threads.
>Each thread may have to add/delete thousands of entries in the database(
>for performance reason , we don't want to open/close  the database for
>each insertion/deletion) .If we use different sqlite_open handle for
>each thread , then one thread has to do busy looping until other threads
>complete their operation, which is not desirable according to the
>application requirement. That's why we opened global database handle for
>the lifetime of the application and each thread used the handle serially
>and it worked.
>
>  
>
We have a multi-threaded windows application with four threads.  Three
threads need access to the database (all three are producers and
consumers), but one thread is the GUI thread and wants to access the
database while handling WM_TIMER messages (re-entrency issues).  So we
allocate 4 database connections during initialization.  Each section of
our code uses its own connection.  We have a special "stress test" mode
that we can enable.  The program remains stable after hours of operation
under the stress test.  The program will slow down because of the
database locking mechanism (especially during large transactions), but
it has never crashed due to multiple threads accessing the database used
_different_ connection objects.

If you are going to be multi-threaded, then why not just use multiple
connection objects (structs - ours are wrapped in a C++ class)?

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Gerhard Häring
In reply to this post by D. Richard Hipp
On Fri, Jul 15, 2005 at 08:27:14AM -0400, D. Richard Hipp wrote:

> [...]
> I am constantly amazed at the prevailing idea (exemplified
> by Java) that software should be strongly typed and should
> not use goto statement or pointers - all in the name of
> reducing bugs - but that it is OK to use multiple threads
> within the same address space.  Strong typing helps prevent
> only bugs that are trivially easy to locate and fix.  The
> use of goto statements and pointers likewise results in
> deterministic problems that are easy to test for and
> relatively easy to track down and correct.  But threading
> bugs tend to manifest themselves as timing-dependent
> glitches and lock-ups that are hardware and platform
> dependent, that never happen the same way twice, and that
> only appear for customers after deployment and never in a
> testing environment.
My quote of the week :-)

-- Gerhard
--
Gerhard Häring - [hidden email] - Python, web & database development

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Roushan Ali
In reply to this post by Dennis Jenkins
 Hi,
   Thanks for your response. I don't have any idea how multiple
connection objects work. Can you please tell us something about that.

Thanks,
Roushan

On Fri, 2005-07-15 at 20:15, Dennis Jenkins wrote:

> Roushan Ali wrote:
>
> >Thanks Richard for your reply.
> >
> >Actually, we have written a windows application which uses four threads.
> >Each thread may have to add/delete thousands of entries in the database(
> >for performance reason , we don't want to open/close  the database for
> >each insertion/deletion) .If we use different sqlite_open handle for
> >each thread , then one thread has to do busy looping until other threads
> >complete their operation, which is not desirable according to the
> >application requirement. That's why we opened global database handle for
> >the lifetime of the application and each thread used the handle serially
> >and it worked.
> >
> >  
> >
> We have a multi-threaded windows application with four threads.  Three
> threads need access to the database (all three are producers and
> consumers), but one thread is the GUI thread and wants to access the
> database while handling WM_TIMER messages (re-entrency issues).  So we
> allocate 4 database connections during initialization.  Each section of
> our code uses its own connection.  We have a special "stress test" mode
> that we can enable.  The program remains stable after hours of operation
> under the stress test.  The program will slow down because of the
> database locking mechanism (especially during large transactions), but
> it has never crashed due to multiple threads accessing the database used
> _different_ connection objects.
>
> If you are going to be multi-threaded, then why not just use multiple
> connection objects (structs - ours are wrapped in a C++ class)?
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Dennis Jenkins
Roushan Ali wrote:

> Hi,
>   Thanks for your response. I don't have any idea how multiple
>connection objects work. Can you please tell us something about that.
>  
>
I wrappered the C interface to SQLite3 via a C++ Class called
"CSqlite3".  The constructor does NOT open the database, it just
allocates the sqlite struct.

I declared 4 global instances of this class.  The constructors get
called before my WinMain().

In my initialization code (called before any threads are created), I
open the database 4 times.  I do an integrity check (and some other
logic) after the first open.  Like this:

g_DbMain.Open(szFilename);
CheckDatabase(g_DbMain); // "pragma integrity_check, create missing
tables / schema updates, vacuum"
g_DbTimer.Open(szFilename);
g_DbThread2.Open(szFilename);
g_DbThread3.Open(szFilename);

I then create the worker threads.  One of my threads does NOT use any
database, so we'll ignore it.  Another thread (main / gui) already
exists, so I am really only creating threads #2 and #3.  The thread
function uses the database object as needed.

After the worker threads terminate, the main thread closes all four
database objects.  The object's destructor is called when the
application exits.

I do not create new connections to the database while the executing.

Please note that my solution is NOT appropriate if I wanted to create
arbitrary threads at arbitrary times.  If I were doing that, then each
thread would create it's own database object on it's own TLS (thread
local storage) or stack.  I created all of my database "Open()" code
into the main thread just to keep it all together.

Each of my threads does a very specific function that is totally unique
to that thread:

   1. The main thread uses it's database connection to respond to user
      initiated GUI events.
   2. The main thread also uses the "timer" database connection to
      handle WM_TIMER messages to update a status display synchronously
      (kinda).  Because this function can be invoked while the thread
      has a transaction on the main connection, I need to use a
      different connection.  One thread, but it must be fully re-entrant.
   3. Thread #2 is a producer.  It gathers data and inserts it into the
      database.
   4. Thread #3 is a consumer.  It takes data from the database and does
      stuff with them.  It updates those rows.

The timer connection only executes "select" to update the GUI.  The main
connection is used to query the database, update the database and to
delete from the database.

The application is what it is.  I make no public claims about it being
the best designed thing ever, but it does work well under stress.

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Alex Chudnovsky
In reply to this post by D. Richard Hipp
D. Richard Hipp wrote:

>Actually, this seems like a good opportunity to repeat my
>oft-ignored advice to not use more than one thread in a single
>address space.  If you need multiple threads, create multiple
>processes.  
>
I think its not really an acceptable option for those who are on Windows :(

best regards,

Alex
Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Andrew Piskorski
In reply to this post by Cariotoglou Mike
On Fri, Jul 15, 2005 at 04:21:05PM +0300, Cariotoglou Mike wrote:

> memory and cpu-wise. on Linux, this is nothing, it can handle it easily.
> otoh, 500 threads for windows is business as usual, but threading on
> Linux, is , I hear, iffy at best.

Linux runs multi-threaded apps (e.g., AOLserver) quite well, and has
for many years - since at least 2000 or so, probably earlier.  My
understanding is that the old LinuxThreads implementation had some
pretty ugly bits, but it worked.  NPTL is much better, and is standard
with the Linux 2.6.x kernels.

--
Andrew Piskorski <[hidden email]>
http://www.piskorski.com/
Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Paul G-3

----- Original Message -----
From: "Andrew Piskorski" <[hidden email]>
To: <[hidden email]>
Sent: Friday, July 15, 2005 1:05 PM
Subject: Re: [sqlite] Multi-threading.


> On Fri, Jul 15, 2005 at 04:21:05PM +0300, Cariotoglou Mike wrote:
>
> > memory and cpu-wise. on Linux, this is nothing, it can handle it easily.
> > otoh, 500 threads for windows is business as usual, but threading on
> > Linux, is , I hear, iffy at best.
>
> Linux runs multi-threaded apps (e.g., AOLserver) quite well, and has
> for many years - since at least 2000 or so, probably earlier.  My
> understanding is that the old LinuxThreads implementation had some
> pretty ugly bits, but it worked.  NPTL is much better, and is standard
> with the Linux 2.6.x kernels.

the issue wasn't necessarily the thread implementation per se, but the fact
that threads were treated as processes for scheduling purposes and hence
scheduled with the regular process scheduler, which was not efficient for a
large number of processes. these problems went away when ingo molnar's O(1)
scheduler was adopted (not sure when it was merged into linus' 2.4, but
distros adopted it quite fast).

-p

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Dennis Jenkins
In reply to this post by Andrew Piskorski
Andrew Piskorski wrote:

>On Fri, Jul 15, 2005 at 04:21:05PM +0300, Cariotoglou Mike wrote:
>
>  
>
>>memory and cpu-wise. on Linux, this is nothing, it can handle it easily.
>>otoh, 500 threads for windows is business as usual, but threading on
>>Linux, is , I hear, iffy at best.
>>    
>>
>
>Linux runs multi-threaded apps (e.g., AOLserver) quite well, and has
>for many years - since at least 2000 or so, probably earlier.  My
>understanding is that the old LinuxThreads implementation had some
>pretty ugly bits, but it worked.  NPTL is much better, and is standard
>with the Linux 2.6.x kernels.
>
>  
>
Some architectures permit, or even encourage, multi-threaded design.  It
can be done obviously.

However, Dr. Hipp still has a point.  One thread can trash another's
address space.  They share code, global data, the heap (generally) and
system object handles (files, sockets, IPC devices ( and weird crap like
"Desktop" and "Mutants" on windows).  The only non-shared things are the
stack, TLS (thread local storage) and per-thread  CPU context.  Even
then all of those things can be trashed by other threads in the same
process.  Unless you can _prove_ that your code won't do this (and all
code that you call, including system DLLs / SOs) then you are taking a risk.

Personally, I prefer multi-threaded code.  I like to write it and I like
to debug it.  I ship it to customers.  Your millage may vary.

And yes, Linux threads used to be very unstable.  I've only used Linux
threads once, and it was on a recent 2.6 kernel, so I never experienced
the problem(s).

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Craig Morrison-2
In reply to this post by D. Richard Hipp
D. Richard Hipp wrote:

> On Fri, 2005-07-15 at 16:41 +0530, Roushan Ali wrote:
>
>>Hello all,
>>          Can we use single sqlite_open handle(global) across threads(
>>if all database operations are serialized by using semaphore) ? Please
>>help.
>>          
>
>
> Opening a database connection in one thread and using it in another
> will work on some operating systems but not on others.  You are
> advised not to do it.  See http://www.sqlite.org/cvstrac/tktview?tn=1272
> and http://www.sqlite.org/cvstrac/chngview?cn=2521.

Good sound advice, to a point.

Multiple threads accessing the same connection *can* be done, its a
design time issue that needs to be addressed before even a single line
of code is written.

I do it with my mail server using SQLite for logging purposes, I use
mutex semaphores to handle the nitty gritty details.

Its the usual issue of knowing what you are stepping into before you
step, because some of what you step into stinks.

--
Craig Morrison
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
http://www.mtsprofessional.com/
   A Win32 email server that works for You.
Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Andrew Piskorski
In reply to this post by Paul G-3
On Fri, Jul 15, 2005 at 01:04:50PM -0400, Paul G wrote:

> the issue wasn't necessarily the thread implementation per se, but the fact
> that threads were treated as processes for scheduling purposes and hence
> scheduled with the regular process scheduler, which was not efficient for a
> large number of processes. these problems went away when ingo molnar's O(1)
> scheduler was adopted (not sure when it was merged into linus' 2.4, but

Interesting.  Then that may explain why I never heard any first hand
reports of notable Linux threading problems.  The people I tended to
talk to were probably all running with well under 100 threads per
process, and only 2 or 3 such processes at most.  Presumably even the
earlier lousy process scheduler could handle that ok.

--
Andrew Piskorski <[hidden email]>
http://www.piskorski.com/
Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Paul G-3

----- Original Message -----
From: "Andrew Piskorski" <[hidden email]>
To: <[hidden email]>
Sent: Friday, July 15, 2005 1:27 PM
Subject: Re: [sqlite] Multi-threading.


> On Fri, Jul 15, 2005 at 01:04:50PM -0400, Paul G wrote:
>
> > the issue wasn't necessarily the thread implementation per se, but the
fact
> > that threads were treated as processes for scheduling purposes and hence
> > scheduled with the regular process scheduler, which was not efficient
for a
> > large number of processes. these problems went away when ingo molnar's
O(1)
> > scheduler was adopted (not sure when it was merged into linus' 2.4, but
>
> Interesting.  Then that may explain why I never heard any first hand
> reports of notable Linux threading problems.  The people I tended to
> talk to were probably all running with well under 100 threads per
> process, and only 2 or 3 such processes at most.  Presumably even the
> earlier lousy process scheduler could handle that ok.

all depends on what these threads were doing and the activation pattern - a
bunch of compute intensive, fixed work slice threads in a constant pool are
a completely different animal to, say, threads handling network and disk i/o
with variable workload in dynamically growing/shrinking thread pools.

another notable issue was the so-called 'thundering herd' problem -
processes (traditional or threads)  waiting on an event being *all* woken up
when the event comes in. this would happen on accept(), for example, and the
scheduler would thrash. windows had an elegant solution for this (since at
least nt5) in completion ports. linux 2.6 has epoll, which has been
backported to 2.4 and available in distro kernels at least for quite some
time.

we're getting a bit too off-topic here. in short, multi-threading and event
driven models are equivalent (this has been demonstrated formally) for ideal
implementations of both. the trouble is, if w're talking c, that while there
are many good event driven model implementations, threads invariably suck.
they are more intuitive from a comprehension standpoint, but the devil is in
the details, namely concurrency/locking issues. for bonus points, use both
at the same time and watch your brain (and debugger) melt. practically
speaking, threads are non-trivial to do right in non-trivial applications
without higher-level primitives, cf. erlang and various actor-based
languages.

richard's advice is solid. use async io/event loops if possible, separate
processes if possible, threads as a last resort, in that order. the grey
area is the 'if possible' test, since it's a multi-way tradeoff between
performance, simplicity and provable (to an extent) correctness. i fully
expect that a lot of folks *do* need to use threads and the probability of
that being the case on windows is much higher than on posixish platforms.

-p

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Kervin L. Pierre
Paul G wrote:
>
> richard's advice is solid. use async io/event loops if possible, separate
> processes if possible, threads as a last resort, in that order. the grey
> area is the 'if possible' test, since it's a multi-way tradeoff between
> performance, simplicity and provable (to an extent) correctness. i fully
> expect that a lot of folks *do* need to use threads and the probability of
> that being the case on windows is much higher than on posixish platforms.
>

I agree with you, but it doesn't seem like
you're exactly concurring with what DRH
said though.

I'm guessing that that 'if possible' test
is huge, and very frequently will fail.

Why suffer the context switch when you don't
have to?  Would you write a non-trivial GUI
program today without using threads?  Why
subject the users to the added latency IPC
is going to introduce?

The funny thing is eventually multi-process
apps go to MMap for IPC, for performance, and
then run into a lot of the same issues they'd
have to deal with if they were threaded.

And as far as the 'threads introduce
difficult to debug' errors; Isn't that the
age-old performance versus complexity trade-
off?

Processes are easier to use, but very often
perform worse under the same conditions as
the more complex threaded application.  That
is a fact many of us can not look past easily.

PS. It's funny, this discussion seems like its
been taked right from a early '90s newsgroup :)

Regards,
Kervin





Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Paul G-3

----- Original Message -----
From: "Kervin L. Pierre" <[hidden email]>
To: <[hidden email]>
Sent: Saturday, July 16, 2005 9:31 AM
Subject: Re: [sqlite] Multi-threading.


> Paul G wrote:
> >
> > richard's advice is solid. use async io/event loops if possible,
separate
> > processes if possible, threads as a last resort, in that order. the grey
> > area is the 'if possible' test, since it's a multi-way tradeoff between
> > performance, simplicity and provable (to an extent) correctness. i fully
> > expect that a lot of folks *do* need to use threads and the probability
of
> > that being the case on windows is much higher than on posixish
platforms.
> >
>
> I agree with you, but it doesn't seem like
> you're exactly concurring with what DRH
> said though.

right, i'm not concurring with *everything* he wrote. eg. structured
programming wasn't meant to reduce buggage directly, but rather to improve
maintainability of code (which has the indirect effect of reducing buggage).
however, his main point that arbitrary use of a shared address space with
concurrent access is a bit like drinking and skydiving (ie a bad idea which
you come to regret very fast but never get the chance to regret for very
long ;) is indeed very cogent.

the key is understanding that nothing is ever black and white. the more
restrictions you place on usage of shared data structures, the less
concurrency-related issues you are going to have, but take it far enough and
you've got the equivalent of ipc api-wise.

> I'm guessing that that 'if possible' test
> is huge, and very frequently will fail.

right. event loops are great for i/o heavy apps, but you will still need to
farm compute heavy units of work to a thread pool (this is a very common
pattern), not to mention the fact that a lot of external dependencies (ie db
client libs) do not provide an async api. separate processes are fine for a
certain range of tasks, but as soon as you need to move a lot of data back
and forth or spawn a lot of them, your performance tanks. threads have
neither of the above issues, but you then need to figure out why the thing
crashes when jupiter is in saggitarius and the moon is full (hint: many
threadsafe libs aren't, pain invariably ensues ;).

when you're making the call on which way to go, you invariably consider all
the tradeoffs and go with the least worst of your options given your
constraints (which model fits the largest part of the app best, things you
need to interface with, capabilities of your team, deadlines, whether you're
going to still be there to take the flogging when the fit hits the shan
etc).

> Why suffer the context switch when you don't
> have to?  Would you write a non-trivial GUI
> program today without using threads?  Why
> subject the users to the added latency IPC
> is going to introduce?

if the language i'm writing it in has a good async io framework, the app is
not compute bound and the windowing toolkit supports it, most definitely.
consider the fact that the gui handling is (in most modern windowing
toolkits) an event loop and compute heavy tasks are farmed off to a thread
pool and you'll start to see the big picture.

> The funny thing is eventually multi-process
> apps go to MMap for IPC, for performance, and
> then run into a lot of the same issues they'd
> have to deal with if they were threaded.

performance must suck enough for this to happen; this is not always the
case. beyond that, there is a big difference between taking a shared address
space for granted and being forced to think about access to shared data
structures from a psychological point of view. i must confess, however, that
i usually oscillate between the pure event loop, event loop + task queue +
thread pool and pure multithreading for the things i write (no separate
processes included here, with the hybrid model being the most common by
far), but that is down to the things i usually need to do and the fact that
i generally trust myself to do a decent job of fencing my shared data access
given the relative rigidity of the task queue + thread pool pattern.

> And as far as the 'threads introduce
> difficult to debug' errors; Isn't that the
> age-old performance versus complexity trade-
> off?

not necessarily. i routinely see multithreaded applications which would have
a simpler and more performant event loop implementation. this is a bit of a
contradiction given my previous statement that the two are isomorphic, but
in the real world mt apps are often suboptimally implemented due to the
complexity of an optimal implementation. iow, given locking which is fine
grained enough, the overhead of locking shouldn't differ significantly from
the overhead of the event loop, but locking which is fine grained enough is
too tough and you see lock contention (very hard to debug) and
inefficiencies elsewhere because the deadline has come and passed while
everyone was debugging elusive random data corruption/memory
leak/what-have-you somewhere. i'm sure you've seen apps which are so complex
by the time they're feature complete that noone dares to muck with it to
optimize it.

> Processes are easier to use, but very often
> perform worse under the same conditions as
> the more complex threaded application.  That
> is a fact many of us can not look past easily.

agreed, for certain types of work this is the case. all about tradeoffs
really - do you want an internittently crashing fast app or a solid slouchy
app? sometimes you just want something that works, as soon as possible. at
other times, certain performance levels are a hard requirement and you just
have to make sure you write your mt code right, debug it till it's fixed or
die trying ;) yet in another situation (mtas are a good example), you just
dont need to do that much ipc for the performance hit to be anything but
negligible.

> PS. It's funny, this discussion seems like its
> been taked right from a early '90s newsgroup :)

ahh, i was busy coding in asm back then ;) being serious again for a moment,
i don't feel rehashing this over and over is particularly valuable -
everyone's point of view is likely to be derived from their experience and
trying to agree on an objective view of parallel realities has never seemed
like a worthwhile endeavour to me. personally, i'm just happy i've got tools
which let me forget about all this complexity most of the time these days -
hlls are now practical for the majority of things i need to do, thanks to
mr. moore ;)

-p

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Ben Clewett
In reply to this post by D. Richard Hipp
Dr Hipp,

I am just playing devils advocate here because I have completed much
Java programming in a multi-threaded application. :)

I understand the problems of multi-threading.  I am reminded that it
took nearly 20 years of development to get multi-processor support in a
modern OS stable.  Much success for this can be attributed to Semaphore
Flags.  With CPU hardware support to ensure that the semaphore it's self
cannot be controlled by more than one process.

Multi-thread applications suffer the same problems.  Without semaphore
flags or 20 years of development.  A novice programmer can happily
create a second thread and quickly create terribly applications.

However the need for multi-threads is compelling.  Especially in a GUI
environment.  For instance a Mail reader.  Where one thread is needed to
ensure the GUI is drawn correctly and respond to GUI events.  Another to
download and dispatch mail.  (My Thunderbird has 10 threads.  This may
be a bit of overkill :)

As another user also mentioned, a Windows system works better with few
processes with many threads.

I believe the issue is not whether to use threads, but to use them
correctly.  Which is not a hard thing to do with a little support.

This is where Java (and .NET) work well.  If you use them correctly.
They provide thread-safe objects.  Which have been designed to use
semaphore flags internally.  If the programmer uses these thread-safe
objects correctly, they will not encounter thread issues.  For instance,
all communication between threads should be exclusively through these
thread-safe objects.

Further, Java and .NET provide Sycronisation methods.  The defining of a
method to be synchronised automatically creates the locks to ensure
thread safe access.

I am also interested in your comments on Pointers and GoTo.  I note that
Java is 100% pointers.  Apart from basic types, all object access is by
pointer.

Using Exceptions correctly, I have never felt the need for a GoTo.
Exceptions do the same as GoTo, accept, maybe, in a slightly more
developed and useful way.

These are just my opinions :)

Regards,

Ben Clewett.

D. Richard Hipp wrote:

> On Fri, 2005-07-15 at 16:41 +0530, Roushan Ali wrote:
>
>>Hello all,
>>          Can we use single sqlite_open handle(global) across threads(
>>if all database operations are serialized by using semaphore) ? Please
>>help.
>>          
>
>
> Opening a database connection in one thread and using it in another
> will work on some operating systems but not on others.  You are
> advised not to do it.  See http://www.sqlite.org/cvstrac/tktview?tn=1272
> and http://www.sqlite.org/cvstrac/chngview?cn=2521.
>
> Actually, this seems like a good opportunity to repeat my
> oft-ignored advice to not use more than one thread in a single
> address space.  If you need multiple threads, create multiple
> processes.  This has nothing to do with SQLite = it is just
> good programming advice.  I have worked on countless multi-
> threaded programs over the years, and I have yet to see a
> single one that didn't contain subtle, hard to reproduce,
> and very hard to troubleshoot bugs related to threading issues.
>
> I am constantly amazed at the prevailing idea (exemplified
> by Java) that software should be strongly typed and should
> not use goto statement or pointers - all in the name of
> reducing bugs - but that it is OK to use multiple threads
> within the same address space.  Strong typing helps prevent
> only bugs that are trivially easy to locate and fix.  The
> use of goto statements and pointers likewise results in
> deterministic problems that are easy to test for and
> relatively easy to track down and correct.  But threading
> bugs tend to manifest themselves as timing-dependent
> glitches and lock-ups that are hardware and platform
> dependent, that never happen the same way twice, and that
> only appear for customers after deployment and never in a
> testing environment.

Reply | Threaded
Open this post in threaded view
|

Re: Multi-threading.

Mrs. Brisby
On Wed, 2005-07-20 at 17:26 +0100, Ben Clewett wrote:

> Dr Hipp,
>
> I am just playing devils advocate here because I have completed much
> Java programming in a multi-threaded application. :)
>
> I understand the problems of multi-threading.  I am reminded that it
> took nearly 20 years of development to get multi-processor support in a
> modern OS stable.  Much success for this can be attributed to Semaphore
> Flags.  With CPU hardware support to ensure that the semaphore it's self
> cannot be controlled by more than one process.

ITC in 1970 supported multiple threads trivially.

> Multi-thread applications suffer the same problems.  Without semaphore
> flags or 20 years of development.  A novice programmer can happily
> create a second thread and quickly create terribly applications.

....

> However the need for multi-threads is compelling.  Especially in a GUI
> environment.  For instance a Mail reader.  Where one thread is needed to
> ensure the GUI is drawn correctly and respond to GUI events.  Another to
> download and dispatch mail.  (My Thunderbird has 10 threads.  This may
> be a bit of overkill :)

No. Threads are not a need. They allow you to use blocking system calls
in parallel without extra page table loads.

History has demonstrated that programmers building multithreaded
applications tend to produce buggier code, and code that touches more
pages than a non-threaded version. As a result, the non-threaded version
is easier to write, safer, and runs faster.


> As another user also mentioned, a Windows system works better with few
> processes with many threads.

Windows uses threads because x86 page tables are expensive to load. It
doesn't help: the system-call method Windows uses eats any benefit that
it has, again producing net-zero.

> I believe the issue is not whether to use threads, but to use them
> correctly.  Which is not a hard thing to do with a little support.

....

> This is where Java (and .NET) work well.  If you use them correctly.
> They provide thread-safe objects.  Which have been designed to use
> semaphore flags internally.  If the programmer uses these thread-safe
> objects correctly, they will not encounter thread issues.  For instance,
> all communication between threads should be exclusively through these
> thread-safe objects.

Java uses threads poorly. They're expensive to set up, and many Java
programmers yield to non-blocking methods as Java closures tend to be
easier to program, and faster too.

> Further, Java and .NET provide Sycronisation methods.  The defining of a
> method to be synchronised automatically creates the locks to ensure
> thread safe access.

...

> I am also interested in your comments on Pointers and GoTo.  I note that
> Java is 100% pointers.  Apart from basic types, all object access is by
> pointer.

Java uses references, not pointers.

> Using Exceptions correctly, I have never felt the need for a GoTo.
> Exceptions do the same as GoTo, accept, maybe, in a slightly more
> developed and useful way.

Exceptions are slower than goto. They are also less straightforward when
deeply nested (long chains of throws XYZ come to mind...)

> These are just my opinions :)

They are wrong.

123