SlideShare uma empresa Scribd logo
1 de 155
Baixar para ler offline
Николай Лихогруд
Руководитель группы разработки Яндекс.Карт для iOS
Оптимизация времени
запуска iOS-приложений
It's really clear that the
most precious resource
we all have is time
Steve Jobs
Зачем сокращать время запуска?
4
Важное конкурентное преимущество
Зачем сокращать время запуска?
4
Важное конкурентное преимущество
Влияет на retention, настроение пользователей, оценку в сторе
Зачем сокращать время запуска?
4
Важное конкурентное преимущество
Влияет на retention, настроение пользователей, оценку в сторе
Максимальное время запуска - 20s, при превышении система
останавливает загрузку
Зачем сокращать время запуска?
4
Важное конкурентное преимущество
Влияет на retention, настроение пользователей, оценку в сторе
Максимальное время запуска - 20s, при превышении система
останавливает загрузку
› Актуально для слабых устройств
Зачем сокращать время запуска?
4
Актуальность
5
Множество приложений и фреймворков переходят на swift
Актуальность
5
Множество приложений и фреймворков переходят на swift
Swift нельзя компилировать в статические библиотеки
Актуальность
5
Множество приложений и фреймворков переходят на swift
Swift нельзя компилировать в статические библиотеки
Динамические библиотеки грузятся долго
Актуальность
5
Множество приложений и фреймворков переходят на swift
Swift нельзя компилировать в статические библиотеки
Динамические библиотеки грузятся долго
WWDC 2016: Optimizing App Startup Time
Актуальность
5
План
6
1. Замеры времени запуска

План
6
1. Замеры времени запуска

2. Оптимизация pre-main

План
6
1. Замеры времени запуска

2. Оптимизация pre-main

3. Оптимизация after-main

План
6
1. Замеры времени запуска

2. Оптимизация pre-main

3. Оптимизация after-main

4. Контроль результата
План
6
1. Замеры времени запуска
Что есть время запуска?
8
Что есть время запуска?
8
Что есть время запуска?
9
BestApp
Что есть время запуска?
10
Что есть время запуска?
11
Что есть время запуска?
12
BestApp
Полное время от нажатия на иконку до момента готовности к
использованию
Давно не запускалось или
не запускалось после
перезагрузки телефона
Холодный и теплый запуски
13
iPhone 5s
Теплый Холодный
2 333мс
1 203мс
pre-main
14
1. Динамические библиотеки
pre-main
14
1. Динамические библиотеки
2. Исправление указателей, связывание
pre-main
14
1. Динамические библиотеки
2. Исправление указателей, связывание
3. Objective-C контекст
pre-main
14
1. Динамические библиотеки
2. Исправление указателей, связывание
3. Objective-C контекст
4. +load, c++ globals
pre-main
14
Холодный запуск и pre-main
15
Холодный
Теплый
0 200 400 600 800
dylib loading time rebase/binding time
ObjC setup time initializer time
0.11s
0.73s
Полное время от нажатия на иконку до момента готовности к
использованию
Что замерять?
16
Полное время от нажатия на иконку до момента готовности к
использованию
› Замерять холодные и теплые запуски
Что замерять?
16
Полное время от нажатия на иконку до момента готовности к
использованию
› Замерять холодные и теплые запуски
› Учитывать pre-main
Что замерять?
16
Замер pre-main
17
DYLD_PRINT_STATISTICS
Total pre-main time: 677.82 milliseconds (100.0%)
dylib loading time: 520.33 milliseconds (76.7%)
rebase/binding time: 54.31 milliseconds (8.0%)
ObjC setup time: 43.16 milliseconds (6.3%)
initializer time: 59.99 milliseconds (8.8%)
slowest intializers :
libSystem.B.dylib : 4.35 milliseconds (0.6%)
TestApp : 74.83 milliseconds (11.0%)
DYLD_PRINT_STATISTICS
18
Total pre-main time: 677.82 milliseconds (100.0%)
dylib loading time: 520.33 milliseconds (76.7%)
rebase/binding time: 54.31 milliseconds (8.0%)
ObjC setup time: 43.16 milliseconds (6.3%)
initializer time: 59.99 milliseconds (8.8%)
slowest intializers :
libSystem.B.dylib : 4.35 milliseconds (0.6%)
TestApp : 74.83 milliseconds (11.0%)
DYLD_PRINT_STATISTICS
18
Total pre-main time: 677.82 milliseconds (100.0%)
dylib loading time: 520.33 milliseconds (76.7%)
rebase/binding time: 54.31 milliseconds (8.0%)
ObjC setup time: 43.16 milliseconds (6.3%)
initializer time: 59.99 milliseconds (8.8%)
slowest intializers :
libSystem.B.dylib : 4.35 milliseconds (0.6%)
TestApp : 74.83 milliseconds (11.0%)
DYLD_PRINT_STATISTICS
18
Total pre-main time: 677.82 milliseconds (100.0%)
dylib loading time: 520.33 milliseconds (76.7%)
rebase/binding time: 54.31 milliseconds (8.0%)
ObjC setup time: 43.16 milliseconds (6.3%)
initializer time: 59.99 milliseconds (8.8%)
slowest intializers :
libSystem.B.dylib : 4.35 milliseconds (0.6%)
TestApp : 74.83 milliseconds (11.0%)
DYLD_PRINT_STATISTICS
18
Total pre-main time: 677.82 milliseconds (100.0%)
dylib loading time: 520.33 milliseconds (76.7%)
rebase/binding time: 54.31 milliseconds (8.0%)
ObjC setup time: 43.16 milliseconds (6.3%)
initializer time: 59.99 milliseconds (8.8%)
slowest intializers :
libSystem.B.dylib : 4.35 milliseconds (0.6%)
TestApp : 74.83 milliseconds (11.0%)
DYLD_PRINT_STATISTICS
18
Total pre-main time: 677.82 milliseconds (100.0%)
dylib loading time: 520.33 milliseconds (76.7%)
rebase/binding time: 54.31 milliseconds (8.0%)
ObjC setup time: 43.16 milliseconds (6.3%)
initializer time: 59.99 milliseconds (8.8%)
slowest intializers :
libSystem.B.dylib : 4.35 milliseconds (0.6%)
TestApp : 74.83 milliseconds (11.0%)
DYLD_PRINT_STATISTICS
18
Замер after-main
19
с начала didFinishLaunching
Замер after-main
19
с начала didFinishLaunching
Замер after-main
19
› не учитывается время создания
UIApplication, UIApplicationDelegate
с начала didFinishLaunching
Замер after-main
19
с начала main
› не учитывается время создания
UIApplication, UIApplicationDelegate
Замер after-main
20
// main.swift
let start = Date().timeIntervalSince1970
let argc = Int(CommandLine.argc)
fileprivate let argv =
UnsafeMutableRawPointer(CommandLine.unsafeArgv)
.bindMemory(to: UnsafeMutablePointer<Int8>.self, capacity: argc)
UIApplicationMain(CommandLine.argc, argv, nil, NSStringFromClass(AppDelegate.self))
Замер after-main
20
// main.swift
let start = Date().timeIntervalSince1970
let argc = Int(CommandLine.argc)
fileprivate let argv =
UnsafeMutableRawPointer(CommandLine.unsafeArgv)
.bindMemory(to: UnsafeMutablePointer<Int8>.self, capacity: argc)
UIApplicationMain(CommandLine.argc, argv, nil, NSStringFromClass(AppDelegate.self))
Замер after-main
20
// main.swift
let start = Date().timeIntervalSince1970
let argc = Int(CommandLine.argc)
fileprivate let argv =
UnsafeMutableRawPointer(CommandLine.unsafeArgv)
.bindMemory(to: UnsafeMutablePointer<Int8>.self, capacity: argc)
UIApplicationMain(CommandLine.argc, argv, nil, NSStringFromClass(AppDelegate.self))
Важность множественных запусков
21
0
325
650
975
1300
1 2 3 4 6 7 8 9 10 11 12 13 15 16 17 18 19 20
21%
Автоматические запуски
22
libimobiledevice
› прямое взаимодействие с устройством
› не требует jailbreak
Автоматические запуски
22
libimobiledevice
23
$idevice_id -l
$ideviceinstaller -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 -i SomeApp.app
$idevicedebug -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 run com.some.app
$idevicediagnostics restart
libimobiledevice
23
$idevice_id -l
$ideviceinstaller -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 -i SomeApp.app
$idevicedebug -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 run com.some.app
$idevicediagnostics restart
libimobiledevice
23
$idevice_id -l
$ideviceinstaller -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 -i SomeApp.app
$idevicedebug -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 run com.some.app
$idevicediagnostics restart
libimobiledevice
23
$idevice_id -l
$ideviceinstaller -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 -i SomeApp.app
$idevicedebug -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 run com.some.app
$idevicediagnostics restart
libimobiledevice
23
$idevice_id -l
$ideviceinstaller -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 -i SomeApp.app
$idevicedebug -u e1bbc7f0353933938929c3279fc6b7f51fac1c02 run com.some.app
$idevicediagnostics restart
libimobiledevice + DYLD_PRINT_STATISTICS
24
$idevicedebug -e DYLD_PRINT_STATISTICS=1 
-u e1bbc7f0353933938929c3279fc6b7f51fac1c02 run test.app
Total pre-main time: 52.85 milliseconds (100.0%)
dylib loading time: 7.21 milliseconds (13.6%)
rebase/binding time: 3.22 milliseconds (6.1%)
...
Релизная конфигурация с оптимизациями
› отключены ассерты и функциональность для дебага
exit(0) после завершения загрузки, если

