<div dir="ltr"><div><div><div><div><div><br>On Sat, Mar 8, 2014 at 1:19 PM, Joshua Colp <<a href="mailto:jcolp@digium.com" target="_blank">jcolp@digium.com</a>> wrote:<br>> Greetings everyone on this glorious weekend!<br>
><br>> I've had an idea bouncing around my head for the past many months on an<br>
> alternative approach for optimizing Local/Unreal channels. This morning<br>> everything finally clicked and I put it together[1] (I'm still working on<br>> it/tweaking it, but it DOES work).<br>><br>> The traditional approach has been to collapse the chain of Local channels<br>
> down until you are left with the minimum amount required. Unfortunately this<br>> can be rather complex and error prone as you need to go through the entire<br>> chain and then figure out the best way to accomplish this (keeping in mind<br>
> juggling multiple locks and potentially multiple bridges). You also end up<br>> needing to give information when this happens so consumers know what is<br>> going on.<br><br>In any of the code bases, this is a difficult and complex thing to do. In 12, while I'm not sure we made the problem worse, we certainly didn't make it any better.<br>
<br>In order to optimize, each Local channel half has to first determine if they even can optimize. If they are in a bridge with multiple participants, there are ways in which they can - either by a bridge merge or a bridge swap. (Merge puts two multi-party bridges together; swap moves a single participant into another bridge (single or multi)). If they can they then have to synchronize with the other half, lock both bridges that the halves are in - including all of the participants (via the bridge lock) - then move a lot of channels around.<br>
<br>To date, the Local channel optimization test - which collapses 150 Local channels - is the number one failing test in the test suite. Weird timing errors cause weird errors. While I'm confident we'll get to the bottom of all the edge cases, it is very, very, very complex.<br>
<br>We eliminated the vast majority of masquerades - but this particular operation is, in many ways, just as nasty.<br><br>> The bridge_unreal approach doesn't do this. It aims to optimize the path for<br>> frames traveling through the chain, allowing them to skip intermediary hops<br>
> where they don't need to go through. This results in a very similar<br>> situation for the frames but does not move/change/alter/hangup the<br>> intermediary channels involved.<br><br>It's important to point out that optimization's goal was never the removal of the channel. If anything, nuking Local channels has - in my opinion - always made life more difficult for everyone, not easier.<br>
<br>The goal was performance - minimize the frame path. If I'm picturing this correctly, this doesn't *quite* optimize as efficiently as completely removing the Local channels - but it may still be sufficient.<br>
<br><span style="font-family:courier new,monospace">Real-01 Local-02;1 Local-02;2 Real-03</span><br><span style="font-family:courier new,monospace">------> <-------------> <------------> <-------</span><br>
<span style="font-family:courier new,monospace"> \ / \ / \ /<br> -B0- -NLB- -B1-<br> Real-03 Real-01</span><br><br></div>
In this case - and this is assuming I understand the proposed Native Local Bridge correctly! - Local-02;1 has as its actual destination target Real-03, while Local-02;2 has as it actual destination Real-01. When B0 pushes a frame to Local-02;1, Local-02;1 knows that it should just pass it on to its destination. Rather than passing to its bridge, it writes directly to Real-03. The same happens in reverse for Real-03 to Local-02;2.<br>
<br></div>Creating a chain of these works by the real 'endpoints' getting passed down the chain of Local channels via control frames.<br><br></div>There's two issues I can see with this - one minor, one maybe not.<br>
</div>(1) There's a small amount of work here that occurs by the Local channel passing the frame on to its destination channel. It's minor, but it would be slightly more work than what occurs during today's optimization.<br>
</div>(2) More seriously: I wonder if the destination shouldn't be a channel but a bridge. The above optimization cannot work for multi-party bridges: there is no single channel destination. Today's optimization does work in that scenario via a bridge swap - the single party on one end gets swapped with the Local channel in the multi-party bridge. This really is a minor case - the idea of optimizing channels into multi-party bridges is admittedly ridiculously new - but it may be useful to think through this use case.<br>
<div><div><div><div><div>
<br>> It does this by passing each far end channel through the entire chain with<br>> each intermediary hop storing them and the next hop in the chain examining<br>> and forwarding them on over and over. Once this completes each end has the<br>
> channel that is at the far end and is able to queue frames onto it directly,<br>> bypassing the intermediary hops. This happens over time (less than a second,<br>> I'm not talking minutes here) but leads to eventual optimization. Even in a<br>
> compromised optimized state frames will still flow as expected.<br>><br>> This also works perfectly fine when a hop uses /n and wishes to remain in<br>> the path of frames. Each side of that hop will optimize themselves and skip<br>
> any intermediary hops. (Although, since channels stick around... when would<br>> you need to use /n? Hrm...)<br>><br><br></div><div>I would think you'd need it if you had a hook that needed the audio on that Local channel - such as a MixMonitor.<br>
<br></div><div>In general, I prefer this approach over our current, for a few reasons:<br><br></div><div>(1) Things are now consistent. The relationship between Local channels is now explicit as opposed to implicit, and the events that are raised in relation to them are now the same as all others.<br>
<br></div><div>(2) Things are simpler - or at least, complex in the same areas as 'normal' channels. It's easy to be complex and fast (current Local channel optimization) and also dead wrong (dead locks, ref leaks, and other badness). I think Local channels end up being wrong more than we'd like to admit. Because this relies on the bridging core to get things right, if the bridging core is right, Local channels will be right.<br>
</div><div><br></div><div>One other major downside to this: it will change our model of Local channels in a breaking fashion. Some events will no longer occur (such as the optimization begin/end events), and new ones will definitely start to happen (BridgeEnter/Leave messages for the new native bridge). That may be worth doing - but this isn't a habit we should get into.<br>
<br>Matt<br></div><div><br>-- <br>Matthew Jordan<br>Digium, Inc. | Engineering Manager<br>445 Jan Davis Drive NW - Huntsville, AL 35806 - USA<br>Check us out at: <a href="http://digium.com" target="_blank">http://digium.com</a> & <a href="http://asterisk.org" target="_blank">http://asterisk.org</a><br>
</div></div></div></div></div></div>