From: Peter Olcott on

"Ersek, Laszlo" <lacos(a)caesar.elte.hu> wrote in message
news:Pine.LNX.4.64.1004020234430.11352(a)login01.caesar.elte.hu...
> On Thu, 1 Apr 2010, Peter Olcott wrote:
>
>> I don't see how this does not guarantee all of the
>> atomicity that I need. Could you propose a concrete
>> example that meets the standard and causes problems? It
>> seems like it is saying the entire append must complete
>> before any other file modifications take place.
>
> write() itself (with or without O_APPEND) is not required
> to write all bytes at once, even to a regular file.
>
> http://www.opengroup.org/onlinepubs/9699919799/functions/write.html
>
> Consider a signal delivered to the thread, a file size
> limit reached, or being temporarily out of space on the fs
> hosting the file; all after some but not all bytes were
> written. (These would return -1 and set errno to EINTR
> (without SA_RESTART), EFBIG, ENOSPC, respectively, if no
> data could have been written before encountering the
> condition in question.) This list is not exhaustive.
>
> (Signal delivery is plausible -- suppose you submit a
> write request of 1G bytes on a system with little buffer
> cache and a slow disk. If SSIZE_MAX equals LONG_MAX, for
> example, the result of such a request is not even
> implementation-defined.)

I want to somehow define this process for maximum
reliability. Each request will be a customer's purchase, I
don't want to lose any requests. The reason that I defined
the log file as part of this process was to make these
customer requests persistent. The purpose of the named pipe
was to provide event driven notification to each process.

>
>
>
> ----v----
>
> Write requests to a pipe or FIFO shall be handled in the
> same way as a regular file with the following exceptions:
>
> [...]
>
> * Write requests of {PIPE_BUF} bytes or less shall not be
> interleaved with data from other processes doing writes on
> the same pipe. [...]
>
> * If the O_NONBLOCK flag is clear, a write request may
> cause the thread to block, but on normal completion it
> shall return nbyte.
>
> [...]
>
> ----^----
>
> Both quoted guarantees (exclusion of interleaved writes,
> plus completeness of writes) are exceptional behavior of
> pipes in relation to regular files.
>
> Perhaps an interpretation request should be submitted: if
> write() returns nbyte and O_APPEND was set, was the block
> written atomically then?
>
> <http://www.kernel.org/doc/man-pages/online/pages/man2/write.2.html>
> does say
>
> ----v----
>
> If the file was open(2)ed with O_APPEND, the file offset
> is first set to the end of the file before writing. The
> adjustment of the file offset and the write operation are
> performed as an atomic step.
>
> ----^----
>
> which seems to imply that the write operation itself is
> atomic. (... if it returns "count", in my interpretation.)
>
> lacos

Great thanks.


From: Vitus Jensen on
Hi David,

On Thu, 1 Apr 2010, David Schwartz wrote:

> On Apr 1, 4:23 pm, "Peter Olcott" <NoS...(a)OCR4Screen.com> wrote:

....

> Seems kind of silly to have a thread for each request that spends most
> of its time just waiting for another program. You don't need a thread
> to wait. Just assign a thread to do what needs to be done when you're
> notified that the request is finished being processed by the OCR
> software.

I'm coming from another platform where the maxime was "a thread should do
nothing very well" (PF), which I always interpreted as to code your thread
so that they spend most of their time waiting. So yes, you need a thread
to wait. 99% of the time it should do nothing else but wait.

> I'm saying, don't have one thread waiting to do X when X is possible
> and one waiting to do Y when Y is possible and so on. First, this
> wastes a lot of threads. Second, it forces a lot of context switches
> to get the "right thread for the job" running.

Are threads a sparse resource in linux? I thought the limit for a typical
system is well above 1000.

And if a thread is waiting for data appearing on a filehandle how could it
create context switches? It's just lying there, the only thing it's
occupying is address space and some kernel memory.

Now if all those threads will be crunching data this would be another
case. To avoid overload just increase/decrease a counter and wait (!) if
it's getting too high.

> Instead, have one thread that waits until anything is possible. When
> something is possible, it wakes another thread to wait for the next
> thing to be possible and it does X, Y, Z, or whatever it was just told
> is now possible to do.

In this case you need code to decide what to do when woken up in your
application. A switch and a call to the corresponding worker routine,
passing matching context data via stack to that routine.

> This results in far fewer context switches and better utilization of
> CPU code and data caches. (Of course, if the web part is an
> insignificant fraction of resource usage, it might not matter.)

This doesn't result in more context switches (see above) but in more
application code which puts a heavier load on code and data caches.

If you start those worker routines as threads, the decision making about
what worker to run is moved into the kernel which is highly optimised for
that kind of work. Additionally your worker threads keep their context
data local and may hide that data structure from other threads/modules
which give a much cleaner, simpler and safer design.

Give threads a chance, they are there for a reason.

Vitus

--
Vitus Jensen, Hannover, Germany, Earth, Universe (current)
From: Peter Olcott on

