fast reliable IPC

A

alexia

Hello all,

I need to write loggerReader which receives strings from embedded
device using UDP socket.
The embedded device sends og strings which should be written to a file
and printed on textbox.
The device can send log strings in bursts.

This requiers my logger to be very fast.

The logger has the following design:

1. UDP thread which receives the log strings from the device.
2. worker thread which get the log strings from the UDP thread, write
to the file and print them on the text box.

The mechanism I used for the IPC is socket. The problem is that I saw
that using socket as IPC is not good since some log strings aren't
written to the file (socket is not fast enough ?).

I tried to use the .NET PipeQ object. The problem is that I need to
install this on the PC.

Are there any other async methods that are fast enough?

Thank you for your help.
 
A

Alberto Poblacion

alexia said:
The mechanism I used for the IPC is socket. The problem is that I saw
that using socket as IPC is not good since some log strings aren't
written to the file (socket is not fast enough ?).

The socket should be fast enough. You can use sockets to copy files over
the network, and you will easily achieve transfer speeds of several
megabytes per second.

Your trouble looks more likely to be due to a synchronization problem
between your threads. Are you using a queue between the threads? It probably
needs to be locked while an item is being inserted into the queue and also
another lock while an item is being extracted.
Are there any other async methods that are fast enough?

You could also use Microsoft Message Queuing (MSMQ). It is included
with Windows, although not installed by default. Should be quite fast if
properly used.
 
A

alexia

     Your trouble looks more likely to be due to a synchronization problem
between your threads. Are you using a queue between the threads? It probably
needs to be locked while an item is being inserted into the queue and also
another lock while an item is being extracted.


     You could also use Microsoft Message Queuing (MSMQ). It is included
with Windows, although not installed by default. Should be quite fast if
properly used.

Hello Alberto,

Thanks for the reply.
The socket should be fast enough. You can use sockets to copy files over
the network, and you will easily achieve transfer speeds of several
megabytes per second.

Maybe sockets are not fast enough to transfer data? mayve the device
sends data faster than the socket in the thread transfer the data?
Your trouble looks more likely to be due to a synchronization problem
between your threads. Are you using a queue between the threads? It probably
needs to be locked while an item is being inserted into the queue and also
another lock while an item is being extracted.

I want the mechanism to be Async since the mechanism between the
logger and the device is Async. If the mechanism between the threads
will be Sync than I will most probably loose logs sent from the
device.
I am not using queue between the threads. I use socket to transfer the
logs between the threads. locking is not good since it will set the
mechanism to Sync which is slower than Async.
You could also use Microsoft Message Queuing (MSMQ). It is included
with Windows, although not installed by default. Should be quite fast if
properly used.

I though using the MSMQ. The problem with MSMQ is that I will have to
install this componnent on every PC I install the logger. By default
it is not installed.

I was thinking about cyclic buffer but the development of that
mechanism will take long time.
 
A

Alberto Poblacion

alexia said:
I want the mechanism to be Async since the mechanism between the
logger and the device is Async. If the mechanism between the threads
will be Sync than I will most probably loose logs sent from the
device.
I am not using queue between the threads. I use socket to transfer the
logs between the threads. locking is not good since it will set the
mechanism to Sync which is slower than Async.


No, the queue would not make it Sync. You only place a lock during the
extremely brief period of time needed to perform the insertion into the
queue. You then remove the lock. Your message is kept inside the queue until
the other thread wants to remove it, possibly several microseconds later. In
fact, several messages could be inserted into the queue in this way (in case
there is a burst from the device) before the other thread retrieves any
message from the queue. This second thread would then place a lock on the
queue for an extremely brief period, while the message is being extracted,
and then the lock is removed. The thread then proceeds to process the
message and write it to disk; while this hapens, there are no locks in
place, so the first thread can be inserting messages into the queue while
this process is taking place. Therefore, the queue decouples bouth threads
and lets one of them proceed independently of the other.
 
P

Peter Duniho

Maybe sockets are not fast enough to transfer data? mayve the device
sends data faster than the socket in the thread transfer the data?

Where are you using sockets?

Your question is a bit confusing. You say you're implementing "IPC". But
I don't see more than one process described in your post. According to
your first post, you've got a single process that receives data from your
"device" as well as logs that data to a file.

As Alberto says, sockets should be plenty fast. After all, the data
that's coming in is (apparently, according to your first post) arriving
via a socket (UDP). Any other socket handling in your process should
easily be able to keep up with that.