processInfo.environment["DYLD_PRINT_STATISTICS"] != nil
Сборка для тестов
25
На каждой итерации:
1. idevicediagnostics restart, дождаться загрузки
2. idevicedebug run - холодный запуск
3. idevicedebug run - теплый запуск
4. Обработать вывод, сохранить лог
Организация скрипта
26
pre-main: перезагрузка vs переустановка
27
Перезагрузка
Переустановка
Теплый
0 225 450 675 900
dyld rebase&bind objc-setup initialization
На каждой итерации:
1. ideviceinstaller -i
2. idevicedebug run - холодный запуск
3. idevicedebug run - теплый запуск
4. Обработать вывод, сохранить лог
Организация скрипта
28
Запуски на разных устройствах
29
Времязапуска,мс
iPhone 5 iPhone 5s iPhone 6 iPhone 6s iPhone 7
8851 014
1 930
2 333
4 470
533721
1 0881 203
2 195
Теплый Холодный
Пустой проект на swift
Пустой проект: Objective-C, iPhone 5s
31
Total pre-main time: 19.40 milliseconds (100.0%)
dylib loading time: 0.72 milliseconds (3.7%)
rebase/binding time: 1.14 milliseconds (5.8%)
ObjC setup time: 5.02 milliseconds (25.9%)
initializer time: 12.51 milliseconds (64.4%)
slowest intializers :
libSystem.B.dylib : 10.27 milliseconds (52.9%)
CoreFoundation : 0.66 milliseconds (3.4%)
Пустой проект: swift, iPhone 5s
Total pre-main time: 232.19 milliseconds (100.0%)
dylib loading time: 209.33 milliseconds (90.1%)
rebase/binding time: 7.98 milliseconds (3.4%)
ObjC setup time: 8.49 milliseconds (3.6%)
initializer time: 6.37 milliseconds (2.7%)
slowest intializers :
libSystem.B.dylib : 3.14 milliseconds (1.3%)
32
Пустой проект: swift, iPhone 5
33
Total pre-main time: 837.72 milliseconds (100.0%)
dylib loading time: 789.01 milliseconds (94.1%)
rebase/binding time: 15.41 milliseconds (1.8%)
ObjC setup time: 13.52 milliseconds (1.6%)
initializer time: 19.57 milliseconds (2.3%)
slowest intializers :
libSystem.B.dylib : 5.56 milliseconds (0.6%)
3.5x!
Список загружаемых библиотек
34
Бинарь приложения + 146 системных библиотек
Для проекта на swift дополнительно загружаются 9 библиотек из
бандла приложения, т.н. swift standard libraries
Список загружаемых библиотек
35
...
dyld: loaded: /private/var/containers/Bundle/Application/
AE358ED8-8FE3-4E90-88C8-FC602FDEA528/Empty.app/Frameworks/libswiftCore.dylib
dyld: loaded: /private/var/containers/Bundle/Application/
AE358ED8-8FE3-4E90-88C8-FC602FDEA528/Empty.app/Frameworks/libswiftUIKit.dylib
...
Swift продолжает активно
развиваться, не обеспечивает
обратную совместимость и не
является частью iOS
в отличие от ObjectiveC
Выводы
37
Загрузка системных библиотек оптимизирована
Выводы
37
Загрузка системных библиотек оптимизирована
Библиотеки из бандла приложения грузятся долго
Выводы
37
Загрузка системных библиотек оптимизирована
Библиотеки из бандла приложения грузятся долго
Любое приложения на swift будет грузиться на iPhone 5
минимум секунду при холодном запуске
Выводы
37
2. Оптимизация pre-main
Уменьшить число загружаемых динамических библиотек
Уменьшить использование Objective-C:
› Использовать swift
Перенести код +load в +initialize
Избавиться от статических с++ переменных со сложными
конструкторами
На что теоретически можно повлиять?
39
Уменьшить число загружаемых динамических библиотек
Уменьшить размер бинарного файла
› вынести символы в динамические библиотеки
› грузить лениво через dlopen
На что практически можно повлиять?*
40
*в готовом проекте на swift
41
...
use_frameworks!
target :OriginalApp do
pod 'AlamofireObjectMapper'
pod 'AlamofireImage'
pod 'FacebookLogin'
pod 'ObjectMapper'
pod 'PhoneNumberKit'
pod 'UIImageEffects'
pod 'pop'
pod 'KissXML'
pod 'MTDates'
pod 'Punycode-Cocoa'
pod 'YandexSpeechKit'
pod 'YandexMapKit'
end
Тестовый: Podfile
use_frameworks! из-за подов
на swift
много подов, собираемых из
исходных файлов
Тестовый: Функциональность
42
func handleDirectionsRequest(_ request: MKDirectionsRequest) {
//... использует MapKit из iOS SDK
}
func presentMap() {
//... использует YandexMapKit
}
func startSpeechRecognition() {
//... использует YandexSpeechKit и AVFoundation
}
Тестовый: Время запуска
43
Total pre-main time: 741.74 milliseconds (100.0%)
dylib loading time: 627.80 milliseconds (84.6%)
rebase/binding time: 28.87 milliseconds (3.8%)
ObjC setup time: 36.00 milliseconds (4.8%)
initializer time: 49.04 milliseconds (6.6%)
slowest intializers :
libSystem.B.dylib : 4.57 milliseconds (0.6%)
OriginalApp : 28.50 milliseconds (3.8%)
3x!!
Тестовый
Пустой
Добавились для каждого пода, собираемого из
исходных файлов
Добавились новые библиотеки swift standard
libraries
Динамические библиотеки
44
$gem install cocoapods-amimono
Плагин для cocoa pods
Патчит скрипты и xcconfig-и cocoapods:
› Линкует объектные файлы, оставшиеся после сборки подов,
непосредственно в бинарный файл приложения
cocoapods-amimono
45
cocoapods-amimono
46
...
plugin 'cocoapods-amimono'
use_frameworks!
target :StaticPodsApp do
pod ‘AlamofireObjectMapper’
...
pod 'YandexSpeechKit'
pod 'YandexMapKit'
end
post_install do |installer|
require 'cocoapods-amimono/patcher'
Amimono::Patcher.patch!(installer)
end
cocoapods-amimono
46
...
plugin 'cocoapods-amimono'
use_frameworks!
target :StaticPodsApp do
pod ‘AlamofireObjectMapper’
...
pod 'YandexSpeechKit'
pod 'YandexMapKit'
end
post_install do |installer|
require 'cocoapods-amimono/patcher'
Amimono::Patcher.patch!(installer)
end
Добавить plugin в Podfile
cocoapods-amimono
46
...
plugin 'cocoapods-amimono'
use_frameworks!
target :StaticPodsApp do
pod ‘AlamofireObjectMapper’
...
pod 'YandexSpeechKit'
pod 'YandexMapKit'
end
post_install do |installer|
require 'cocoapods-amimono/patcher'
Amimono::Patcher.patch!(installer)
end
Добавить plugin в Podfile
Добавить post_install в Podfile
Тестовый: Время запуска
47
Total pre-main time: 741.74 milliseconds (100.0%)
dylib loading time: 627.80 milliseconds (84.6%)
rebase/binding time: 28.87 milliseconds (3.8%)
ObjC setup time: 36.00 milliseconds (4.8%)
initializer time: 49.04 milliseconds (6.6%)
3x!!
оригинал
пустой
0 200 400 600 800
После cocoapods-amimono
48
Total pre-main time: 413.13 milliseconds (100.0%)
dylib loading time: 320.20 milliseconds (77.5%)
rebase/binding time: 28.71 milliseconds (6.9%)
ObjC setup time: 21.40 milliseconds (5.1%)
initializer time: 42.80 milliseconds (10.3%)
оригинал
aminomo
пустой
swift standard libraries
49
В пустом проекте
В тестовом проекте
swift standard libraries
50
В пустом проекте
В тестовом проекте
import CoreLocation в *.swift
#import <CoreLocation/CoreLocation.h> в bridging header
Приводят к добавлению libswiftCoreLocation.dylib в
бандл приложения
swift standard libraries
51
Некоторые библиотеки
SDK стоит
использовать только в
Objective C
*Пока библиотеки swift не станут частью системы
Обернуть CoreLocation в Objective-C с таким же интерфейсом,
но другим префиксом
› CLWLocationManger, CLWLocation, CLWHeading и т.д.
53
Objective C обертки
Обернуть CoreLocation в Objective-C с таким же интерфейсом,
но другим префиксом
› CLWLocationManger, CLWLocation, CLWHeading и т.д.
53
Objective C обертки
Использовать в swift только эти обертки
› Тогда libswiftCoreLocation.dylib не добавляется
swift standard libraries
54
import AVFoundation
libswiftAVFoundation.dylib
libswiftCoreMedia.dylib
libswiftCoreAudio.dylib
import MapKit
libswiftMapKit.dylib
libswiftCoreLocation.dylib
import CoreLocation
После cocoapods-amimono
55
Total pre-main time: 413.13 milliseconds (100.0%)
dylib loading time: 320.20 milliseconds (77.5%)
rebase/binding time: 28.71 milliseconds (6.9%)
ObjC setup time: 21.40 milliseconds (5.1%)
initializer time: 42.80 milliseconds (10.3%)
оригинал
aminomo
пустой
Objective C обертки
56
Total pre-main time: 294.30 milliseconds (100.0%)
dylib loading time: 210.64 milliseconds (71.5%)
rebase/binding time: 22.18 milliseconds (7.5%)
ObjC setup time: 19.08 milliseconds (6.4%)
initializer time: 42.38 milliseconds (14.4%)
оригинал
обертки
пустой
Objective C обертки
56
Total pre-main time: 294.30 milliseconds (100.0%)
dylib loading time: 210.64 milliseconds (71.5%)
rebase/binding time: 22.18 milliseconds (7.5%)
ObjC setup time: 19.08 milliseconds (6.4%)
initializer time: 42.38 milliseconds (14.4%)
оригинал
обертки
пустой
На старте должны
загружаться только
необходимые символы
Все остальное можно загружать лениво
В рассматриваемом примере карта и распознавание звука не
включаются на старте
› Можно конвертировать YandexSpeechKit и YandexMapKit в
динамические библиотеки и лениво загружать через dlopen
Неизбежно уменьшит rebase&bind, obj startup, initialization
Уменьшение размера бинарного файла
58
Создать отдельный таргет «Cocoa Touch Framework»
В созданный таргет
› Добавить pod со статической библиотекой в Podfile
› Прилинковать недостающие зависимости
static lib -> dynamic lib
59
Для основного таргета
› Убрать pod со статической библиотекой в Podfile
› Добавить новый framework в «embedded binaries»
› Перенести ресурсы
› Сделать Objective-C обертки для ленивой загрузки символов
библиотеки
static lib -> dynamic lib
60
dlopen: загрузка библиотеки
61
#import <dlfcn.h>
NSString *frameworksPath = [[NSBundle mainBundle] privateFrameworksPath];
NSString *dyLib = @"SomeFramework.framework/SomeFramework";
NSString *path = [NSString stringWithFormat:@"%@/%@", frameworksPath, dyLib];
const char *pathStr = [path cStringUsingEncoding:NSASCIIStringEncoding];
void *handle = dlopen(pathStr, RTLD_LAZY);
dlopen: загрузка библиотеки
61
#import <dlfcn.h>
NSString *frameworksPath = [[NSBundle mainBundle] privateFrameworksPath];
NSString *dyLib = @"SomeFramework.framework/SomeFramework";
NSString *path = [NSString stringWithFormat:@"%@/%@", frameworksPath, dyLib];
const char *pathStr = [path cStringUsingEncoding:NSASCIIStringEncoding];
void *handle = dlopen(pathStr, RTLD_LAZY);
dlopen: загрузка библиотеки
61
#import <dlfcn.h>
NSString *frameworksPath = [[NSBundle mainBundle] privateFrameworksPath];
NSString *dyLib = @"SomeFramework.framework/SomeFramework";
NSString *path = [NSString stringWithFormat:@"%@/%@", frameworksPath, dyLib];
const char *pathStr = [path cStringUsingEncoding:NSASCIIStringEncoding];
void *handle = dlopen(pathStr, RTLD_LAZY);
dlsym: функции и глобальные переменные
62
void (*someFuncPtr)(int) = dlsym(handle, "SomeFunc");
someFuncPtr(5);
NSString *__autoreleasing *someGlobalVarPtr =
(NSString *__autoreleasing *)dlsym(handle, "SomeGlobalVar");
NSLog(@"%@", *someGlobalVarPtr);
dlsym: функции и глобальные переменные
62
void (*someFuncPtr)(int) = dlsym(handle, "SomeFunc");
someFuncPtr(5);
NSString *__autoreleasing *someGlobalVarPtr =
(NSString *__autoreleasing *)dlsym(handle, "SomeGlobalVar");
NSLog(@"%@", *someGlobalVarPtr);
dlsym: функции и глобальные переменные
62
void (*someFuncPtr)(int) = dlsym(handle, "SomeFunc");
someFuncPtr(5);
NSString *__autoreleasing *someGlobalVarPtr =
(NSString *__autoreleasing *)dlsym(handle, "SomeGlobalVar");
NSLog(@"%@", *someGlobalVarPtr);
dlsym: функции и глобальные переменные
62
void (*someFuncPtr)(int) = dlsym(handle, "SomeFunc");
someFuncPtr(5);
NSString *__autoreleasing *someGlobalVarPtr =
(NSString *__autoreleasing *)dlsym(handle, "SomeGlobalVar");
NSLog(@"%@", *someGlobalVarPtr);
dlsym: функции и глобальные переменные
62
void (*someFuncPtr)(int) = dlsym(handle, "SomeFunc");
someFuncPtr(5);
NSString *__autoreleasing *someGlobalVarPtr =
(NSString *__autoreleasing *)dlsym(handle, "SomeGlobalVar");
NSLog(@"%@", *someGlobalVarPtr);
dlsym: классы
63
#import <SomeFramework/SomeFramework.h>
Class someClass = (__bridge Class)dlsym(handle, "OBJC_CLASS_$_SomeClass");
SomeClass *someObj = [[someClass alloc] initWithParameter: param];
[someObj someMethod];
dlsym: классы
63
#import <SomeFramework/SomeFramework.h>
Class someClass = (__bridge Class)dlsym(handle, "OBJC_CLASS_$_SomeClass");
SomeClass *someObj = [[someClass alloc] initWithParameter: param];
[someObj someMethod];
dlsym: классы
63
#import <SomeFramework/SomeFramework.h>
Class someClass = (__bridge Class)dlsym(handle, "OBJC_CLASS_$_SomeClass");
SomeClass *someObj = [[someClass alloc] initWithParameter: param];
[someObj someMethod];
dlsym: классы
63
#import <SomeFramework/SomeFramework.h>
Class someClass = (__bridge Class)dlsym(handle, "OBJC_CLASS_$_SomeClass");
SomeClass *someObj = [[someClass alloc] initWithParameter: param];
[someObj someMethod];
dlsym: классы
63
#import <SomeFramework/SomeFramework.h>
Class someClass = (__bridge Class)dlsym(handle, "OBJC_CLASS_$_SomeClass");
SomeClass *someObj = [[someClass alloc] initWithParameter: param];
[someObj someMethod];
dlsym: классы
63
#import <SomeFramework/SomeFramework.h>
Class someClass = (__bridge Class)dlsym(handle, "OBJC_CLASS_$_SomeClass");
SomeClass *someObj = [[someClass alloc] initWithParameter: param];
[someObj someMethod];
Objective C обертки
64
Total pre-main time: 294.30 milliseconds (100.0%)
dylib loading time: 210.64 milliseconds (71.5%)
rebase/binding time: 22.18 milliseconds (7.5%)
ObjC setup time: 19.08 milliseconds (6.4%)
initializer time: 42.38 milliseconds (14.4%)
оригинал
обертки
пустой
65
Total pre-main time: 263.41 milliseconds (100.0%)
dylib loading time: 210.72 milliseconds (79.9%)
rebase/binding time: 16.89 milliseconds (6.4%)
ObjC setup time: 17.47 milliseconds (6.6%)
initializer time: 18.32 milliseconds (6.9%)
Уменьшение размера бинарного файла
оригинал
dlopen
пустой
Таким же образом можно загружать динамические
библиотеки из подов и собственные модули
приложения
dlopen
66
Итог
67
Оригинальный
amimono
objc обертки
dlopen
пустой
0 200 400 600 800
dylib rebase&bind objc-setup initialization
3. Оптимизация after-main
Нужно на старте делать
как можно меньше
работы
Избыточное создание сущностей на старте
Избыточный UI
Инициализация, необязательная для показа стартового UI
На что обратить внимание в первую очередь
70
Инъекция зависимостей
71
class RootViewController {
init(searchFacade: SearchFacade, routingFacade: RoutingFacade) {
...
}
}
let searchFacade: SearchFacade = SearchFacadeImpl(...)
let routingFacade: RoutingFacade = RoutingFacadeImlp(...)
let rootVC = RootViewController(searchFacade: searchFacade,
routingFacade: routingFacade)
Инъекция зависимостей
72
RootViewController
Инъекция зависимостей
72
RootViewController
SearchFacade RoutingFacade
Инъекция зависимостей
72
RootViewController
SearchManager RoutingPresenter... ...
SearchFacade RoutingFacade
Инъекция зависимостей
72
RootViewController
SearchManager RoutingPresenter... ...
SearchFacade RoutingFacade
...... ... ...
Оформить зависимости сущностей в протоколы
В конструкторе принимать реализацию протокола
В реализации использовать lazy var
Инъекция ленивых зависимостей на Swift
73
Инъекция ленивых зависимостей
74
protocol RootViewControllerDeps {
var searchFacade: SearchFacade { get }
var routingFacade: RoutingFacade { get }
}
class RootViewController {
init(deps: RootViewControllerDeps) {
...
}
}
Инъекция ленивых зависимостей
75
protocol RootViewControllerDeps {
var searchFacade: SearchFacade { get }
var routingFacade: RoutingFacade { get }
}
class RootViewControllerDepsImpl: RootViewControllerDeps {
lazy var searchFacade: SearchFacade = { return SearchFacadeImpl(...) }()
lazy var routingFacade: RoutingFacade = { return RoutingFacadeImpl(...) }()
}
Composition Root
76
class ApplicationDeps: SearchFacadeImplDeps, RoutingFacadeImplDeps,
RootViewControllerDeps {
lazy var searchFacade: SearchFacade =
{ return SearchFacadeImpl(deps: self) }()
lazy var routingFacade: RoutingFacade =
{ return RoutingFacadeImpl(deps: self) }()
lazy var rootViewController: RootViewController =
{ return RootViewController(deps: self) }()
}
На старте создаются только нужные сущности
Не используется рефлексия
resolve проверяется компилятором
Инъекция ленивых зависимостей
77
Сократить view-tree, создаваемое на старте
› ленивое создание контейнерных view и view-контроллеров
› ленивое создание view с опциональным контентом
Оптимизация UI
78
Оптимизация UI в Яндекс.Картах
79
Оптимизация UI в Яндекс.Картах
79
Оптимизация UI в Яндекс.Картах
79
› Ленивая загрузка шрифтов
› Графику, генерируемую программно, отрисовать в ассеты
› Текст также отрисовать в ассеты
› Сложный autolayout перевести на фреймы
› …
Прочие оптимизации UI
80
Цель - как можно быстрее разблокировать UI для пользователя
Пока UI не загружен - выполнять только необходимые
действия, прочие отложить на 0.1-0.3с
Необязательная на старте работа
81
Отложили на 0.3с
› Синхронизацию закладок
› Отображение закладок на карте
› Загрузку конфигурации приложения
› Настройку аудиосессии
› ...
В Яндекс.Картах
82
4. Сохранение результата
Continuous integration
84
Встроить вызов скрипта c автозапусками в CI
Continuous integration
84
Встроить вызов скрипта c автозапусками в CI
Собирать статистику запусков
Continuous integration
84
Встроить вызов скрипта c автозапусками в CI
Собирать статистику запусков
Обеспечить доступ к статистике
Continuous integration
84
Логировать создание зависимостей в composition root
Логировать список загружаемых динамических бибиотек через
objc_copyImageNames()
Сверять с эталонными логами
Идеи для CI
85
Информация о процессе через sysctl
86
#import <sys/sysctl.h>
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
struct kinfo_proc kp;
size_t len = sizeof(kp);
sysctl(mib, 4, &kp, &len, NULL, 0)
Время старта через sysctl
87
#import <sys/sysctl.h>
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
struct kinfo_proc kp;
size_t len = sizeof(kp);
sysctl(mib, 4, &kp, &len, NULL, 0)
struct timeval start_time = kp.kp_proc.p_starttime;
Замерять полное время запуска от нажатия на иконку
приложения через sysctl
Отправлять в системы аналитики
Проверять графики
88
Пользовательские запуски
Заключение
Яндекс.Карты - холодный, 5s
90
До оптимизаций
После оптимизаций
0 625 1250 1875 2500
dylib loading time rebase/binding time
ObjC setup time initializer time
before didFinishLaunching time didFinishLaunching time
1.6s, -30%
2.3s
Яндекс.Карты - холодный запуск
91
Времязапуска,мс
iPhone 5 iPhone 5s iPhone 6 iPhone 6s iPhone 7
607695
1 342
1 620
3 148
8851 014
1 930
2 333
4 470
До оптимизаций После оптимизаций
-30% -31% -31%-29% -31%
Яндекс.Карты - теплый, 5s
92
До оптимизаций
После оптимизаций
0 300 600 900 1200
dylib loading time rebase/binding time
ObjC setup time initializer time
before didFinishLaunching time didFinishLaunching time
0.75s, -37.5%
1.2s
Яндекс.Карты - теплый запуск
93
Времязапуска,мс
iPhone 5 iPhone 5s iPhone 6 iPhone 6s iPhone 7
283354
676752
1 347
533
721
1 088
1 203
2 195
До оптимизаций После оптимизаций
-37% -37% -51%-39% -47%
Примеры из доклада
WWDC 2016 "Optimizing App Startup Time"
libimobiledevice
Доклад Почты Mail.Ru
cocoapods-amimono
sysctl
Ссылки
94
Николай Лихогруд
Руководитель группы разработки Яндекс.Карт для iOS
likhogrud@yandex-team.ru
Спасибо за внимание