"Vitus Jensen" <vitus(a)alter-schwede.de> wrote in message
news:alpine.LNX.2.00.1004021202200.5338(a)asterix.crazy-teaparty.dyndns.org...
> Hi David,
>
> On Thu, 1 Apr 2010, David Schwartz wrote:
>
>> On Apr 1, 4:23 pm, "Peter Olcott" <NoS...(a)OCR4Screen.com>
>> wrote:
>
> ...
>
>> Seems kind of silly to have a thread for each request
>> that spends most
>> of its time just waiting for another program. You don't
>> need a thread
>> to wait. Just assign a thread to do what needs to be done
>> when you're
>> notified that the request is finished being processed by
>> the OCR
>> software.
>
> I'm coming from another platform where the maxime was "a
> thread should do nothing very well" (PF), which I always
> interpreted as to code your thread so that they spend most
> of their time waiting. So yes, you need a thread to wait.
> 99% of the time it should do nothing else but wait.

You probably have that correctly, when I first read it, it
seemed that it was saying that threads can not be relied
upon because they keep screwing things up. I thought that I
might add this little bit of humor.

>
>> I'm saying, don't have one thread waiting to do X when X
>> is possible
>> and one waiting to do Y when Y is possible and so on.
>> First, this
>> wastes a lot of threads. Second, it forces a lot of
>> context switches
>> to get the "right thread for the job" running.
>
> Are threads a sparse resource in linux? I thought the
> limit for a typical system is well above 1000.
>
> And if a thread is waiting for data appearing on a
> filehandle how could it create context switches? It's
> just lying there, the only thing it's occupying is address
> space and some kernel memory.
>
> Now if all those threads will be crunching data this would
> be another case. To avoid overload just increase/decrease
> a counter and wait (!) if it's getting too high.
>
>> Instead, have one thread that waits until anything is
>> possible. When
>> something is possible, it wakes another thread to wait
>> for the next
>> thing to be possible and it does X, Y, Z, or whatever it
>> was just told
>> is now possible to do.
>
> In this case you need code to decide what to do when woken
> up in your application. A switch and a call to the
> corresponding worker routine, passing matching context
> data via stack to that routine.
>
>> This results in far fewer context switches and better
>> utilization of
>> CPU code and data caches. (Of course, if the web part is
>> an
>> insignificant fraction of resource usage, it might not
>> matter.)
>
> This doesn't result in more context switches (see above)
> but in more application code which puts a heavier load on
> code and data caches.
>
> If you start those worker routines as threads, the
> decision making about what worker to run is moved into the
> kernel which is highly optimised for that kind of work.
> Additionally your worker threads keep their context data
> local and may hide that data structure from other
> threads/modules which give a much cleaner, simpler and
> safer design.
>
> Give threads a chance, they are there for a reason.
>
> Vitus
>
> --
> Vitus Jensen, Hannover, Germany, Earth, Universe (current)


From: Ersek, Laszlo on
On Fri, 2 Apr 2010, Vitus Jensen wrote:

> Hi David,

(I'll try to follow up on this, though I'm sure David will offer you much
better answers.)


> On Thu, 1 Apr 2010, David Schwartz wrote:
>
>> On Apr 1, 4:23�pm, "Peter Olcott" <NoS...(a)OCR4Screen.com> wrote:
>
> ...
>
>> Seems kind of silly to have a thread for each request that spends most
>> of its time just waiting for another program. You don't need a thread
>> to wait. Just assign a thread to do what needs to be done when you're
>> notified that the request is finished being processed by the OCR
>> software.
>
> I'm coming from another platform where the maxime was "a thread should
> do nothing very well" (PF), which I always interpreted as to code your
> thread so that they spend most of their time waiting. So yes, you need
> a thread to wait. 99% of the time it should do nothing else but wait.

What's the name of that platform? I don't understand the "PF"
abbreviation. Perhaps you mean "FP" as in functional programming. The
programmer-accessible thread concept in "such languages" tends to be
lightweight ("green threads" or "managed threads"), and the runtime
environment of the language provides a scheduler, implemented in user
space, that multiplexes such green threads over kernel threads (kernel
schedulable entities). This is called the M:N thread model.


>> I'm saying, don't have one thread waiting to do X when X is possible
>> and one waiting to do Y when Y is possible and so on. First, this
>> wastes a lot of threads. Second, it forces a lot of context switches to
>> get the "right thread for the job" running.
>
> Are threads a sparse resource in linux? I thought the limit for a
> typical system is well above 1000.

GNU/Linux switched to a 1:1 thread model not so long ago (at least when
you program in C), AFAICT.

http://people.redhat.com/drepper/glibcthreads.html
http://people.redhat.com/drepper/nptl-design.pdf

Furthermore, IIRC the default stack dedicated to a single thread is 2M (at
least?), so 1000 threads in a 32-bit process would eat up (per default)
the usable address space of the process quite quickly.

