Вы когда-нибудь интересовались измерением различных технических показателей вашего приложения? Например, время сборки, время запуска, использование ЦП, памяти и т. Д. Потому что они могут вызвать хорошее или плохое взаимодействие с пользователем при использовании вашего приложения. Сегодня мы поговорим о времени запуска.

Но прежде всего… Здесь вы не можете найти ответ на вопрос «Как оптимизировать время запуска? - это не тема этой публикации.

Есть несколько способов измерить время запуска:

  • используйте флаг DYLD_PRINT_STATISTICS;
  • используйте xcrun;
  • используйте Darwin C API, чтобы вычислить его вручную.

DYLD_PRINT_STATISTICS

Установка этой переменной среды позволяет анализировать pre-main время.

Чтобы оптимизировать время перед основной фазой, я бы порекомендовал посмотреть доклад WWDC на тему Оптимизация времени запуска приложений.

К сожалению, вы не можете вручную изменить эту информацию и отправить ее на свой сервер. Вообще-то, вы можете разобрать журнал ОС, но это нетривиальная задача. И это выходит за рамки данной темы.

Но мы хотим отслеживать время запуска для реального пользователя. Как мы можем это сделать?

xcrun

Использование этого инструмента командной строки разработки позволяет написать сценарий для измерения времени запуска на симуляторах. Но не на реальных пользователях.

Дарвин C API

Что ж, мы должны использовать Darwin C API. Основная идея: сравнить время, когда система запускает процесс нашего приложения, и время, когда наше приложение становится доступным для использования.

Все, что вам нужно сделать, это написать код на C.

#include "LaunchTimeMeasurer.h"
#include <sys/sysctl.h>;
#include <sys/unistd.h>;
double processUptime() {
    struct timeval currentTime; // 1
    struct kinfo_proc processInfo // 2;
    size_t processInfoSize = sizeof(processInfo) // 3;
    int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; // 4
    
    sysctl(mib, sizeof(mib)/sizeof(int), &processInfo, &processInfoSize, NULL, 0); // 5
    gettimeofday(&amp;currentTime, NULL); // 6
    
    return toSeconds(currentTime) - toSeconds(processInfo.kp_proc.p_starttime); // 7
}
double toSeconds(struct timeval time) {
    const int microsecondsInSecond = 1000000;
    return time.tv_sec + (double)time.tv_usec / microsecondsInSecond;
}

Давайте просто рассмотрим этот код построчно.

  1. timeval - это структура, используемая для указания временного интервала. Он состоит из двух членов:
  • tv_sec представляет временной интервал в секундах;
  • tv_usec представляет интервал времени в микросекундах. Это значение используется в сочетании с элементом tv_sec для представления значений временного интервала, не кратных секундам.

2. kinfo_proc - это структура, содержащая огромное количество информации о текущем процессе, включая идентификатор процесса, имя процесса и т. Д.

3. Размер информации о текущем процессе.

4. Массив описывается MIB (База управляющей информации - возвращается sysctl как дерево с несколькими широкими категориями, такими как kern, net, vm).

  • CTL_KERN - «старшее ядро»: процесс, ограничения
  • KERN_PROC - записи процесса
  • KERN_PROC_PID - фильтр по id процесса
  • getpid () - идентификатор текущего процесса

5. sysctl читает и / или записывает параметры ядра.

6. Функция получает текущее время, выраженное в секундах и микросекундах, и сохраняет его в структуре timeval .

7. Просто сравните разницу между текущим временем и временем начала процесса.

Это все. Вы можете вызвать эту функцию из кода pre-main части или в начале didFinishLaunchingWithOptions или в конце didFinishLaunchingWithOptions. Зависит от того, что вы хотите измерить.

Также вы можете найти Swift-реализацию здесь.