Как да получите времето за изпълнение на скрипт

Пространство в ядрото спрямо потребителското пространство
CS Архитектура

Преди няколко седмици работих по забавен проект за монитор на врати с Raspberry Pi 3 модел B и скриптове на черупките. Наскоро свързах камера с Pi и актуализирах скрипта, така че да се направи снимка, когато вратата се отвори и изпрати като прикачен файл в известието по имейл.

Един от проблемите, с които се сблъсках, беше, че времето за изпълнение на скрипта се увеличи значително от няколко секунди първоначално до 17,58 сек. Успях да идентифицирам и изолирам времето за изпълнение на всеки ред от скрипта. Разбрах, че командата raspistill изпълни 5. 87 сек. Което води до липса на напълно за заснемане на снимка на лицето, което отваря вратата.

как да се намали времето за изпълнение на raspistill

Прост raspistill, последван от „- help“ тага на терминала, предостави повече информация за командите за параметри на изображението:

pi @ raspberrypi: ~ $ raspistill --help
Стартира камерата за определено време и взима JPG заснемане в края, ако бъде поискано
използване: raspistill [опции]
Команди за параметри на изображението
...
-t, --timeout: Времето (в ms) преди да направи снимка и се изключва (ако не е посочено, задайте на 5s)

Успях да намаля времето за изпълнение на raspistill до няколко милисекунди, като посочих времето, преди снимката да бъде заснета в сценария, както следва:

Как ефективно да постигнете времето за изпълнение на скрипт

По време на този процес научавам за командата време, която се използва за получаване на времето, необходимо за изпълнение на друга команда или скрипт:

време tvojecript.sh // получи изпълнение за скрипт
time ls // получи време за изпълнение на команда ls

което даде следния резултат:

Скриншот на терминала на командата

Сега можете да забележите, че командата за време предоставя реално, потребителско и системно време. Разбирането на потребителското пространство срещу пространството на ядрото има значение. Едно от тези неща не е като другото. Real се отнася до действително изминалото време; Потребителят и Sys се отнасят до времето на процесора, използвано само от процеса.

Реална, потребителска и Sys статистика на времето
  • Истинско е времето за стенен часовник - време от началото до края на разговора. Това е цялото изминало време, включително отрязъци от време, използвани от други процеси, и времето, което процесът прекарва блокиран (например, ако изчаква завършване на I / O).
  • Потребителят е времето на процесора, прекарано в код на потребителски режим (извън ядрото) в рамките на процеса. Това е само действителното време на процесора, използвано при изпълнение на процеса. Други процеси и време, което процесът прекарва блокирано, не се отчитат към тази цифра.
  • Sys е количеството време на процесора, прекарано в ядрото в рамките на процеса. Това означава изпълнение на времето на процесора, прекарано в системни обаждания в ядрото, за разлика от кода на библиотеката, който все още работи в потребителско пространство. Подобно на „потребител“, това е само време на процесора, използвано от процеса. Вижте по-долу кратко описание на режима на ядрото (известен също като режим „надзорник“) и механизма за системно повикване.

User + Sys ще ви каже колко действително време на процесора е използвал вашият процес. Обърнете внимание, че това е във всички процесори, така че ако процесът има множество нишки (и този процес се изпълнява на компютър с повече от един процесор), той потенциално може да надвиши отчетеното от Real време на стенен часовник (което обикновено се случва). Обърнете внимание, че в резултата тези цифри включват времето за потребител и Sys на всички дъщерни процеси (и техните потомци), както и кога те биха могли да бъдат събрани, напр. чрез изчакване (2) или изчакване (2), въпреки че основните системни обаждания връщат статистически данни за процеса и неговите деца отделно.

Произход на статистиката, отчетена по време (1)

Статистиката, отчетена по време, се събира от различни системни обаждания. „Потребител“ и „Сис“ идват от изчакване (2) или времена (2), в зависимост от конкретната система. „Реално“ се изчислява от начален и краен час, събран от разговора gettimeofday (2). В зависимост от версията на системата, времето може да се събира и различни други статистически данни, като например броя на контекстните превключватели.

