Превышаем скоросные лимиты с Angular 2

Post on 14-Apr-2017

66 views 0 download

Transcript of Превышаем скоросные лимиты с Angular 2

Превышаем скоростные лимиты с Angular 2

Алексей Охрименко

IPONWEB

1

#rtb_techday

2

#rtb_techday

3

#rtb_techday

4

#rtb_techday

5

Алексей Охрименко

Twitter: @Ai_boy

6

7

IPONWEB

RTBDSPSSP

8

последствия превышения скорости (в реальной

жизни)

9

последствия превышения скорости*

* - поищите в Google Image - 4-ый результат

10

Всегда успеете…

11

А где тогда скорость превышать?

12

13

14

Angular 2

16

import { Component } from '@angular/core';

@Component({ moduleId: module.id, selector: 'project-name-app', template: ` <h1 (click)='onClick()'> {{title}} </h1> `, styleUrls: ['project-name.component.css'] }) export class PROJECTNAMEAppComponent { title = 'project-name works!'; }

17

import { Component } from '@angular/core';

@Component({ moduleId: module.id, selector: 'project-name-app', template: ` <h1 (click)='onClick()'> {{title}} </h1> `, styleUrls: ['project-name.component.css'] }) export class PROJECTNAMEAppComponent { title = 'project-name works!'; }

18

import { Component } from '@angular/core';

@Component({ moduleId: module.id, selector: 'project-name-app', template: ` <h1 (click)='onClick()'> {{title}} </h1> `, styleUrls: ['project-name.component.css'] }) export class PROJECTNAMEAppComponent { title = 'project-name works!'; }

Angular 2, Angular 2… нас и [НАШ_FRAMEWORK]

неплохо кормит

19

20

А что значит «скорость»?

21

Скорость загрузки

22

Скорость загрузки

Размер

23

Скорость загрузки

Размер

LazyLoading

24

Скорость загрузки

Скорость работы

Размер

LazyLoading

25

Скорость загрузки

Скорость работы

Размер

LazyLoading

Обьем работы

26

Скорость загрузки

Скорость работы

Размер

LazyLoading

Обьем работы Производительность

27

Скорость загрузки

Скорость работы

Размер

LazyLoading

Обьем работы Производительность

Память

28

Скорость загрузки

Скорость работы

Размер

LazyLoading

Обьем работы

Многопоточность

Производительность

Память

29

Скорость загрузки

Скорость работы

Размер

LazyLoading

Обьем работы

Многопоточность

Производительность

Память

30

Скорость работы

31

https://github.com/krausest/js-framework-benchmark

https://github.com/mathieuancelin/js-repaint-perfs

32

33

Кол-во перерисовок в секунду (больше лучше)

Angular 1

Angular 2

React

Elm

0 9 18 27 36

34

Наша цель … 90 RR

35

Кол-во перерисовок в секунду (больше лучше)

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

36

Старая версия Angular 2

37

Alpha 44

38

Alpha 44 —> v2.1.2

39

Alpha 44

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

40

v2.1.2

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

41

v2.1.2

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

42

На самом деле все просто…

43

Angular 2 Performance Checklist

44

import {enableProdMode} from '@angular/core';

enableProdMode();

45

300% в EdgeenableProdMode()

46

Alpha 44

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

47

v2.1.2 + enableProdMod()

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

48

