Synchronizing "pushed" multicasts

Yes, you can. And you must.

Which is why you must set up your receiver such that "actual" data rates don't even enter the picture.

It tells you nothing. Reception times are essentially irrelevant. They must be. Only _transmission_ times can be allowed to matter. I.e. the sender must mark its data with timestamps, and receivers _have_ to respect those.

You must have. If you have no idea at all, about the network-induced jitter of data package timing, then synchronized transfer is utterly impossible.

Which is why those are utterly the wrong conditions to be looking for.

The trick is not in what to do when the buffer runs dry, but rather in how to avoid that that ever happens in the first place.

You don't wait until your tank runs dry before you start looking for a gas station. You keep an eye on the needle, and compare estimated remaining mileage (and your trust in that estimate) with the signs saying "last gas station for ... miles". And once it starts to look like a close shave, you may even start to adapt your driving to increase chances.

I.e. a sensible signal for the receivers to report back to the master is the fill percentage of their buffers. That way, as the fill rate of some slaves starts dropping too far, the source may have to sub-sample its signal to reduce the data rate, so the receivers can fill up faster with the same amount of raw data. Similarly, slaves in danger of filling up their buffers can sub-sample their buffer contents to reduce the volume of data while still having the same buffering time.

No. Because that's what mechanism 1) already _is_!

Of course it does. A multicast or broadcast source cannot have every single receiver making their own decisions. The only way that can possibly work if there's only _one_ sheriff in town.

The same thing, for every source.

Reply to
Hans-Bernhard Bröker
Loading thread data ...

See my comments to him...

An elegant way of saying what I would have spent paragraphs hunting for appropriate words :-/

Yes. In my case, the external observer's criteria apply -- since other clients/consumers qualify as "external observers" (whose activities must relate to those of each other *individual* client)

Not sure what you mean by "constant rate transmission". I.e., I don't expect packets to arrive evenly (or even *similarly*!) spaced in time. However, I expect data within those packets to represent equally spaced samples in the audio stream.

Yes, this is how a single client connection could be implemented. But, it means each client has it's own "connection" (in effect... even if a connectionless protocol is used). If N clients are sinking the same data, then the server has to push that data out N times. The server's bandwidth gets eaten up quickly (and the server has to *process* N request streams interactively).

Moving to a multicast/broadcast implementation means each "channel" of data need only be transmitted once for all clients "subscribing" to that channel (assuming they are all roughly synchronized in their intended playback of that material).

More importantly, it means the server isn't spending as much time handling routine requests ("give me the next packet") and can have that real-time available for handling *exceptions* (i.e., when things go badly!)

It still causes extra traffic (on the server's spigot) and requires the server to *react* all the time -- instead of just when something heads south.

Exactly. You end up having to resample *all* input streams since each clock can be operating at a slightly different rate/phase.

[I contend that you need this capability, regardless, but as a *fallback* rather than as a normal mechanism]

Then you have to deal with different notions of time between different servers.

To be clear, the "client's clock" is slaved to a master clock. The "server's clock" is also slaved to that master clock. In theory, the two should be syntonous *and* synchronous (the former even moreso than the latter).

So, the "client's clock" is, conceptually, the same as the server's. And, neither is "authoritative"...

(imagine a client actually being an *agent*... so, it acts as a server to still *other* clients!)

There are actually some network devices that do this "in iron". And, some protocols (NTP, PTP) that do it with varying degrees of hardware assist.

I'm taking the latter approach. Implement a servo that locks a "virtual clock" to some other "virtual clock" (since neither are actual vibrating bits of iron -- or quartz :> ). In a system at steady state, this can give very tight synchronization tolerances (O(1us) or better).

The problem lies in those cases where one or more elements are not currently "settled". Either they were just powered up or some sort of disturbance has whacked their notion of time so it no longer has the desired phase and frequency.

In the case of buffer overrun (underrun is a different matter), you have a buffer full of data that buys you (locally) time to solve this problem. If you can request (it;s not really a re-request since you never requested the datum in the first place) the discarded samples *again*, then you can recover -- at some minor cost in network bandwidth "waste" (since the sample had previously been transmitted, transmitting a second copy of it to you is a loss of resources).

In the *short* term, you can resample data, etc. to compensate for this "problem" (assuming you know *your* clock needs to be tweeked).

But, if you don't do anything about the controls that govern the phase and frequency of your clock and the server's clock, then this problem will repeat. You'll just end up mimicking the "apparent" fluctuations in the server(s)'s clock(s).

What I'm looking for is a mechanism that *fixes* this problem instead of *compensating* for it.

Reply to
Don Y

Hi Hans-Bernhard,

I contend that you don't know you will have a problem until you actually *have* that problem (esp if you can't control the producer).