На мултипроцесорна машина процесът с много нишки или процеса на разделяне на деца може да има изминало време, по-малко от общото време на процесора - тъй като паралелно могат да протичат различни нишки или процеси. Също така, отчетените статистически данни за времето идват от различен произход, така че времената, записани за много кратки изпълнени задачи, могат да бъдат обект на грешки при закръгляване, както показва примерът, даден от оригиналния плакат.

Кратък грунд за Kernel vs. User mode

В Unix или която и да е операционна система със защитена памет, режимът „Kernel“ или „Supervisor“ се отнася до привилегирован режим, в който може да работи процесорът. Някои привилегировани действия, които биха могли да повлияят на сигурността или стабилността, могат да се извършват само когато процесорът работи в това режим. Тези действия не са достъпни за кода на приложението.

Пример за такова действие може да бъде манипулация на MMU за получаване на достъп до адресното пространство на друг процес. Обикновено кодът в потребителски режим не може да направи това (с основателна причина), въпреки че може да поиска споделена памет от ядрото, което може да бъде прочетено или записано от повече от един процес. В този случай споделената памет изрично се изисква от ядрото чрез защитен механизъм и двата процеса трябва изрично да се прикачат към нея, за да се използват.

Привилегированият режим обикновено се нарича режим „ядро“, тъй като ядрото се изпълнява от процесора, работещ в този режим. За да преминете към режим на ядрото, трябва да издадете конкретна инструкция (често наричана капан), която превключва процесора да работи в режим на ядрото и изпълнява код от конкретно място, което се намира в таблица за скокове.

От съображения за сигурност не можете да преминете към режим на ядрото и да изпълните произволен код - капаните се управляват чрез таблица от адреси, на които не може да се запише, освен ако процесорът не работи в режим на надзор. Капате с изричен номер на капана и адресът се търси в таблицата за скокове; ядрото има ограничен брой контролирани входни точки.

„Системните“ обаждания в C библиотеката (по-специално тези, описани в раздел 2 на ръководните страници) имат компонент в потребителски режим, който всъщност се обаждате от вашата C програма. Зад кулисите те могат да издават едно или повече системни обаждания на ядрото за извършване на специфични услуги като I / O, но те все още имат код, работещ в потребителски режим.

Също така е напълно възможно директно да се издаде капан в режима на ядрото от всеки код на потребителско пространство, ако желаете, въпреки че може да се наложи да напишете фрагмент от език за сглобяване, за да настроите регистрите правилно за повикването. Страница, описваща системните обаждания, предоставени от Linux ядрото, и конвенциите за настройка на регистрите може да намерите тук.

Повече за „sys“

Има неща, които вашият код не може да направи от потребителски режим - неща като разпределяне на памет или достъп до хардуер (HDD, мрежа и т.н.). Те са под надзора на ядрото и само той може да ги направи. Някои операции, които правите (като malloc orfread / fwrite) ще извикат тези функции на ядрото и ще се считат за 'sys' време. За съжаление, не е толкова просто, тъй като "всяко обаждане към malloc ще бъде отчетено в" sys "време".

В C, функцията на библиотеката malloc се използва за разпределяне на блок памет на грамадата. Програмата осъществява достъп до този блок памет чрез указател, който malloc връща. Когато паметта вече не е необходима, показалеца се предава на свободен, който раздава паметта, така че да може да се използва за други цели.

Обаждането към malloc ще извърши някаква своя обработка (все още се брои в 'потребител' време) и след това някъде по пътя може да извика функцията в ядрото (броено в 'sys' време). След като се върнете от повикването на ядрото, ще има още малко време в 'user' и тогава malloc ще се върне към вашия код. Що се отнася до това, когато превключвателят се случи и колко от него се изразходва в режим на ядрото ... не можете да кажете. Зависи от изпълнението на библиотеката. Също така, други на пръв поглед невинни функции също могат да използват malloc и подобни на заден план, които отново ще имат известно време в „sys“.

Част от съдържанието на тази статия е комбинация от отговори, първоначално публикувани в Stack Overflow
Ако ви хареса тази статия, може да ви хареса и „Как да изградим двупосочно приложение за Интернет на нещата / Чат с Python“
Моля, дайте му няколко хлопки за поддръжка!
Наздраве !!!