Why is the mobile web slow?
codenameone.com
codenameone.com
Well, "always" is a little wrong. The first time a message is passed and the bound method is called by the runtime is significantly slower (~4x slower than a virtual method call in C++). But then this message/method pair gets cached and for every subsequent call the cache is used.
Then there's some real neat trickery that is performed in objc_msgSend() ... after the method to "call" has been found the code directly jumps into that method without creating a new stack frame. (All needed arguments have been passed to objc_msgSend() and are already on the stack.) objc_msgSend() in essence is a trampoline.
So when sending a message to an object multiple times you only pay for the cache lookup - which is pretty fast by itself and a cached call is faster than a C++ virtual method call.
Performance Numbers: http://www.mikeash.com/pyblog/performance-comparisons-of-com...
More about objc_msgSend(): http://www.mikeash.com/pyblog/friday-qa-2012-11-16-lets-buil...
Now I don't know enough about Java but I guess it isn't much more faster than that. So calling Obj-C slow may be a little too bold.
objc_msgSend is a trampoline in the sense that it leaves the frame/registers untouched and jumps straight to the target implementation.
That said, you can implement the kinds of trampolines you're referring to without writable code pages, it just requires more work: http://landonf.bikemonkey.org/2011/04/index.html
The language alone cannot do anything.
http://www.friday.com/bbum/2009/12/18/objc_msgsend-part-1-th...
This is not true. The code in Mike's test for "IMP-cached message send" doesn't match the cached path of objc_msgSend. It matches what you would get by doing IMP-caching yourself, which is common in some Objective-C frameworks, especially older ones. The cached path of objc_msgSend is what is measured by the "Objective-C message send" row, which is a lot slower.
The fast path of objc_msgSend roughly goes like this: you dereference the isa of the object to get to a class description, then you dereference a pointer to the cache, and after finding the selector in the cache, perform a tail indirect call to the IMP. Even if the cache lookup is free this is two dependent pointer dereferences followed by a dependent indirect branch.
A C++ virtual call just dereferences a vptr and makes an indirect call to a function at a static index in the vtable, which will always be more efficient than objc_msgSend. It's true that manually caching the IMP yourself and calling it will be faster than a C++ virtual call, but there's nothing stopping you from caching the implementation of a C++ virtual call in exactly the same way.
Another major factor in the performance difference between C++ and Objective-C is that C++ allows you to have non-virtual member functions, which can be inlined, whereas Objective-C requires all method calls to go through the same mechanism.
DOM reflows are the major unsolvable source of perceived slowness.
Cool.
So, in an app where you avoid reflows, is mobile web fast? Why or why not? How avoidable are reflows?
Can anyone point me to any articles that talk about this specifically, or benchmarks that make this concrete? (I vaguely recall benchmarks that covered reflow, but it's a vague memory).
Edit: ah, posting the same link at the same time... But I think the best tip is: be shallow. A lot of things trigger reflow but DOM-depth is causing slow reflows.
For example, many infinite-scroll pages add a small amount of content to the DOM and then ask, "Did I fill the page enough?" by asking for the new height of the page. Each time they do that it requires a reflow where the browser recalculates the height of the page. When the added content is small it may take four or five trips through this loop to feed enough content into the page. A better alternative performance-wise would be to make each chunk of added content a fixed height. That way it's easy to do the math inside your own code, add four or five chunks, and the browser will do a single reflow at the end.
If you look at the "flat" designs that are becoming common in operating systems and apps, they perform well in these situations because they are very regular and easy to compute. Things like rounded corners, transparency, and drop shadows all make pages slower to render.
> This isn't really hard, you just make sure that while you are performing an animation or within a game level you don't make any allocations. The GC is unlikely to kick in and your performance will be predictable and fast. ARC on the other hand doesn't allow you to do that since ARC instantly deallocates an object you finished working with.
I don't understand this. All the strategies one might use to avoid allocations in performance-critical code under GC (pooling resources, or whatever) are also available under ARC.
The difference is that if the way I use memory causes performance issues without GC, it will be much more reliably reproducible than with GC.
It's a valid point that almost nobody's writing 50-second raytracing routines in JavaScript, but it's trivial to run code that's executed in the background without freezing your app, by repeatedly calling it with setTimeout(). Just make sure that any "tick" of your code runs in under 30ms or so (although, depending on your task, that may not be so trivial).
[1] - http://stackoverflow.com/questions/5943949/late-binding-vs-d... [2] - http://www.gnu.org/software/gnustep/resources/ObjCFun.html [3] - http://developer.apple.com/library/ios/#documentation/genera... [4] - http://stackoverflow.com/questions/9470824/dynamic-binding-l...
I've always been interested in whether this is done in various managed languages. Since I never know the answer, one pattern I've taken to is to allocate memory in static const/final fields that I would normally put on the stack in C, instead of doing a heap allocation to a variable whose scope is completely within one function. You have to watch out for some gotchas like recursing into the same function, but overall it's a pretty painless and clear pattern for me. Multiple functions can all share the same static memory too.
Not that I'm religious about this design pattern, but it's something I try to do in performance-critical code.
I am still curious what Google is going to do with Java and Dalvik, as the whole thing seems to be frozen since the whole process with Oracle, and they only add new APIs.
The last two Google IOs did not have any Dalvik related talk.
Android is, still, a very lean project inside and lean corporate structure. If it's a third of the way down the priority list, it probably ain't happening.
Well the people doing games already gave up on it since the NDK is available, but given that Google gives a second class treatment to the folks using the NDK, it would be nice if they cared to improve the JIT.
Sure we can find how way around what is provided, but the performance story could be made better, specially when compared what is given to us in iOS and Windows Phone 8 environments.
That seems like a big 'just', at least in a multi-threaded application...
Some numbers to back this up would be nice. Apple has been optimizing the hell out of Objective-C and I think it has a method invocation down to like 10 instructions or so.