But transmission times tell you nothing, *either*! Because that assumes your clock is (at least) syntonous with that of the sender. Further, you *want* the sender to be able to deliver data at varying rates instead of forcing it to fit a very periodic framework.

Looking at transmission times, reception times or The New York Times tells you nothing about whether you're going to encounter an overrun or underrun.

Timestamps (packet numbers) in the packets tell the clients when to *play* (i.e., push them out to the D/AC) the samples in the packet. This allows packets to be received out of order. And, also ensures packet X is played concurrently by clients A and B.

All you can tell from these packet numbers is whether or not any "holes" exist in your cached data stream (assuming the producer always generates a continuous data stream).

Theoretically (i.e., if all works right), the "soonest" packet that you have enqueued will be played "now" -- all older data having since been discarded. Likewise, the "futurest" packet that you have enqueued should be at the very end ("top") of your buffer.

The clients need to co-operate with the server to ensure that each is operating at or near this theoretical state.

This is actually a *lot* harder than these discussions have made it sound. E.g., consider the problems posed by a new client coming on-line (e.g., turning on the "rear speakers") and having to synchronize itself with other clients (Hint: think about the current network traffic and the contents -- present and future -- of that new client's buffer! :> )

You don't look at packets. You deal with tracking a timebase and let the jitter in packets "be what it may". How much of that jitter is caused by delays in the fabric itself? How much is caused by delays in the sender's network stack? (i.e., if some

*other* outbound traffic happened to be ahead of this packet as it left the server *this* time but not the *previous* time)

You don't *look* for them. My point is that you can't *predict* them.

You can't avoid a buffer underrun or overrun -- since you can't control the other parts of the system. It's a probabilistic roll of the dice: what are the chances that the sender will not be able to produce another packet before I *need* it, etc.

But you don't have those "last gas station for..." signs to tell you about the future! You *expect* to receive samples at an average rate that corresponds with your consumption rate. You buffer to tolerate jitter in their delivery -- either at the producer or in the fabric (other network traffic, etc.). But there is nothing that tells you the next packet *will* be here in X us. It could end up arriving a bit early, late or not at all.

----------------------------------------------^^^^^^^^^^^^

That was the point of the thread. How do you "close the loop" so that these discrepancies (in clocks) get corrected without losing data.

(3) allows for the production rate to be changed -- (1) doesn't!

And I'm saying there is no sheriff. Rather, there are a cooperating group of *actors* ("deputies"?) that have assigned roles but a shared goal.

Two people are digging a hole for a new planting in the yard. One guy has the shovel, the other guy has the wheelbarrow (to haul the dirt away). Who's the "sheriff"? The guy with the shovel because he's "producing" the dirt (from the hole)? Or, the guy with the wheelbarrow who's hauling it away?

In reality, they work in tandem -- sharing responsibilities.

If the "digger" digs too fast, he runs the risk of dirt piling up on the ground *beside* the hole -- because the hauler was off dumping the previous load. If the digger is too slow, the hauler spends lots of time twiddling his thumbs and they *both* spend more time than necessary out in the hot sun.

Instead, they have to cooperate -- finding a fine balance between digging and hauling so that they achieve their goal (digging the hole in a timely fashion) efficiently.

This *requires* you to resample constantly. I only use that as a remedy when the system is headed over a cliff.

Reply to
Don Y

No. That's not when you know you _will_ have a problem, it's when you know you _do_ have a problem right then.

But unless your buffer is entirely too small, you would have to turn a blind eye on purpose to _not_ notice that the buffer fill level is steadily running low (or high). It's when you notice this trend that you have to start applying countermeasures. If the buffer ever actually runs full (or empty), that means those countermeasures have not been up to the medium's antics.

On the contrary. It's the only thing around allowed to tell you _anything_.

Which it must be, to a useful extent. Which is why the sender must send _timestamps_, not just sequence numbers.

Of course not. That's what looking at the buffer fill level is for.

Timestamps aren't just packet numbers.

Since there was not the slightest mention before of such a situation being part of the picture, that's none too surprising. If you ask only half the question, you won't get the whole answer.

But no, that's no more complicated. That new client will start the same way as any other one: it'll listen to transmissions for a while until its buffer is reasonably full, and its clock sufficiently synched to the master, _before_ it starts playback at the right point.

It doesn't matter at all where that jitter comes from. Only how big it is, overall.

And my point is that you're wrong about that. Buffer fill levels don't just surprisingly jump all the way from "nicely filled" to "overflown" or "empty" --- not unless the buffer is way too small, that is. So you can track their movement, and detect that you're going to run into trouble _before_ actually hitting it.

You're looking way too closely at individual packets. Once you're down to the last packet before buffer-empty, it's indeed too late to react. Which is why you must react _before_ that point. Way before.

And that's where you've been wrong all this time. You can't think of that as a last-minute bail-out.

Reply to
Hans-Bernhard Bröker

I think this may be the crux (oooh, I get 25 cents for using that word!) of the issue (difference in our views).

You need a buffer:

- because samples can't (efficiently) be sent individually

- because the system (fabric + stacks) has variable latency

- because the system can temporarily be overloaded

The buffer "buys you time" to react to "things you notice". E.g., if the ("average") buffer level ever starts to drop, you should be concerned that it might eventually run dry. Perhaps the server has crashed? Or, temporarily been overloaded?

(or, there is a "sudden" difference in producer/consumer clock rates -- you are now consuming faster than producer is producing)

Regardless: "Buffer is a Good Thing"

You want a buffer to be larger (rather than smaller) as it gives you more leeway in the types of situations to which you can adapt.

OTOH, you want to keep the buffer as small as practical:

- minimizes cost

- smaller physical size (SoC -- reduced component count)

- *can* reduce code complexity (but won't)

Overruns are "easier" to recover from (misstatement: "give you more *time* to recover) than underruns (once the buffer runs dry, there is nothing you can do to "hide" the problem -- you're broken!)

As such (all of the above), you want to keep as big a buffer as possible *and* keep it as *full* as possible. I.e., if you knew for a fact that your clocks would always be syntonous, you could size your protocols to keep the buffer at 99.9% utilization.

Regardless, the difference between your current/average utilization and total utilization is your *effective* buffer size (in terms of your overrun calculations). This wants to be small -- because you want to maximize your buffer size for the dreaded underrun case (since that is very unforgiving).

The upper limit on your buffer utilization is dependant on the packet size of your protocol. When you "expect" another packet, you need to be sure you have *room* for that packet.

[In these audio clients, I cheat and blur the bounds between subsystems -- e.g., the network stack and the audio "process". I use zero-copy semantics throughout to save cycles and bytes. So, my buffer is really a list of network frames (not just the "payload" of those frames). So, the above requirement boils down to "When you expect another packet, you need to be sure you have another network buffer available"]

To handle any potential of overrun (i.e., even *one* sample too many in a given period of time) you have to be able to accept one more packet than theoretically needed. If you *use* that buffer, you are *in* overrun.

Since you can always re-request the sample(s) for which this buffer was needed, you can just as easily discard the sample (and the entire packet).

Bottom line: your effective buffer size (for the overrun case) is one packet-size. And, since you can only use a buffer of that size to store a whole packet, one sample over is the same as one *packet-worth* over.

If you set aside any *more* space for the buffer, you're shrinking the effective buffer size for the *underrun* case (i.e., only using a portion of the resources that you have available). And, since "one sample too many" will result in a whole *packet* of that buffer space being consumed, you haven't gained anything from the case I outlined above (i.e., one spare packet of "overflow detection").

A timestamp only makes sense if the client can examine the sender's clock. Sequence numbers represent the same data in a more terse form. I.e., the client knows what the data rate is *supposed* to be so it knows what the time between samples is supposed to be. This is how he determines what his "D/AC clock" should run at (you don't allow samples to be emitted at "random" times!).

So, if there are 100 samples in a packet, the first sample in packet #2 will be emitted 100*sample_period after the first sample of packet #1.

If I track the number of sequential packets in my buffer, I can tell you how long (in terms of clock time) it will be before I run out of data (assuming no more data arrives in that time). And, I can tell you when *each* datum in that set of packets (i.e., the entire buffer's contents) will be emitted.

Telling me that the server generated this packet at XX:XX:XX.XXXXX tells me nothing more. I.e., I can *predict* that the packet that followed it was/will_be generated at XX:XX:XX.XXXXX+100*sample_period.

Sequence numbers are smaller (more efficient in terms of packet space) and can be made smaller *still* (e.g., I plan on using less than a single octet to encode the sequence number... having ~256 outstanding packets at any given time in a particular stream would imply a large buffer in each client (~100K+)

See above. You don't aim for an "average fill level" of ~50% but, rather, something like 95% (or more). In theory, the producer and consumer are operating at the same data rates. The only time data should be coming in *faster* than average is if it had previously been coming in *slower* than average (i.e., the buffer started to run dry because the server was overloaded, etc.)

See above. When a client connects to a server (data stream), it gets told the reference ("absolute system time") time (i.e., time zero) for the stream and the sample rate. Thereafter, the "emit time" for any particular sample can be determined simply by adding "sample number * sample_period" to time_zero. Sample number is: "packet_number * samples_per_packet + sample_within_packet"

But it's buffer will never become "reasonably full"! :>

Every time a packet comes in, it will be busy consuming that packet -- since it is consuming as fast as data is arriving! I.e., the average buffer utilization will be 1/2 of a packet: the buffer is initially empty. A packet arrives every "samples_per_packet * sample_period". In that same time, *exactly* samples_per_packet will be consumed! So, the next packet will, theoretically, arrive just as the last *sample* in the previous packet is consumed (i.e., as the buffer runs dry!).

When a client comes on-line, I precharge that client's buffer (after determining the client's capabilities) with the contents of the packets that have already been captured by the *other* clients (while this client was powered off)

The whole point is that the buffer utilization should remain constant (if clocks are syntonous). So, put whatever you want *into* the bufferS (in the clientS) and utilization should remain at exactly that level -- falling only in periods of overload and then quickly returning to the same utilization level. NEVER INCREASING.

See above. You *expect* a buffer to empty from time to time (overload, etc.). And, you expect it to recover reasonably quickly (depends on the design of the server). But, you never expect a buffer to grow *beyond* this point unless clocks are wonked.

Yes. Emptying is the easy to understand. You use as much buffer as you have available (biggest time cushion). You watch to see how much ripple you expect to encounter in the utilization level. When you see more than you are "comfortable with", you begin invoking remedies: verify that the server is still sending (you can talk to your network stack to get this information), verify that the network is still "up" (can you contact your peers?), etc.

If the system is entering a period of prolonged overload (i.e., something that your buffer isn't likely to span), you can request the server to reduce the sample rate so that each packet gives you "more real time" to span (audibly).

I contend that you can be simpler in your handling of overrun. If you *ever* get more data than you expect, you know something is wrong. The producer knows your capabilities. So, assuming it isn't buggy, if it is sending you more data than you can consume, it must think your clock is running at a different rate than it actually *is*. It's not the same sort of problem as a "temporary system overload" -- it's a "broken".

There always has to be something that you do when all else fails. My point is to leverage the knowledge/observations of other components in the system to prevent that from happening. Using peer knowledge to come to concensus instead of *dictating* behavior.

Reply to
Don Y
[...]

or - because the system can be temporarily underloaded, and it would be a waste _not_ to use that free bandwidth to prepare for when it might be overloaded, later.

It's more than that in this situation. It's an absolute necessity. The only way around data arriving later than usual is to have enough data buffered to survive the pause without running dry.

No. You want to keep it at around the 50% mark. Networks will fluctuate in _both_ directions, so you need to both be able to accept excess data and survive late arrivale.

Not in a broadcast situation you can't, without making the whole problem _worse_ for all other receivers, and wasting bandwidth.

A timestamp _is_ exactly the means to let the receiver do that.

No. They represent less than a timestamp does.

Wouldn't it be nice if it were that easy? Well, it isn't. The problem with that is that the sender and the receivers don't necessarily agree (to the required accuracy) over what sample_period actually is. Clocks _do_ run away from each other.

It _cannot_ start consuming before its buffer has filled up a bit. If for no other reason, then because the first data it sees are _not_ allowed to be played until quite a bit of time later. Remember: those packets are supposed to go to the top of all other receivers' buffers, while they're playing back the bottom end.

That will blow the master's bandwidth requirement right out of the water. If your network had the bandwidth to actually do _that_, you wouldn't have needed multicast/broadcast in the first place.

Well, but are your capabilities the same as every other recipient's? All the time? Do we want to force the producer to play to the weakest recipient's capabilities?

Reply to
Hans-Bernhard Bröker

The network can't create data out of thin air. The producer is generating data *at* the sample_rate. I.e., broadcast/multicast-ing a packet every "sample_rate * samples_per_packet" unit of time. Doing so any faster than this would overfill client buffers.

As I said before, the only time a buffer's contents can increase faster than the sample rate (assuming the buffer has already been precharged) is if it had previously *shrunk* -- because samples got queued up in the network fabric or output stack of the server.

It is possible for a packet to get stuck in a switch in such a way that it only affects one particular client (which can vary over time). But, any packets that get delayed in an output queue will affect all clients -- so *all* of their buffers will start emptying (at exactly the same rate)... and, thereafter, refilling at the same *accelerated* rate.

However, this accelerated rate will only continue until the buffers have reached the level of fullness that they would have had, all along, had the fabric/server not temporarily held onto data (causing the clients to consume buffered data).

In a broadcast/multicast environment, there are many different strategies you can use to ensure reliable delivery to all clients.

E.g., I could require each client to ACK each packet (or some artificial grouping of packets). This generates lots of traffic confirming something that I already *expect* to be true -- that the data *is* reaching all destinations correctly.

Or, I could require *no* feedback from the clients and leave them to their own devices if they discover some data is missing (recall, this is a continuous data stream so a client can *infer* when it has "missed" some portion of it!).

Or, I could *assume* each client has received the data unless told (by that client) otherwise. Again, since it is a stream, a client can deduce that it has missed some data and *request* it -- in a unicast message directed to the server.

Note that all of this feedback can be just as tenuous as the forward channel. The server might not *get* the request, it might get lost in the fabric, etc. So, there is no guarantee that the client gets something just because he asked for it! (client will still have to have some means of handling the "lost data" issue)

Since I am assuming packets don't regularly get dropped, basing the first level recovery protocol on "request missing packets" seems to be least risk/cost.

It also has the advantage of implicitly carrying information to the server *without* necessitating a separate "status message" (i.e., "*I* lost a packet. Did *you* fail to generate it in the timeframe I expected? Have *other* clients complained to you about this problem? Is the fabric getting flakey? Other network traffic increasing to a point where transmissions have become unreliable? Should *you* start changing how you interact with me/us in light of these observations?")

But it only tells the receiver what the server thought it's *own* clock said at that time. Since the delivery of the packet isn't instantaneous *and* exhibits varying latency, it tells the receiver nothing about what the clock is *now* (when it receives or examines the packet).

That's the whole reason I (separately) synchronize all nodes' clocks to the "Grand Master Clock": if I tell you I sent this packet at time X and you receive it at time Y, then you **know** it has been delayed "in the ether" for Y-X time units.

If your clock is not synchronized to mine, then all you know is two arbitrary numbers which have no relationship to each other I.e., you can *say* you sent it at 2:45 and I can notice that I received it at 2:41 (!) even after it drifted in the ether for 0:37 (!!).

[contrast these to the claims I make in the paragraph preceeding]

If my clock is synchronized to yours (i.e., your time X occurs coincident with *my* time X) and I tell you I did something

5 "intervals" after time X -- and, that an interval is Y time units, you *know* that this "something" happened at X + 5Y.

If this *isn't* true, then your notion of "Y time units" differs from mine (or your idea of "5" differs from mine :> ).

But, since our clocks are synchronized (and syntonous), then your notion of Y time units *must* coincide with mine -- else the clocks would no longer be in sync!

And buffer overrun is a *symptom* of that!

I.e., if our clocks are (still) synchronized (or at least syntonous), then a buffer *can't* overflow -- because the producer *won't* create data faster than it is being consumed (i.e., it *knows* you can only buffer N "samples of the future" so it won't *send* you the sample that will correspond to now+N+1)

So, if it *has* overrun, it is indicative of a disagreement in the clocks (or their relative rates). I.e., this is information that the "clock synchronization process" can use to determine that the clocks are *not* synchronized. That's the point of feeding back information to the server -- so that, by listening to the unsolicited complaints of *all* of its clients, it can decide whether *it* may be the offending party (i.e., *its* clock isn't synchronized well enough to the Grand Master Clock) or "(all of?) the complaining clients" are the problem -- or, something else (a failure in a switch, some anomalous sort of traffic change that impacts the synchronization algorithm, failure of some part of the fabric, etc.)

But then it has to "remain silent" until it's buffer fills.

Actually, expressed that way, that's misleading (though correct) so let me clarify...

The packet currently being broadcast corresponds to a time "N packet-times" in the future (where N is the size of the *other* clients' buffers -- since their buffers are already "full", the producer is getting ready to emit the packet that will come *after* those that are already enqueued). Assuming the current client's buffer to be of the same size as the other clients' (not required!), then that next packet will sit in

*this* client's buffer for N sample times (which happens to be the size of its buffer!) before it *should* be "played". [Note that the samples *can't* be played until time+N else this client's output will not be synchronized with the output from other clients]

No. You only need this when a new client comes online. And, you don't have to *blast* all of the data down the wire instantaneously. What you are trying to do is get this client caught up with the others "as quickly/efficiently as possible".

What I do is push the "previous" packets (i.e., those that have

*already* been broadcast to the other clients while this one was "off") to the new client in reverse chronological order. That way, there are no gaps in the client's buffer between the packet that is currently being broadcast for the *set* of clients and the packets that have been accumulated, thus far, by this *new* client.

In this way, the client can participate in the "normal" broadcast stream -- enqueuing future data -- while also "backfilling" data that the other clients already have. Once it has backfilled to "now" (realizing that now changes with the passing of time), there's nothing more for the server to do and the client can start emitting sound.

No. The server knows (learns) the capabilities of all clients that are currently on-line. It then has to juggle the data stream(s) (!) that it broadcasts so that all clients' capabilities are maximally utilized.

If it caters to clients with big buffers, then those with small buffers end up "running dry" regularly!

If it caters to clients with small buffers, then those with big buffers have surplus resources that are NEVER used (why did you buy the deluxe model?).

So, if it has clients of different buffer sizes CONNECTED TO THE SAME AUDIO SOURCE (channel) it has to create multiple broadcast/multicast streams to address their differing capabilities.

Reply to
Don Y

Let us assume that the Buffer in each Client has "Almost Full and "Almost Empty" detection (the thresholds for each could be fairly close to 50% if desired). When "Almost Full" is reached, the Client asks the Server to slow down. When "Almost Empty" is reached (from middle, that is), the Client asks the Server to speed up. Simples!

Now consider the case where there are many Clients. It is extremely likely that at least 1 Client will be asking the Server to speed up, and at least

1 Client will be asking the Server to slow down. Therefore a system of this type cannot work.

A system where the Clients can each adjust their clock so that the Buffer is kept in the 'happy' zone is required.

Or else a realization that dropping/repeating/interpolating an occasional audio sample won't actually do any discernible harm...

--------------------------------------- Posted through

formatting link

Reply to
RCIngham

------------------------------------------------------------^^^^^^^^^^^^^^^^

No. It is only "likely" if your clock synchronization algorithm isn't up to par!

So, in those cases where the clock synchronization algorithm isn't up to par, you are advocating ANOTHER "clock synchronization algorithm"? And *that*, magically, will be better than the *real* synchronization algorithm? In that case, why not use *that* magical algorithm to synchronize the clocks?

Reply to
Don Y

"Almost

if

slow

likely

least

this

Buffer

occasional

No. I am suggesting that the as-I-understand-your-description-of-it requirement for clock synchronization is impossible to solve.

--------------------------------------- Posted through

formatting link

Reply to
RCIngham

It can be "solved" (as much as any engineering problem can be solved). But, you still have to write your code to handle the case where it "isn't working" -- or, isn't working at exactly 100.0% (apparently).

[recall that getting one extra sample only signifies that the incoming data rate is epsilon greater than the outgoing one! Can any recovery algorithm -- e.g., resampling data -- be *better* than epsilon, GUARANTEED? (or, will you need a recovery algorithm for the cases that *that* algorithm doesn't completely address, etc.)]
Reply to
Don Y

algorithm"?

So, what is the 'fall-back behaviour' or 'recovery algorithm' in these cases?

--------------------------------------- Posted through

formatting link

Reply to
RCIngham

That was the point of the post:

"But, what PRO-ACTIVE strategies can I adopt -- if I am willing to enlist the other clients and server -- to minimize the chances of this happening?"

Note that this sort of problem isn't limited to distributed systems but, rather, to any system where there isn't a tight coupling of services to clients. Or, where performance guarantees aren't as tight as one would theoretically *hope*.

E.g., if you write a producer and a consumer on a uniprocessor and your "get_system_time()" exhibits some degree of jitter (e.g., perhaps it -- or *you* -- is *interruptible*), then you run the same risk of your producer and consumer getting (even slightly) out of sync leading to an instantaneous overrun/underrun condition. ("Missed it by *that* much...")

I contend that running with buffers "nearly full" as the nominal case is the only prudent approach.

- If your consumption clock creeps up *faster* than the production clock (regardless of where the delta comes from), then you run the risk of slowly draining your buffer EVEN THOUGH DATA IS ARRIVING AT THE "correct" RATE. So, having "more" data to fall back on is better than having *less*. This buys you time to identify the source of the problem and fix it.

- If your consumption clock slips down *slower* than the production clock, then you *will* overrun your buffer. But, you can elect to discard those newest samples *if* you have a mechanism for reacquiring them (when you *can* accommodate them). Again, buying you time (i.e., the maximum interval in which you will be able to reacquire the dropped samples) to fix the problem.

But, any remedies that you implement locally without some way of determining whether the cause of the problem *is* local will just distort or corrupt the data. The trick is to "close the (cascaded) loop"

Reply to
Don Y
[snip]

But can you limit the data distortion/corruption to something that doesn't actually matter? A dropped/padded/interpolated audio sample that is effectively undetectable to the ear? A radar return truncated at the far end where it is of least interest? A skipped frame of CCTV video? If so, why bother closing the loop at all?

I refer you to plesiochronous telecommunications system design...

--------------------------------------- Posted through

formatting link

Reply to
RCIngham

How can you quantify the distortion/corruption if you don't

*know* what it is or *whether* it is?

Remember, the *application* determines what does and doesn't matter! The goal here is to make a *wire* for "audio frequency signals" (one application of which is distributing "sound")

What happens if that artifact repeats periodically? (i.e., if you haven't fixed the problem, it *will* repeat -- periodically)

If that's an incoming missile, someone might appreciate that extra warning the dropped signal would have provided (instead of waiting for the antenna to circle 'round again)

As with the audio, what happens when you see a frame skip

*regularly*? Or, if you were *analyzing* those frames to detect/quantify motion?

Because you (I) don't *know* what the application will consider "significant". Why do we use shielded cables -- why not just

*tolerate* the noise floor that is present? Heck, it doesn't seem to matter to me when I use them for SPEAKER WIRE! :>

Why isn't all wire #2 AWG stranded? It seems to work quite well for my jumper cables!

I don't *know* what each of the examples you've presented would be considered appropriate and/or acceptable. I suspect that different *users* of each of those applications would have different criteria of "acceptability".

But, how are you going to present the capabilities of your "wire" to each of them: "It's a wire -- sort of -- except when it isn't"?

Telecom has *really* poor audio requirements -- two tin cans and a *string* are almost good enough. Imagine if it was *data* that was being sent down that telecom network. How tolerant would you be if every Nth byte was irrevocably *lost*? Or duplicated?

*And* if you had no way of knowing *which* bytes were affected?
Reply to
Don Y
[snip]

"significant".

Actually, I do, because the System Design process.

If you don't know the characteristics of the signals you are passing, or the use to which they are put, then you don't have a System Design. In which case "Good luck with that".

--------------------------------------- Posted through

formatting link

Reply to
RCIngham

Exactly. My design criteria is "as a wire". I want a subsystem that I don't have to re-evaluate (or re-DESIGN!) each time I "apply" it:

"Well, we're pushing audio down the pipe but the people that will be listening to it will be over 65 and, therefore, we can assume most of them won't be able to hear anything over 15KHz..."

Reply to
Don Y

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.