On Mon, Mar 10, 2014 at 7:27 AM, Matthew Jordan <mjor...@digium.com> wrote: > > On Mon, Mar 10, 2014 at 6:59 AM, Joshua Colp <jc...@digium.com> wrote: >> >> Matthew Jordan wrote:
<snip> >> The NLB compatibility code actually checks whether something like a >> MixMonitor is on either Local channel and won't allow it to be used. >> >> Now that I've given a diagram to show where things optimize and how it >> isn't inside of chan_local... what do you think NOW? ;) > > > I think this proposal is tantamount to killing Local channel optimization. > > I'm not sure that's a bad thing, but I'd certainly like to get more > opinions. > Updating this thread with some more thoughts. These are a bit random, but hopefully they'll spark some conversation about possibilities here: * We probably can't get rid of Local channel optimization. While it is ugly - and prone to causing strange thing to happen both in the core and from the perspective of an external user - there's at least one use case that needs this feature: collapsing two RTP capable channels into a native bridge. For example, assume we have the following: --> <------> <--------> <-- SIP/foo \ / Local;1 Local;2 \ / SIP/bar - - B0 B1 Here, B0 and B1 would currently be simple two party bridges with the media flowing through the core. If feature requirements meant that SIP/foo and SIP/bar could not be natively bridged - even if they were directly in a bridge together - then optimizing this scenario doesn't buy much performance. If, however, optimizing away the Local channel would result in the bridge between SIP/foo and SIP/bar being a native bridge, then the performance gain is significant. * There's lots of strange edge cases with Local channels. Consider, for example, some of the following scenarios (all of which are possible in 12): ** Local channel between Real channel and multi-party bridge with Real channels. In this case, optimization should result in the Real/A channel being pushed into bridge B1. B0 / <-------- Real Real/A -->/ \<------> <------> - B1 -- <-------- Real Local;1 Local;2 \ <-------- Real ** Local channel between Local channel and a multi-party bridge with Real channels. Here, there's a possible race condition between the Local channels: we don't know for sure what is on the other end of the Local/A;2 channel. Finding out is also a bad idea - a whole lot of things would have to be locked in order to get that information. What's more, there may be another Local channel beyond Local/A! This is where Josh's proposal comes into play, as the information is passed down the chain - making it so that optimizations don't have to occur in Local channel chains. At the same time, we may want to try and optimize away the Local channel between the multi-party bridge of Real channels and the other Local channel. Assuming Local/A doesn't win in an optimization race, we'd want Local/A to take the place of the existing Local channel - but we have to prevent it from optimizing away at the same time. B0 / <-------- Real Local/A;2 -->/ \<------> <------> - B1 -- <-------- Real Local;1 Local;2 \ <-------- Real ** Local channel between two multi-party bridges. Here, there's really two ways to handle this: either don't optimize away, or merge both bridges together into one massive multi-party bridge. Real --> \ / <-------- Real Real --> -- B0 - <-------> <------> - B1 -- <-------- Real Real --> / Local;1 Local;2 \ <-------- Real ** Two Local channels optimizing into a multi-party bridge. Both our Local channel - as well as Local/B - may attempt to optimize the channels on the other ends into B1 at the same time. The bridge has to carefully manage this process. B0 / <-------- Real Real/A -->/ \<------> <------> - B1 -- <-------- Local/B Local;1 Local;2 \ <-------- Real All of these scenarios are currently handled by core_unreal and core_local in some fashion. It is, however, very complex code that - particularly with Local channel chains - is prone to error. The implementation today faces two problems: (1) Knowledge of what is on the other side of the bridge is known by the bridge, but not by either Local channel half. In order to get that knowledge, both Local channel halves must take control of the bridge (and all of its participants), then synchronize with each other. (2) When multiple Local channels can optimize in a chain, they have to communicate with each other (or at least compete with each other) to see who optimizes out first. This can change the information that a Local channel has about how it can optimize: for example, a Local channel may view that it is in a two party bridge with another Local channel, attempt to optimize, only to find out later that it is now in a multi-party bridge with multiple Real channels. (3) When optimization occurs, there can be *no* information in flight on the Local channel. This is particularly difficult as the write queue exists on the ast_channel struct - which means that the bridging layer has to be informed to not write to the channel when the optimization occurs. Again, more points of synchronization and locking. There's a few possible approaches that may simplify the implementation: * Use approaches such as Josh's native Local bridge to move logic out of core_unreal and core_local into bridge implementations. The bridges actually have state now, and *know* who is in the bridge with them. A bridge implementation could be written that handles a Local channel + one other channel, and it could tell the Local channel when it can optimize. * Add a write queue on the bridge_channel struct. There already exists a read queue on this same struct; having two queues would make it so that the bridge never has to stop writing frames destined for a channel, even during optimization. There is a possible performance cost to this approach, but it would reduce friction during optimization as the Local channel can opt to stop reading from its write queue. Lots of things to think about! Matt -- Matthew Jordan Digium, Inc. | Engineering Manager 445 Jan Davis Drive NW - Huntsville, AL 35806 - USA Check us out at: http://digium.com & http://asterisk.org
-- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- asterisk-dev mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/asterisk-dev