MX value in SSDP search request

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

MX value in SSDP search request

bebopfreak
Is there a way to change the MX value for search requests?
I haven't found anything in the manual.

Currently it takes about 10 secs for my phone to detect devices
(usuall I have 3 or more devices running).

As far as I understand the default value for MX is 1 in Cling.

I looked at the way randomization is done in libupnp:
replayTime = rand() % mx; (in seconds - they should have
taken at least 10ths of seconds)
which amounts to no randomization at all, when the
value is 1!

Cyberlink has a default value of 3, which works pretty well.

Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

Christian Bauer
Administrator
I've added the method ControlPoint.search(UpnpHeader searchType, int mxSeconds) in trunk.
Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

bebopfreak
Now it's behaving like Cyberlink (not really surprising).

'1' second mx value certainly would be great nowadays,
if devices weren't that dumb!

Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

bebopfreak
After doing some more test, I think speed has improved, but there is still a noticible difference between Cling and Cyberlink.

I don't know the reason - too much locking?

You can do tests, to see how the behaviour scales with multiple devices. Switching between Cling and Cyberlink is possible with current snapshots at http://upnplay.hoohol.ath.cx/
Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

Christian Bauer
Administrator
In reply to this post by bebopfreak
Last time I profiled Cling on Android, the problem was the XML parsing. I've done what I could to make this as fast as possible but it looks like XML parsing is indeed very very slow on Android 2.1. I'm not sure what Cyberlink is doing and I still hope that 2.2 is faster.
Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

bebopfreak
If I read the code correctly, Cyberlink uses XmlPullParser as default parser - and I didn't change the default. The resulting internal xml representation it creates is certainly much simpler with less validation!

I'm using Android 2.2 and my timing for detection (with 3 devices, 2 servers 1 renderer) is basically around 1-2 secs for Cyberlink vs 4-8 secs for Cling with higher variance. (So even jit doesn't help that much.)

I don't know the Cling code, but how much parallelism is there during detection? Do you lock everything until a complete device is constructed?

Are you sure, you can blame the parser and not the time needed for creating and validating structures? The xml part of Cyberlink is rather self contained, so it would be easy to set up performance tests.
Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

Christian Bauer
Administrator
Locking and concurrency is an issue on Android but I believe I found good thread pool settings. You can play with these as well if you like in AndroidUpnpServiceConfiguration:

    @Override
    protected Executor createDefaultExecutor() {

        // Smaller pool and larger queue on Android, devices do not have much resources...
        ThreadPoolExecutor defaultExecutor = new ThreadPoolExecutor(8, 16, 5, TimeUnit.SECONDS, new ArrayBlockingQueue(512)) {
            @Override
            protected void beforeExecute(Thread thread, Runnable runnable) {
                super.beforeExecute(thread, runnable);
                thread.setName("Thread " + thread.getId() + " (Active: " + getActiveCount() + ")");
            }
        };

        defaultExecutor.setRejectedExecutionHandler(
                new ThreadPoolExecutor.DiscardPolicy() {
                    @Override
                    public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {

                        // Log and discard
                        log.warning(
                                "Thread pool saturated, discarding execution " +
                                "of '"+runnable.getClass()+"', consider raising the " +
                                "maximum pool or queue size"
                        );
                        super.rejectedExecution(runnable, threadPoolExecutor);
                    }
                }
        );

        return defaultExecutor;
    }

To see how long descriptor retrieval (incl. HTTP) and parsing takes, just enable FINER logging for category 'org.teleal.cling.protocol.RetrieveRemoteDescriptors'. For each discovered device there will be one thread that runs through this procedure.

I profiled and then, after it was clear the problem is the XML parsing, I benchmarked and optimized the XML parsing procedure. No other code was involved in these tests.

I wrote a plain SAX and a DOM parser, both are extremely slow. Surprisingly, SAX is a little slower than DOM parsing contrary to what other microbenchmarks show. There is another API in Android but I don't think it's any better or faster unless it is not internally using the Apache XML crap. I've not seen any difference in other benchmarks so I didn't even try.

You can take UDA10DeviceDescriptorParsingTest#readUDA10DescriptorDOM() of Cling and run it on Android in a loop to benchmark. If you write an org.xmlpull parser - which is the third API supported in Android - and it turns out to be faster than the existing DOM and SAX parsers, I'd be happy to include it in Cling.
Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

Christian Bauer
Administrator
By the way, these thread pool settings mean:

- at most there will be 16 threads running
- there will always be 8 threads waiting to do work in the pool, at minimum
- if more than 8 threads are active, and one is idle for more than 5 seconds, it will be removed
- if more than 16 threads are required, work has to wait in a queue of maximum 512 items
- if the queue is full, executions are rejected

Some threads of this pool will always be used, for the UDP/TCP socket listeners and registry maintainer, so there are really only 5-10 threads available when devices are discovered and descriptors parsed.
Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

bebopfreak
I spent some time trying Cling as a possible alternative to Cyberlink for my project.

I was telling about my experiences, but my intention was never to get involved in the development (or tuning) of the project. It would have certainly produced ideological conflicts.

With Cling I might get 99.999% compliance with the standard (if there are really more than 100000 features in the UPnP specification).
On the other hand I get zero permissiveness: I even won't detect a device, if it has one allowed string value with 33 characters ("1 star: didn't detect my ...device, erased the crap"  would be the  comment and I will usually don't know what's going on).

In my opinion there should be at least two different modes: 'strict': for developing new devices with the possiblity to remove unnecessary overhead (if the goal should be embedded), when development has finished. 'permissive': without overhead for applications that deal with existing real devices.

As the attention span of todays users (kids) is extremely short, I don't think I can tell them that waiting 5 seconds is an improvement to waiting 1 second.

So currently I'll stick with Cyberlink (it's small - far less than 300 classes - and learn a bit more about HTTP sockets, to fix the remaining problems).

As my interface to a UPnP-library is really thin (using a few convenience functions), there's no problem to come back, when Cling will be faster, leaner and more permissive.
Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

bebopfreak
In reply to this post by Christian Bauer
Cyberlink parses the same device and service files with the standard XmlPullParser as Cling and takes much less time, so why should the parsing be responsible?
Reply | Threaded
Open this post in threaded view
|

Re: MX value in SSDP search request

bebopfreak
I looked a bit closer at Cyberlink and found out that my statement above isn't quite correct.

Cyberlink uses a 'lazy evaluation' approach, i.e. it reads and parses all device description files, but retrieves and parses service description files only when needed, when access  to properties, variables, actions ... of a service is required. In my current implementation I only needed properties from renderer devices, when creating devices (which I delayed by now). So actually in the scenario of 2 servers and 1 renderer, only 3 device and 3 service files were parsed.

But parsing doesn't seem to be a bottleneck with Cyberlink anyway. Parsing (and constructing its simple dom structure) takes about 1.2 secs for a container DIDL-Lite file of 1500 albums (more than 700000 bytes).
Device and service files are usually much smaller, between 20000 and 50000 altogether per device.
(The timing is for a HTC Desire with Android 2.2).