Why Trigger.io doesn’t use PhoneGap – 5x faster native bridge
trigger.io
trigger.io
This is a silly benchmark - there is absolutely no reason you would put 1000 calls at once, sequential or parallel, across this sort of bridge in a real app. You probably shouldn't be calling any JavaScript API in a client-side app 1000 times at once.
The bridge in PhoneGap Android probably is slower than the one in Forge but
1) that's a tradeoff the PhoneGap devs were willing to make for wider compatibility, support for older devices, and isolation from the bizarre Android WebKit bugs that crop up in every release.
2) synthetic benchmarks aside, there's no indication this would affect the usability of the app.
Take the camera example in the article. A PhoneGap call (judging from the graphs) takes about 14ms, a Forge call about 3ms. That's for the entire round trip (JavaScript -> Native -> JavaScript), so divide each in half for each side of the trip.
With PhoneGap: * first half of the trip (7ms) * Android presents Camera activity, user picks a photo, Android returns control to original app (say, 500ms, very conservatively) * second half of the trip (7ms) = 514ms
With Forge: * first half of the trip (1.5ms) * Android presents Camera activity, user picks a photo, Android returns control to original app (500ms) * second half of the trip (1.5ms) = 503ms
This is much closer to a real-world use case - and the calls to native APIs entirely dominate the time spent on the bridge.
On a side note, are there plans to develop a better set of debugging tools for PhoneGap? It's one of the major pains of the platform. If one is already in development can you point me in the proper direction? Thanks!
Actually, we think this is a pretty important benchmark: battery drain and general responsiveness is a huge deal on mobile devices, so we take performance of the bridge very seriously. Every millisecond counts here.
Also, I can absolutely see the need to send large number of messages - a streaming accelerometer API, for example, which is on our roadmap.
You're right that there might be trade-offs between raw performance and supporting every quirk of every device. However, in this case, the Android bug you refer to only affects v2.3 emulators, not actual devices (to the best of our knowledge). We automatically set up our users with a v2.2 emulator to side step the problem.
We think such significant performance gains for our users, and a much cleaner, easier to maintain codebase for us, is well worth it in this case.
Again, "such significant performance gains for our users" is just FUD when you're talking about arbitrary benchmarks. An app built using Forge and PhoneGap, providing the same functionality, with the same UI layer, would be a much better measure of that. I'd be happy to be proven wrong.
Remember, this post was called "Why Trigger.io doesn’t use PhoneGap" - it's about the reasons we chose not to live downstream from you, not just a post bashing what you've done.
For us, the significant delta in performance is evidence of a different philosophy between what we are aiming for, and what you offer. We clearly want to make different design decisions, and need to be independent to do that properly.
Clearly, there is a tradeoff to be made between usability&portability and speed. To be fair, I think the camera example is not a good one: at Zite we use web<->native api for lots of things that performance is really important for since they are frequent (logging, timing, anything called frequently)
Agree the web<->native api performance is important for the use cases you mention.
Although performance is important, as someone who does PhoneGap apps for a living (http://mulberry.toura.com) I can tell you that there are so many other performance problems with HTML5 that this is wayyy premature optimization.
11ms isn't going to kill you, and if you are experiencing performance problems, there are far more important things to do (check for DOM leaks, dealing with 3G latency, etc.) than shave off a few ms on a call to a native function.
Or put another way, there's no reason to create another PhoneGap-like framework to save 11ms on a native function call. There are a whole lot of other reasons (many business-related) of course. But this isn't one of them. :)
Thanks,
--
Matt
For us at Trigger, however, we don't have any control over the efficiency of your Javascript, or the interpreter and rendering engine that holds it.
What we can control is how efficient the communication is between your JS and the underlying native APIs. Everyone agrees that performance is a key issue, so we take great care to ensure that the performance of code we control is as small as possible.
Of course, there were a number of reasons we were wary of being downstream of PhoneGap. The specific issue of Android performance wasn't a blocker, but was, to us, symptomatic of a philosophical difference between PhoneGap's approach and ours. We're not saying one is Right and one is Wrong - we just have different priorities.
Another key aspect for us was that our runtime platform is tightly integrated with our tooling: how those tools interact with the generation of runnable apps is obviously key to usability of our product, so we were very uncomfortable not owning such a key part of the puzzle.
The other option would have been to fork PhoneGap with no intention to push upstream, but that, to me, is against the spirit of open source, and still not optimal to us as we'd need to shoe-horn our tooling to fit a code base not designed with our needs in mind.
There is no benefit to sending ondevicemotion events out to the native code because you can always get higher frequency updates on the native code (60Hz vs 20Hz) and sending them in via stringViaEvaluatingJavascriptFromString is identical between Trigger.io and PhoneGap (and will happen with a lower latency than things are drawn on screen in a UIWebView).
True enough that on iOS we would perform comparably, but for Android, it would mean "long"-polling a local web server at 60Hz!
I hate to hijack, but are you guys seeing any of these apps rejected by Apple because they weren't made with native controls or any other reason? There's a project I'm going to begin working on and phonegap looks like a real time saver to me, but I don't want to have to deal with Apple telling me that my apps aren't "good enough" for them.
Thanks,
-- Matt
Second, different is not always better. This will increase call performance, but will incur a (de)serialization penalty, limit parameter types (likely to scalars and read-only hashmaps), and make debugging more difficult. And beware of telling the OS that you implement this protocol, or you will have created an XSS attack vector on your native app.
Whenever you break new ground, don't fool yourself into thinking that you're the first person who has had an idea, and make sure that you sanity check your work.
This left us with the option of putting up with it (and ending up with an inferior product), or writing our own bridge, and writing our own bridge made sense. Of course you are right in that writing anything new means you have to work hard to get it to as high a standard as the alternatives, which is why we work hard to test our platform - see http://trigger.io/cross-platform-application-development-blo....
It's also important to remember that the native bridge is just one part of our product, we also write the code that generates and builds the app, which we want to integrate as tightly as possible. Writing our own bridge makes this a lot easier to do well.
In any case, I think that anyone is free to do whatever they want with their code- trigger.io are not obliged to liberally license their work. They even describe how they've achieved their performance increase in the blog post- it's more than many would do.
Also we're a small team so don't have time to do everything we would like, and also contribute to Cordova. Trigger.io's native bridge is not a a fork of PhoneGap or downstream of it.
But the bridge between the webview and the Appcelerator code is painfully slow. I had it pinging over current location coordinates more than once per second- it worked fine in the simulator but utterly crippled the app when run on a device. For now all I can do minimize the number of calls I make, but that's hardly a great solution.
Cool app by the way thanks for sharing... though I wish I could try it on my Android ;-)
Rest assured, the Android version is on the way. In fact, this app-crippling native <-> webview communication is what has taken up all my time and stopped me from developing the Android version.
Looking forward to the day you guys have a solution for background processing- the Appcelerator JS/native hybrid is a mess I'd love to see the back of.
http://phonegap.com/support#support-packages
The main difference with us is that you do not pay to raise a support tickets: you get direct access to our developers on any plan. And we charge per-app with no restrictions on the number of developers.
It seems, from what I can tell, users must go through Trigger.io to do a build to get their app in the store. Their code isn't portable to a non-trigger.io platform, either (mobile web, etc.), and the built binary contains closed-source code (Trigger.io platform stuff).
You can run a PhoneGap build locally without going thru the PhoneGap build service. And you get complete and unrestricted access to the source code.
If your service disappears or starts charging exorbitant amounts of money, users are SOL.
Trigger.io is a commercial entity that is in the business of locking customers into a platform and exploiting it. PhoneGap is the opposite. I place no value judgements on this (I use plenty of licensed code on a daily basis and I work for a commercial entity doing something similar); that may or may not matter to a person, but to me - that seems to be the main difference.
I can't say I never use closed libraries/platforms/APIs, but when possible, I always choose the option that has a community fork, or some other escape route.
We think the biggest barrier to adoption of a platform like ours or PhoneGap's is complexity. So to keep the API and dev process as simple as possible we decided to keep control of the whole experience for our launch. Now, we're considering opening up more than just our command line tools, and will likely start doing that soon.
But being closed for now, people will hold us to a higher standard of simplicity, performance and customer support to give them a reason to change. We work hard to live up to that.
What you consider the 'main' thing is subjective, just wanted to point out the difference in how we support our customers and the pricing for it in the previous comment.
From what I could tell, the bug was shipped starting with some version of Android 2.x (I'm thinking 2.2) where JSC was used as the internal JS engine for WebKit instead of V8. When the Android devs added V8 support, they actually broke JSC support. It's a device manufacturer choice (or was) as to which JS engine to use. Curiously, Android shipped the 2.3 simulator image (guess that was the version) with JSC support, thus, "it was broken".
The API in question is `WebView.addJavascriptInterface()`. That method returned successfully, but whenever you accessed the interface from JS, you'd trap.
Could be this was only on the simulator, but - I'm thinking folks saw this on devices as well. Maybe those devices are no longer relevant?
Presumably Cordova will revert back to using `WebView.addJavascriptInterface()` when it's safe to do. The problem is, it's not clear when it's safe to do so. It's also not clear how you can test your JS environment to see if "it's safe", programmatically. Or maybe you can (eg, throw an Error, check for existence of error.stack), but ... it's wasn't a comfortable situation to be in.
Do you have some references that the 'bug' doesn't ship on devices, or that it no longer ships on simulator images?
What versions of Android SDK/simulator/devices does Trigger.io support? Presumably you don't support running Android 2.3 on the simulator, as your code would trap?
Although we obviously can't test every device out there, everything so far points at no device ever actually shipping with JSC after 2.2, e.g. see http://code.google.com/p/android/issues/detail?id=12987
If we do get requests from our users to change that approach, we'd obviously consider it, but at the moment, we think the significant performance and code cleanliness benefits outweigh the downside.
>> We then make a request to a fake URI (forge://…) which we intercept in native code
Have you tried doing the same for Android? Do you have any numbers that compare the performance of this method with the JS -> Java bridge?
Anecdotally we think a performance comparison of the bridge would be favorable, but actually the main reason people use us over other frameworks is that our development process is designed for web devs.
So with us, you don't need to do local compiles or use a particular IDE, and we have a much faster build / test cycle.
Simplicity is and has always been of huge importance for us. Developers that use our framework tell us it is much easier to get started with than other offerings out there.
And as long as you're referring to mobile, why wouldn't you just use OpenGL anyways?
With a little work, UIWebviews on iOS (4.2+) support WebGL.[1]
[1] http://atnan.com/blog/2011/11/03/enabling-and-using-webgl-on...