Titanium Mobile: flexibility vs. performance

50
Olivier Morandi Appcelerator Titanium Mobile FLEXIBILITY VS PERFORMANCE

Transcript of Titanium Mobile: flexibility vs. performance

Page 1: Titanium Mobile: flexibility vs. performance

Olivier Morandi

Appcelerator Titanium Mobile

FLEXIBILITYVS

PERFORMANCE

Page 2: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

$ whoami

Olivier MorandiSoftware engineer

http://[email protected]@olivier_morandihttps://github.com/omorandi

2

Page 3: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Titanium Mobile• Rapid development & prototyping tool• Single high level language: JS• Multiple deployment platforms (iOS, Android, ...)• We can leverage an ever growing set of JS

libraries and modules (web, node.js, etc.)• Possibility to extend the framework with native

modules

3

Page 4: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Titanium Apps are NATIVE

Can we also expect a native User Experience?

4

Page 5: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Titanium 2.0• Improved stability• Improved platform parity• Improved performance• Appcelerator Cloud Services

5

Page 6: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Some Mobile Dev Tools

6

RubyMotion

1

TitaniumMobile

Mobile Web

PhoneGap

+ High Level Language+ High Level APIs + Dynamic updates+ Cross Platform

+ Execution Speed+ Native UX+ Native capabilities

Flexibility → ∞

0 ← Performance

Page 7: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Some Mobile Dev Tools

6

RubyMotion

1

TitaniumMobile

Mobile Web

PhoneGap

+ High Level Language+ High Level APIs + Dynamic updates+ Cross Platform

+ Execution Speed+ Native UX+ Native capabilities

?

?

Flexibility → ∞

0 ← Performance

Page 8: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

An example: Ti.UI.TableView

7

Page 9: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Common Problems• Slow transitions– the table view takes ages to show up

• Choppy scrolling– Everybody wants super-slick animations, isn’t it?

8

Page 10: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Towards Increased Performance• Understand the tools, then:

9

Measure

Learn

Optimize

Page 11: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Runtime Environment

10

Titanium Modules

JS APP

Parser

Interpreter

IOS SDK

Bytecodegen

JavaScriptCore

Titanium Modules

JS APP

Parser

Native Code

ANDROID SDK

Native Code Gen

V8

OPT

Page 12: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Runtime Environment

10

Titanium Modules

JS APP

Parser

Interpreter

IOS SDK

Bytecodegen

JavaScriptCore

Titanium Modules

JS APP

Parser

Native Code

ANDROID SDK

Native Code Gen

V8

NO JIT OPT

Page 13: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Runtime Environment

10

Titanium Modules

JS APP

Parser

Interpreter

IOS SDK

Bytecodegen

JavaScriptCore

Titanium Modules

JS APP

Parser

Native Code

ANDROID SDK

Native Code Gen

V8

NO JIT OPT

Page 14: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Runtime Environment

10

Titanium Modules

JS APP

Parser

Interpreter

IOS SDK

Bytecodegen

JavaScriptCore

Titanium Modules

JS APP

Parser

Native Code

ANDROID SDK

Native Code Gen

V8

NO JIT OPT

Page 15: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Measure: which runs faster?

11

var rows = [];for (var r = 0; r < array.length; r++) { rows.push({title: array[r].info});}

var rows = [];for (var r = 0; r < array.length; r++) { rows.push(processRow(array[r]));}

var len = array.length;var rows = [];for (var r = 0; r < len; r++) { rows.push({title: array[r].info});}

var len = array.length;var rows = [];for (var r = 0; r < len; r++) { rows.push(processRow(array[r]));}

var rows = array.map(processRow);

function processRow(row) { return {title: row.info};}

1 2

3 4

5

Page 16: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Tests on iPhone 4

12

1

10

100

1000

100 1000 10000

ms

Number of Rows

1) for + inline 2) for + funct3) for + inline + cache len 4) for + funct + cache len5) map

Page 17: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Which runs faster?

13

var rows = [];for (var r = 0; r < array.length; r++) { rows.push(Ti.UI.createTableViewRow(

{title: array[r].info}));}