Mais conteúdo relacionado

Mais procurados

Joker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICESJoker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICESAleksandr Tarasov
 
Kubernetes
KubernetesKubernetes
KubernetesSQALab
 
Scaling services with apache mesos (and docker)
Scaling services with apache mesos (and docker)Scaling services with apache mesos (and docker)
Scaling services with apache mesos (and docker)Ivan Kudryavtsev
 
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)Ontico
 
Быстрое прототипирование бэкенда игры с геолокацией на OpenResty, Redis и Doc...
Быстрое прототипирование бэкенда игры с геолокацией на OpenResty, Redis и Doc...Быстрое прототипирование бэкенда игры с геолокацией на OpenResty, Redis и Doc...
Быстрое прототипирование бэкенда игры с геолокацией на OpenResty, Redis и Doc...Ontico
 
Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»WrikeTechClub
 
Legacy в коробочке. Dev-среда на базе Kubernetes / Илья Сауленко (Avito)
Legacy в коробочке. Dev-среда на базе Kubernetes / Илья Сауленко (Avito)Legacy в коробочке. Dev-среда на базе Kubernetes / Илья Сауленко (Avito)
Legacy в коробочке. Dev-среда на базе Kubernetes / Илья Сауленко (Avito)Ontico
 
Построение аналитического хранилища на 100 петабайт
Построение аналитического хранилища на 100 петабайтПостроение аналитического хранилища на 100 петабайт
Построение аналитического хранилища на 100 петабайтAlexander Mazurov
 