function getData(keepIdentity) { var oldData = data; if (!keepIdentity) { // reset for each tick data = []; for (var i = 1; i <= ENV.rows; i++) { data.push({ … }); data.push({ … }); } } }

49

@Page({ template: ` <div *ngFor="let post of posts;trackBy:identify"> {{post.data}} </div> ` }) export class SomeConponent { identify(index,item){ return post.id } }

50

@Page({ template: ` <div *ngFor="let post of posts;trackBy:identify"> {{post.data}} </div> ` }) export class SomeConponent { identify(index,item){ return post.id } }

51

v2.1.2 + enableProdMod()

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

52

trackBy

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

53

AOTAhead Of Time template compilation

54

55

56

Angular CLI

ng serve ——aotng build ——aot

57

trackBy

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

58

AOT

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

59

WebWorkers

60

import {bootstrapWorkerUi} from '@angular/platform-webworker'; import {enableProdMode} from '@angular/core';

export function main() { enableProdMode(); bootstrapWorkerUi('loader.js'); }

61

import {bootstrapWorkerUi} from '@angular/platform-webworker'; import {enableProdMode} from '@angular/core';

export function main() { enableProdMode(); bootstrapWorkerUi('loader.js'); }

62

@NgModule({ imports: [WorkerAppModule], bootstrap: [AppComponent], declarations: [AppComponent] }) class WebWorkerModule {}

export function main() { enableProdMode(); platformWorkerAppDynamic().bootstrapModule(WebWorkerModule); }

63

@NgModule({ imports: [WorkerAppModule], bootstrap: [AppComponent], declarations: [AppComponent] }) class WebWorkerModule {}

export function main() { enableProdMode(); platformWorkerAppDynamic().bootstrapModule(WebWorkerModule); }

64

AOT

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

65

webWorkers

Angular 2

Target

0 10 20 30 40 50 60 70 80 90

66

67

Кол-во перерисовок в секунду (больше лучше)

Angular 1

Angular 2

React

Elm

0 10 20 30 40 50 60 70 80 90

68

Еще раз• enableProd() • trackBy • AOT • WebWorkers

69

Заглянем под капот

70

Scott Hanselman

71

ZoneJs

72

73

const http = require('http');

const hostname = '127.0.0.1'; const port = 3000;

const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World'); });

server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });

74

75

process.on('uncaughtException', (err) => { console.log(`Caught exception: ${err}`); });

76

77

Zone.current.fork({}).run(function () { Zone.current.inTheZone = true; setTimeout(someCallback, 0); });

function someCallback() { console.log(Zone.current.inTheZone); }

setTimeout(someCallback, 0);

78

Zone.current.fork({}).run(function () { Zone.current.inTheZone = true; setTimeout(someCallback, 0); });

function someCallback() { console.log(Zone.current.inTheZone); }

setTimeout(someCallback, 0);

79

Zone.current.fork({}).run(function () { Zone.current.inTheZone = true; setTimeout(someCallback, 0); });

function someCallback() { console.log(Zone.current.inTheZone); }

setTimeout(someCallback, 0);

80

Zone.current.fork({}).run(function () { Zone.current.inTheZone = true; setTimeout(someCallback, 0); });

function someCallback() { console.log(Zone.current.inTheZone); }

setTimeout(someCallback, 0);

81

Zone.current.fork({}).run(function () { Zone.current.inTheZone = true; setTimeout(someCallback, 0); });