So yes, in the 1:1 thread model (which seems to me kind of "proven
optimal" for system programming languages), a thread is a heavy-weight
resource. You implement manually what the user-space green threads
scheduler does for you elsewhere.


> And if a thread is waiting for data appearing on a filehandle how could
> it create context switches? It's just lying there, the only thing it's
> occupying is address space and some kernel memory.

I recommend reading "High-Performance Server Architecture" by Jeff Darcy:
<http://pl.atyp.us/content/tech/servers.html>.


> Now if all those threads will be crunching data this would be another
> case. To avoid overload just increase/decrease a counter and wait (!) if
> it's getting too high.

You create heavy-weight threads not because you want to express the work
to be done differently, ie. in separate logical sections (eg. for I/O
multiplexing), but because you want to scale CPU-intensive work to
multiple cores, or you wish to overlap waiting for IO with CPU-intensive
work and don't want to use AIO or signals for some reason.

The C10K problem, by Dan Kegel: <http://kegel.com/c10k.html>.


>> Instead, have one thread that waits until anything is possible. When
>> something is possible, it wakes another thread to wait for the next
>> thing to be possible and it does X, Y, Z, or whatever it was just told
>> is now possible to do.
>
> In this case you need code to decide what to do when woken up in your
> application. A switch and a call to the corresponding worker routine,
> passing matching context data via stack to that routine.
>
>> This results in far fewer context switches and better utilization of
>> CPU code and data caches. (Of course, if the web part is an
>> insignificant fraction of resource usage, it might not matter.)
>
> This doesn't result in more context switches (see above) but in more
> application code which puts a heavier load on code and data caches.

The user-space scheduler of your runtime environment does exactly what
David tells you to implement manually in C. You don't have to dispatch
yourself based on event types because you register them beforehand with
your user-space scheduler (probably written in C), and it does this X, Y,
Z or whatever for you. X, Y, Z are things (event handlers) you registered
implicitly when you defined your green threads and the resources they wait
for.

"Homogeneous threads" are easier to schedule for the kernel, and they
adapt better to a changing load between different task types. Consider a
pharmacy with five windows. Compare the following two setups:

- you have a single queue of patients, with the patient at the head of the
queue dispatched to whichever window becomes free -- each window (teller?)
handles all kinds of requests,

- you have five queues and patients can't move between queues once they've
chosen one queue, according to their types of requests.

Which one seems to handle better (a) smoother servicing / minimal wait
times / wildly varying individual servicing times, (b) adding more
windows, (c) adding more patients? Your runtime environment may make the
impression of five separate queues (eg. windows by task types), but
internally, it has, say, two real windows (by CPU cores) and it keeps
reassembling your patients into queues corresponding to different
concepts.


> If you start those worker routines as threads, the decision making about
> what worker to run is moved into the kernel which is highly optimised
> for that kind of work.

It surely is, but then the kernel *must* work (the user/kernel boundary
*must* be crossed) for doing nothing more than dispatching (selecting a
worker based on task type). A switch statement is much cheaper.


> Additionally your worker threads keep their context data local and may
> hide that data structure from other threads/modules which give a much
> cleaner, simpler and safer design.

I agree that keeping request-specific (temporary) data on the stack
improves locality, but I believe this should matter little if a request,
once dispatched, requires a massive amount of computation (relative to
ensuring cache coherence etc). And eavy-weight threads appear most
eligible to me when jobs do need intensive crunching. (We're talking OCR,
right?)


> Give threads a chance, they are there for a reason.

Yes, they're there so you can place one independent instruction stream (or
a very low number of them) on each individual core.


.... Please feel free to pick this apart. I kind of sense some gaping holes
in my reasoning, but I intend to prod knowledgeable subscribers into
explaining, so that I can learn. Thanks.

lacos
From: David W Noon on
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Fri, 2 Apr 2010 15:48:13 +0200, Ersek, Laszlo wrote about Re: IPC
based on name pipe FIFO and transaction log file:

>On Fri, 2 Apr 2010, Vitus Jensen wrote:
[snip]
>> I'm coming from another platform where the maxime was "a thread
>> should do nothing very well" (PF),

[snip]
>What's the name of that platform? I don't understand the "PF"
>abbreviation.

Vitus was referring to OS/2, and PF is Peter Fitzsimmons. Peter was a
well known developer on OS/2 some 15 or 20 years ago.
- --
Regards,

Dave [RLU #314465]
=======================================================================
dwnoon(a)spamtrap.ntlworld.com (David W Noon)
Remove spam trap to reply by e-mail.
=======================================================================
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)

iEYEARECAAYFAku1//AACgkQ9MqaUJQw2MnsvgCfcDJeJ9yFcddhdFqN1TgBZ6Ol
VgoAn2aqUChiOHBhv72GGTHWYpXFumMt
=vfkN
-----END PGP SIGNATURE-----
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8
Prev: LBW 0.1: Linux Binaries on Windows
Next: socket