Продуктовые проблемы при создании очередной Docker PaaS / Владимир Ярцев (Cas...
Продуктовые проблемы при создании очередной Docker PaaS / Владимир Ярцев (Cas...Продуктовые проблемы при создании очередной Docker PaaS / Владимир Ярцев (Cas...
Продуктовые проблемы при создании очередной Docker PaaS / Владимир Ярцев (Cas...Ontico
 
SPb Jenkins Meetup #5. Jenkins in da Cloud. Внутренности
SPb Jenkins Meetup #5. Jenkins in da Cloud. ВнутренностиSPb Jenkins Meetup #5. Jenkins in da Cloud. Внутренности
SPb Jenkins Meetup #5. Jenkins in da Cloud. ВнутренностиOleg Nenashev
 
Движение по хрупкому дну / Сергей Караткевич (servers.ru)
Движение по хрупкому дну / Сергей Караткевич (servers.ru)Движение по хрупкому дну / Сергей Караткевич (servers.ru)
Движение по хрупкому дну / Сергей Караткевич (servers.ru)Ontico
 
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)Ontico
 
Резервное копирование MySQL в экстремальных условиях
Резервное копирование MySQL в экстремальных условияхРезервное копирование MySQL в экстремальных условиях
Резервное копирование MySQL в экстремальных условияхSveta Smirnova
 
Виртуализированные сетевые сервисы на line rate в серверном окружении / Алекс...
Виртуализированные сетевые сервисы на line rate в серверном окружении / Алекс...Виртуализированные сетевые сервисы на line rate в серверном окружении / Алекс...
Виртуализированные сетевые сервисы на line rate в серверном окружении / Алекс...Ontico
 
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемыMoscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемыOleg Nenashev
 
Быстрое построение backendов c помощью реактивных потоков
Быстрое построение backendов c помощью реактивных потоковБыстрое построение backendов c помощью реактивных потоков
Быстрое построение backendов c помощью реактивных потоковCodeFest
 
Лучшие практики Continuous Delivery с Docker / Дмитрий Столяров (Флант)
Лучшие практики Continuous Delivery с Docker / Дмитрий Столяров (Флант)Лучшие практики Continuous Delivery с Docker / Дмитрий Столяров (Флант)
Лучшие практики Continuous Delivery с Docker / Дмитрий Столяров (Флант)Ontico
 

Mais procurados (20)

Joker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICESJoker 2015. WILD microSERVICES
Joker 2015. WILD microSERVICES
 
DC/OS more than PAAS
DC/OS more than PAASDC/OS more than PAAS
DC/OS more than PAAS
 
Kubernetes
KubernetesKubernetes
Kubernetes
 
Scaling services with apache mesos (and docker)
Scaling services with apache mesos (and docker)Scaling services with apache mesos (and docker)
Scaling services with apache mesos (and docker)
 
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
Zabbix 3.4 - простая непростая дружба с сообществом / Алексей Владышев (Zabbix)
 
Быстрое прототипирование бэкенда игры с геолокацией на OpenResty, Redis и Doc...
Быстрое прототипирование бэкенда игры с геолокацией на OpenResty, Redis и Doc...Быстрое прототипирование бэкенда игры с геолокацией на OpenResty, Redis и Doc...
Быстрое прототипирование бэкенда игры с геолокацией на OpenResty, Redis и Doc...
 
Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»Артём Ерошенко «Рецепт приготовления облачных тестингов»
Артём Ерошенко «Рецепт приготовления облачных тестингов»
 
Legacy в коробочке. Dev-среда на базе Kubernetes / Илья Сауленко (Avito)
Legacy в коробочке. Dev-среда на базе Kubernetes / Илья Сауленко (Avito)Legacy в коробочке. Dev-среда на базе Kubernetes / Илья Сауленко (Avito)
Legacy в коробочке. Dev-среда на базе Kubernetes / Илья Сауленко (Avito)
 
Построение аналитического хранилища на 100 петабайт
Построение аналитического хранилища на 100 петабайтПостроение аналитического хранилища на 100 петабайт
Построение аналитического хранилища на 100 петабайт
 
Jenkins в docker in mesos in ...
Jenkins в docker in mesos in ...Jenkins в docker in mesos in ...
Jenkins в docker in mesos in ...
 
Продуктовые проблемы при создании очередной Docker PaaS / Владимир Ярцев (Cas...
Продуктовые проблемы при создании очередной Docker PaaS / Владимир Ярцев (Cas...Продуктовые проблемы при создании очередной Docker PaaS / Владимир Ярцев (Cas...
Продуктовые проблемы при создании очередной Docker PaaS / Владимир Ярцев (Cas...
 
SPb Jenkins Meetup #5. Jenkins in da Cloud. Внутренности
SPb Jenkins Meetup #5. Jenkins in da Cloud. ВнутренностиSPb Jenkins Meetup #5. Jenkins in da Cloud. Внутренности
SPb Jenkins Meetup #5. Jenkins in da Cloud. Внутренности
 
Движение по хрупкому дну / Сергей Караткевич (servers.ru)
Движение по хрупкому дну / Сергей Караткевич (servers.ru)Движение по хрупкому дну / Сергей Караткевич (servers.ru)
Движение по хрупкому дну / Сергей Караткевич (servers.ru)
 
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
Распределенные системы в Одноклассниках / Олег Анастасьев (Одноклассники)
 
Резервное копирование MySQL в экстремальных условиях
Резервное копирование MySQL в экстремальных условияхРезервное копирование MySQL в экстремальных условиях
Резервное копирование MySQL в экстремальных условиях
 
Виртуализированные сетевые сервисы на line rate в серверном окружении / Алекс...
Виртуализированные сетевые сервисы на line rate в серверном окружении / Алекс...Виртуализированные сетевые сервисы на line rate в серверном окружении / Алекс...
Виртуализированные сетевые сервисы на line rate в серверном окружении / Алекс...
 
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемыMoscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
 
Быстрое построение backendов c помощью реактивных потоков
Быстрое построение backendов c помощью реактивных потоковБыстрое построение backendов c помощью реактивных потоков
Быстрое построение backendов c помощью реактивных потоков
 
Лучшие практики Continuous Delivery с Docker / Дмитрий Столяров (Флант)
Лучшие практики Continuous Delivery с Docker / Дмитрий Столяров (Флант)Лучшие практики Continuous Delivery с Docker / Дмитрий Столяров (Флант)
Лучшие практики Continuous Delivery с Docker / Дмитрий Столяров (Флант)
 
CD with Jenkins. Lessons Learned
CD with Jenkins. Lessons LearnedCD with Jenkins. Lessons Learned
CD with Jenkins. Lessons Learned
 

Semelhante a Оптимизация времени запуска iOS-приложений / Николай Лихогруд (Яндекс)

Поговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийПоговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийAndrey Akinshin
 
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)Ontico
 
Jbreak 2016: Твой личный Spring Boot Starter
Jbreak 2016: Твой личный Spring Boot StarterJbreak 2016: Твой личный Spring Boot Starter
Jbreak 2016: Твой личный Spring Boot StarterAleksandr Tarasov
 
DevOps или искусство выживания в растущей компании
DevOps или искусство выживания в растущей компанииDevOps или искусство выживания в растущей компании
DevOps или искусство выживания в растущей компанииAlexey Vakhov
 
Java Platform Performance BoF
Java Platform Performance BoFJava Platform Performance BoF
Java Platform Performance BoFDmitry Buzdin
 
Hl2008 Wtf Hl 169
Hl2008 Wtf Hl 169Hl2008 Wtf Hl 169
Hl2008 Wtf Hl 169Media Gorod
 
Zero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And ForgeZero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And ForgeYehor Herasymchuk
 
Jiramania презентации @augspb
Jiramania презентации   @augspbJiramania презентации   @augspb
Jiramania презентации @augspbGonchik Tsymzhitov
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
Нюансы запуска приложений в Kubernetes
Нюансы запуска приложений в KubernetesНюансы запуска приложений в Kubernetes
Нюансы запуска приложений в KubernetesАндрей Новиков
 
Software Analytics in frontend
Software Analytics in frontendSoftware Analytics in frontend
Software Analytics in frontendDenis Kolesnikov
 
Истинный DevOps. Секрет 42.
Истинный DevOps. Секрет 42.Истинный DevOps. Секрет 42.
Истинный DevOps. Секрет 42.Nikita Borzykh
 
Эволюция BackDoor.Flashback
Эволюция BackDoor.FlashbackЭволюция BackDoor.Flashback
Эволюция BackDoor.Flashbackhexminer
 
Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...
Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...
Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...Ontico
 
OpenSource SQL Databases Enter Millions Queries per Second Era
OpenSource SQL Databases Enter Millions Queries per Second EraOpenSource SQL Databases Enter Millions Queries per Second Era
OpenSource SQL Databases Enter Millions Queries per Second EraSveta Smirnova
 
Расширь границы возможного вместе с Gradle
Расширь границы возможного вместе с GradleРасширь границы возможного вместе с Gradle
Расширь границы возможного вместе с GradleAleksandr Tarasov
 
Java Ahead-Of-Time compilation
Java Ahead-Of-Time compilationJava Ahead-Of-Time compilation
Java Ahead-Of-Time compilationNikita Lipsky
 

Semelhante a Оптимизация времени запуска iOS-приложений / Николай Лихогруд (Яндекс) (20)

Поговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложенийПоговорим о микрооптимизациях .NET-приложений
Поговорим о микрооптимизациях .NET-приложений
 
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
Оптимизация UI потока / Дмитрий Куркин (Mail.Ru)
 
Jbreak 2016: Твой личный Spring Boot Starter
Jbreak 2016: Твой личный Spring Boot StarterJbreak 2016: Твой личный Spring Boot Starter
Jbreak 2016: Твой личный Spring Boot Starter
 
DevOps или искусство выживания в растущей компании
DevOps или искусство выживания в растущей компанииDevOps или искусство выживания в растущей компании
DevOps или искусство выживания в растущей компании
 
Java Platform Performance BoF
Java Platform Performance BoFJava Platform Performance BoF
Java Platform Performance BoF
 
Hl2008 Wtf Hl 169
Hl2008 Wtf Hl 169Hl2008 Wtf Hl 169
Hl2008 Wtf Hl 169
 
Release management with Gradle #JokerConf2016
Release management with Gradle #JokerConf2016Release management with Gradle #JokerConf2016
Release management with Gradle #JokerConf2016
 
Zero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And ForgeZero Downtime PHP Deployment with Envoyer And Forge
Zero Downtime PHP Deployment with Envoyer And Forge
 
Jiramania презентации @augspb
Jiramania презентации   @augspbJiramania презентации   @augspb
Jiramania презентации @augspb
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Нюансы запуска приложений в Kubernetes
Нюансы запуска приложений в KubernetesНюансы запуска приложений в Kubernetes
Нюансы запуска приложений в Kubernetes
 
Software Analytics in frontend
Software Analytics in frontendSoftware Analytics in frontend
Software Analytics in frontend
 
Gradle in Enterprise, Is it possible?
Gradle in Enterprise, Is it possible?Gradle in Enterprise, Is it possible?
Gradle in Enterprise, Is it possible?
 
10M tests per day
10M tests per day10M tests per day
10M tests per day
 
Истинный DevOps. Секрет 42.
Истинный DevOps. Секрет 42.Истинный DevOps. Секрет 42.
Истинный DevOps. Секрет 42.
 
Эволюция BackDoor.Flashback
Эволюция BackDoor.FlashbackЭволюция BackDoor.Flashback
Эволюция BackDoor.Flashback
 
Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...
Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...
Open Source SQL-базы данных вступили в эру миллионов запросов в секунду / Фед...
 
OpenSource SQL Databases Enter Millions Queries per Second Era
OpenSource SQL Databases Enter Millions Queries per Second EraOpenSource SQL Databases Enter Millions Queries per Second Era
OpenSource SQL Databases Enter Millions Queries per Second Era
 
Расширь границы возможного вместе с Gradle
Расширь границы возможного вместе с GradleРасширь границы возможного вместе с Gradle
Расширь границы возможного вместе с Gradle
 
Java Ahead-Of-Time compilation
Java Ahead-Of-Time compilationJava Ahead-Of-Time compilation
Java Ahead-Of-Time compilation
 

Mais de Ontico

One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...Ontico
 
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Ontico
 
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Ontico
 
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Ontico
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Ontico
 
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)Ontico
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Ontico
 
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Ontico
 
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)Ontico
 
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)Ontico
 
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Ontico
 
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Ontico
 
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Ontico
 
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Ontico
 
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)Ontico
 
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Ontico
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Ontico
 
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...Ontico
 
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Ontico
 
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Ontico
 

Mais de Ontico (20)

One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
One-cloud — система управления дата-центром в Одноклассниках / Олег Анастасье...
 
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)Масштабируя DNS / Артем Гавриченков (Qrator Labs)
Масштабируя DNS / Артем Гавриченков (Qrator Labs)
 
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
Создание BigData-платформы для ФГУП Почта России / Андрей Бащенко (Luxoft)
 
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
Готовим тестовое окружение, или сколько тестовых инстансов вам нужно / Алекса...
 
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
Новые технологии репликации данных в PostgreSQL / Александр Алексеев (Postgre...
 
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
PostgreSQL Configuration for Humans / Alvaro Hernandez (OnGres)
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
 
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
Опыт разработки модуля межсетевого экранирования для MySQL / Олег Брославский...
 
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
ProxySQL Use Case Scenarios / Alkin Tezuysal (Percona)
 
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)MySQL Replication — Advanced Features / Петр Зайцев (Percona)
MySQL Replication — Advanced Features / Петр Зайцев (Percona)
 
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
Внутренний open-source. Как разрабатывать мобильное приложение большим количе...
 
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
Подробно о том, как Causal Consistency реализовано в MongoDB / Михаил Тюленев...
 
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
Балансировка на скорости проводов. Без ASIC, без ограничений. Решения NFWare ...
 
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
Перехват трафика — мифы и реальность / Евгений Усков (Qrator Labs)
 
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
И тогда наверняка вдруг запляшут облака! / Алексей Сушков (ПЕТЕР-СЕРВИС)
 
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
Как мы заставили Druid работать в Одноклассниках / Юрий Невиницин (OK.RU)
 
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
Разгоняем ASP.NET Core / Илья Вербицкий (WebStoating s.r.o.)
 
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...100500 способов кэширования в Oracle Database или как достичь максимальной ск...
100500 способов кэширования в Oracle Database или как достичь максимальной ск...
 
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
Apache Ignite Persistence: зачем Persistence для In-Memory, и как он работает...
 
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
Механизмы мониторинга баз данных: взгляд изнутри / Дмитрий Еманов (Firebird P...
 

Оптимизация времени запуска iOS-приложений / Николай Лихогруд (Яндекс)