One thing to keep in mind is that if the device is using UDP to transmit
the data, that's a point of possible failure right there. UDP is
"unreliable". There are a number of useful guarantees it does _not_ make,
including a guarantee of simply delivering a datagram that was sent. If
the device transmits data faster than the receiving computer can process
it, you'll lose datagrams (by "faster" I mean not even considering your
own program...there may be network congestion, CPU contention on the
computer, etc. none of which are under your control to any great degree,
and any of which could cause UDP datagrams to simply be discarded by the
underlying network implementation).
[...]
I am not using queue between the threads. I use socket to transfer the
logs between the threads. locking is not good since it will set the
mechanism to Sync which is slower than Async.

This makes it sound to me as though you're not asking about IPC at all.
Instead, perhaps you are asking about inter-thread communication? If so,
then no...there's really no reason to use sockets. Assuming you use them
correctly, they should still work fine. But within a given process
there's almost never any reason to use network i/o for communication.

Instead, just use a regular producer/consumer queue as Alberto suggests.
The idea that synchronization may slow you down is wrong in a variety of
ways, not the least of which being that sockets internally imply
synchronization (they are thread-safe objects), and so there's no possible
way that, within a process, a socket will out-perform a correctly-written
producer/consumer queue.

If you write the consumer so that it only locks the queue when removing
items, the producer so that it only locks the queue when adding items, and
both so that they perform as much work as possible once they have the lock
-- that is, the consumer removes _all_ available items from the queue, and
the producer adds _all_ available items to the queue -- performance should
be completely acceptable.

Finally note that it's impossible to say for sure what problem you're
having until you post a concise-but-complete code example that reliably
demonstrates the problem. So far, you've only discussed your issue in
generalities, and so the best anyone can do is answer in generalities.
Generalities which may or may not actually apply to your actual question.
:(

Pete
 
E

Eran

hi guys,

Thanks for your help. I was wrong about IPC. I was talking about inter-
thread comm.
As for the problem, it was fix. Using sockets for inter-thread comm is
fast enough.
The problem was that the last log message wasn't written to the file.
I use StreamWriter object to write the log message to the file.
Setting AutoFlash = true now print the last message to the file.
It seems that StreamWriter.WriteLine writes the current line to the
file only if AutoFlash = true.
When AutoFlash wasn't set to true it didn't write the curr log message
but written the prev message to the file.

If you still want, I can supply the sample code.

Again, thank you for the help guys.
 
A

alexia

hi guys,

Thanks for your help. I was wrong about IPC. I was talking about
inter-
thread comm.
As for the problem, it was fix. Using sockets for inter-thread comm
is
fast enough.
The problem was that the last log message wasn't written to the file.
I use StreamWriter object to write the log message to the file.
Setting AutoFlash = true now print the last message to the file.
It seems that StreamWriter.WriteLine writes the current line to the
file only if AutoFlash = true.
When AutoFlash wasn't set to true it didn't write the curr log
message
but written the prev message to the file.


If you still want, I can supply the sample code.


Again, thank you for the help guys.
 
P

Peter Duniho

hi guys,

Thanks for your help. I was wrong about IPC. I was talking about
inter-
thread comm.
As for the problem, it was fix. Using sockets for inter-thread comm is
fast enough.

Okay. But even so, it's a pretty heavy-weight way to communicate between
threads in the same process. Even though it's working, you may want to
rethink that part of the design, using a producer/consumer queue as
Alberto originally suggested.
The problem was that the last log message wasn't written to the file.
I use StreamWriter object to write the log message to the file.
Setting AutoFlash = true now print the last message to the file.
It seems that StreamWriter.WriteLine writes the current line to the
file only if AutoFlash = true.

WriteLine() writes to the stream immediately. But it goes through layers
of buffering...it's not writing directly to the file. Without flushing
the buffers, yes...it's definitely possible to lose data at the end of the
file.
When AutoFlash wasn't set to true it didn't write the curr log message
but written the prev message to the file.

A better solution is probably to simply make sure you call Close() or
Dispose() on the StreamWriter object when you're done with it, to
guarantee that all data has been flushed, including anything pending in
the encoder. Note that the AutoFlush property (not "AutoFlash" :) ) only
flushes data from the stream's buffer; encoder data is still not
necessarily flushed, and so you could still wind up with truncated output
(the docs say this is of particular concern if you're using UTF-8 or UTF-7
encoding).

Glad to hear you got things sorted out.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top