var rows = [];for (var r = 0; r < array.length; r++) { rows.push(processRow2(array[r]));}

var len = array.length;var rows = [];for (var r = 0; r < len; r++) { rows.push(Ti.UI.createTableViewRow( {title: array[r].info}));}

var len = array.length;var rows = [];for (var r = 0; r < len; r++) { rows.push(processRow2(array[r]));}

var rows = array.map(processRow2);

function processRow2(row) { return Ti.UI.createTableViewRow({title: row.info});}

1 2

3 4

5

Page 18: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Tests on iPhone 4

14

Number of rows

ms

1

10

100

1000

10000

10 100 1000

1) for + inline 2) for + funct3) for + inline + cache len 4) for + funct + cache len5) map

Page 19: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Tests on iPhone 4

14

Number of rows

ms

1

10

100

1000

10000

10 100 1000

1) for + inline 2) for + funct3) for + inline + cache len 4) for + funct + cache len5) map

DON’T TRUST THESE

RESULTS!!!

Page 20: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

WHY?• They’re not generalizable• Your code won’t look like the one presented here• Do your own measurements

15

Page 21: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Is table creation slow?• Obtaining some rough figures:

16

var start = new Date().getTime();

//your code goes here

var end = new Date().getTime();Ti.API.info('elapsed ms: ' + (end - start));

Page 22: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Are there more accurate tools?• mmm.... AFAIK NO!

17

Page 23: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Android DDMS + Traceview

18

Page 24: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Android DDMS + Traceview

18

WHERE’S MY JS???

Page 25: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Xcode Instruments: profiler tool

19

Page 26: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Xcode Instruments: profiler tool

19

JS code hidden here

Page 27: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Titanium Profiler... still to come

20

Page 28: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Titanium Profiler (iOS only)• Custom version of the Ti JavaScriptCore library• Work in progress• Some info here

http://titaniumninja.com/profiling-ti-mobile-apps-is-it-possible/

• Will be possibly integrated in Ti Mobile• Stay tuned on

http://titaniumninja.com/

21

Page 29: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Is table creation REALLY slow?• Try optimizing the row creation loop body• Implement Lazy loading– Initialize the table with fewer rows and show it

immediately–Meantime continue creating the remaining rows and

update the table with the complete row set

22

Page 30: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Wanna smooth scrolling?

23

Page 31: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Instruments: Core Animation

24

Page 32: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Tables with complex rows are slow

25

~35-40 FPSExpected: ~60 FPS

Page 33: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

1. Blended layers

26

These labels are transparent, even if we set the background color, or a background image

Page 34: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

What can we do?

27

-(UILabel*)label{! if (label==nil)! { label = [[UILabel alloc] initWithFrame:CGRectZero]; label.backgroundColor = [UIColor whiteColor]; label.numberOfLines = 0; [self addSubview:label]; label.opaque = YES; self.opaque = YES; self.backgroundColor = [UIColor whiteColor];! }! return label;} TiUILabel.m:104

Discussion (Cfr. UIView Reference)“The opaque property provides a hint to the drawing system as to how it should treat the view. If set to YES, the drawing system treats the view as fully opaque, which allows the drawing system to optimize some drawing operations and improve performance”

Page 35: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

What can we do?

27

-(UILabel*)label{! if (label==nil)! { label = [[UILabel alloc] initWithFrame:CGRectZero]; label.backgroundColor = [UIColor whiteColor]; label.numberOfLines = 0; [self addSubview:label]; label.opaque = YES; self.opaque = YES; self.backgroundColor = [UIColor whiteColor];! }! return label;} TiUILabel.m:104

NOT A FIX!!!

Discussion (Cfr. UIView Reference)“The opaque property provides a hint to the drawing system as to how it should treat the view. If set to YES, the drawing system treats the view as fully opaque, which allows the drawing system to optimize some drawing operations and improve performance”

Page 36: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Result

28

~45-50 FPS

Page 37: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

2. Offscreen rendered layers

29

Page 38: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Solution• Don’t use rounded corners (borderRadius)• Use an image mask instead