function someCallback() { console.log(Zone.current.inTheZone);//TRUE }

setTimeout(someCallback, 0);

82

Zone.current.fork({}).run(function () { Zone.current.inTheZone = true; setTimeout(someCallback, 0); });

function someCallback() { console.log(Zone.current.inTheZone); }

setTimeout(someCallback, 0);

83

Zone.current.fork({}).run(function () { Zone.current.inTheZone = true; setTimeout(someCallback, 0); });

function someCallback() { console.log(Zone.current.inTheZone);//FALSE }

setTimeout(someCallback, 0);

84

Change Detection

85

86

87

88

89

90

// very simplified version of actual source class ApplicationRef {

changeDetectorRefs:ChangeDetectorRef[] = [];

constructor(private zone: NgZone) { this.zone.onTurnDone .subscribe(() => {

this.zone.run(() => this.tick() });

}

tick() { this.changeDetectorRefs .forEach((ref) => ref.detectChanges()); } }

91

// very simplified version of actual source class ApplicationRef {

changeDetectorRefs:ChangeDetectorRef[] = [];

constructor(private zone: NgZone) { this.zone.onTurnDone .subscribe(() => {

this.zone.run(() => this.tick() });

}

tick() { this.changeDetectorRefs .forEach((ref) => ref.detectChanges()); } }

92

// very simplified version of actual source class ApplicationRef {

changeDetectorRefs:ChangeDetectorRef[] = [];

constructor(private zone: NgZone) { this.zone.onTurnDone .subscribe(() => {

this.zone.run(() => this.tick() });

}

tick() { this.changeDetectorRefs .forEach((ref) => ref.detectChanges()); } }

93

// very simplified version of actual source class ApplicationRef {

changeDetectorRefs:ChangeDetectorRef[] = [];

constructor(private zone: NgZone) { this.zone.onTurnDone .subscribe(() => {

this.zone.run(() => this.tick() });

}

tick() { this.changeDetectorRefs .forEach((ref) => ref.detectChanges()); } }

94

95

@Component({ template: '<v-card [vData]="vData"></v-card>' }) class VCardApp {

constructor() { this.vData = { name: 'Christoph Burgdorf', email: 'christoph@thoughtram.io' } }

changeData() { this.vData.name = 'Pascal Precht'; } }

96

@Component({ template: ` <h2>{{vData.name}}</h2> <span>{{vData.email}}</span> ` }) class VCardCmp { @Input() vData; }

97

@Component({ template: '<v-card [vData]="vData"></v-card>' }) class VCardApp {

constructor() { this.vData = { name: 'Christoph Burgdorf', email: 'christoph@thoughtram.io' } }

changeData() { this.vData = { name: 'Pascal Precht' }; } }

98

@Component({ template: ` <h2>{{vData.name}}</h2> <span>{{vData.email}}</span> `, changeDetection: ChangeDetectionStrategy.OnPush }) class VCardCmp { @Input() vData; }

99

100

Управляем Zone и CD

101

constructor(private zone: NgZone) {}

102

processOutsideAngularZone() { this.progress = 0; this.zone.runOutsideAngular(() => { this.increaseProgress(() => { this.zone.run(() => { console.log('Outside Done!'); }); }); }); }

103

processOutsideAngularZone() { this.progress = 0; this.zone.runOutsideAngular(() => { this.increaseProgress(() => { this.zone.run(() => { console.log('Outside Done!'); }); }); }); }

104

constructor(private cd: ChangeDetectorRef) {}

105

ngOnInit() { this.addItemStream.subscribe(() => { this.counter++; // application state changed this.cd.markForCheck(); // marks path }) } }

106

А можно как-то попроще?

107

Redux

108

ng2-redux ngrx/store

109

Mobx

110

ng2-mobx

111

112

Улучшаем Perceived Performance

•Увеличивая реальную производительность

113

Улучшаем Perceived Performance

•Увеличивая реальную производительность •Замедляя реальную производительность

114

Улучшаем Perceived Performance•Увеличивая реальную производительность •Замедляя реальную производительность •Грамотно перераспределяя нагрузку и ресурсы

115

116

FRPfunctional reactive programming

117

this.form.valueChanges .filter((value) => this.form.valid) .switchMap((value) => { return http.post(‘/api’, value) });

118

this.form.valueChanges .debounce(500) .filter((value) => this.form.valid) .switchMap((value) => { return http.post(‘/api’, value) });

119

this.form.valueChanges .debounce(500) .distinctUntilChanged() .filter((value) => this.form.valid) .switchMap((value) => { return http.post(‘/api’, value) });

120

this.form.valueChanges .debounce(500) .distinctUntilChanged() .filter((value) => this.form.valid) .switchMap((value) => { return http.post(‘/api’, value) }).retryWhen(attempts => attempts .zip(Observable.range(1, 3), (_, i) => i) .flatMap((i: number) => { return Observable.timer(i * 1000); }) ))

121

122

Алексей ОхрименкоTwitter: @Ai_boy

IPONWEB

http://bit.ly/2eMOBjm

123