30

var img = Ti.UI.createMaskedImage({ mask : 'mask.png',// alpha mask image : myPicture,//image to mask mode : Ti.UI.iOS.BLEND_MODE_SCREEN});

Page 39: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

What about FPSs?

31

~55-60 FPS(Just using image masks)

Page 40: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Not satisfied? Going fully native• Let’s create a custom optimized UITableView• We’ll expose it through a native module

32

Page 41: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

API for the custom view• API

• createMessagesView(properties);• setMessages([]messages);• insert(message);• addEventListener(‘click’, callback);

• Config

33

{ rowBackgroundColor: '#efefef', nameColorIfMe: '#191919', nameColorIfOther: '#8f032c', …}

Page 42: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

API for the custom view• API

• createMessagesView(properties);• setMessages([]messages);• insert(message);• addEventListener(‘click’, callback);

• Config

33

{ rowBackgroundColor: '#efefef', nameColorIfMe: '#191919', nameColorIfOther: '#8f032c', …}

DECREASED FLEXIBILITY

Page 43: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Message model

34

{ isMe: true, name: "Vincent", picture: "vin.png", body: "It's not. It's the same ballpark.", date: 12394838299 //unix timestamp},

Page 44: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

A single row

35

picture

name

body

date

Click

Page 45: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Traditional UITableViewCell

36

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {! ! UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MessageCell"];! if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault

reuseIdentifier:@"MessageCell"] autorelease]; UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(75.0, 25.0, 120.0, 18.0)]; nameLabel.font = [UIFont boldSystemFontOfSize:16.0]; nameLabel.textAlignment = UITextAlignmentLeft;! ! nameLabel.backgroundColor = rowBackgroundColor;! ! [cell.contentView addSubview:nameLabel]; } else { //... }

Message *msg = [messages objectAtIndex:(indexPath.row)]; BOOL isMe = [TiUtils boolValue:[dict objectForKey:@"isMe"]]; nameLabel.textColor = isMe ? nameColorIfMe : nameColorIfOther; //...

Page 46: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Not fast enough? Use FastCells

37

- (void) drawContentView:(CGRect)rect { if (message == nil) return; CGContextRef context = UIGraphicsGetCurrentContext(); CGContextClearRect(context, rect); CGFloat max_width = self.contentView.frame.size.width;

if (message.isMe) [nameColorIfMe set]; else [nameColorIfOther set]; [message.name drawInRect:CGRectMake(userInfoLeft, userInfoTop, rectWidth(userInfoLeft,

userInfoRight, max_width), userInfoHeight) withFont:bigBoldFont lineBreakMode:UILineBreakModeTailTruncation];

//...}

Low level drawing primitives

Page 47: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Concluding remarks on Titanium• Is it worth it?• Does it really speeds up development?• Is developing with Titanium “better” or “worse”

than making parallel per-platform developments?

38

Page 48: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Where’s the value?

39

• Quick prototyping iterations• Single complex business-logic core• Cross platform deployment• Maintainability of the project in the long term

Page 49: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Some interesting reads• JavaScriptCore, the WebKit JS implementation - http://wingolog.org/archives/

2011/10/28/javascriptcore-the-webkit-js-implementation• v8: a tale of two compilers - http://wingolog.org/archives/2011/07/05/v8-a-tale-

of-two-compilers• JSC v/s V8 performance on ARM - http://xc0ffee.wordpress.com/2011/09/07/

webkit-gtk-jsc-vs-v8-performance-on-arm/• The Future of JavaScript Engines: Replace Them With JavaScript Compilers -

http://shorestreet.com/node/43• Optimisation: don't waste your time - http://www.scirra.com/blog/83/

optimisation-dont-waste-your-time• Guidelines for JavaScript Programs: Are They Still Necessary? - http://www.inf.u-

szeged.hu/~akiss/pub/pdf/herczeg_guidelines.pdf

40

Page 50: Titanium Mobile: flexibility vs. performance

Appcelerator Titanium - Flexibility vs. Performance

Thank YOU!

41

Any question?