Како да оптимизујете своје Питхон скрипте за боље перформансе

Kako Da Optimizujete Svoje Pithon Skripte Za Bole Performanse



Оптимизација Питхон скрипти за боље перформансе укључује идентификацију и решавање уских грла у нашем коду, чинећи га бржим и ефикаснијим. Питхон је популаран и моћан програмски језик који се данас користи у бројним апликацијама, укључујући анализу података, МЛ пројекте (машинско учење), развој веба и још много тога. Оптимизација Питхон кода је стратегија за побољшање брзине и ефикасности програмског програма при обављању било које активности користећи мање линија кода, мање меморије или додатних ресурса. Велики и неефикасан код може успорити програм, што може довести до лошег задовољства клијената и потенцијалног финансијског губитка, или потребе за додатним радом на поправљању и решавању проблема.

Неопходан је при обављању задатка који захтева обраду неколико радњи или података. Стога, замена и побољшање неких неефикасних блокова кода и функционалности може имати запањујуће резултате као што су следећи:

  1. Повећајте перформансе апликације
  2. Креирајте читљив и организован код
  3. Учините праћење грешака и отклањање грешака једноставнијим
  4. Сачувајте значајну рачунарску снагу и тако даље

Профилирајте свој код

Пре него што почнемо са оптимизацијом, неопходно је идентификовати делове кода пројекта који га успоравају. Технике за профилисање у Питхон-у укључују цПрофиле и профиле пакете. Користите такве алате да бисте проценили колико брзо се извршавају одређене функције и линије кода. Модул цПрофиле производи извештај који детаљно описује колико дуго треба да се покрене свака функција скрипте. Овај извештај нам може помоћи да пронађемо све функције које раде споро како бисмо могли да их побољшамо.







Исјечак кода:



увоз цПрофил као цП
деф израчунајСум ( инпутНумбер ) :
збир_улазних_бројева = 0
док инпутНумбер > 0 :
збир_улазних_бројева + = инпутНумбер % 10
инпутНумбер // = 10
принт ( 'Збир свих цифара у улазном броју је: 'збир_улазних_бројева'' )
повратак збир_улазних_бројева
деф маин_фунц ( ) :
цП. трцати ( 'цалцулатеСум(9876543789)' )
ако __име__ == '__главни__' :
маин_фунц ( )

Програм врши укупно пет позива функција као што се види у првом реду излаза. Детаљи о сваком позиву функције су приказани у следећих неколико редова, укључујући број позива функције, укупно трајање времена у функцији, трајање времена по позиву и укупну количину времена у функцији (укључујући све функције које се зове).



Поред тога, програм штампа извештај на екрану са упитом који показује да програм завршава време извршења свих својих задатака у року од 0.000 секунди. Ово показује колико је програм брз.





Изаберите праву структуру података

Карактеристике перформанси зависе од структуре података. Конкретно, речници су бржи за тражење него листе у вези са складиштем опште намене. Изаберите структуру података која је најпогоднија за операције које ћемо спроводити на вашим подацима ако их познајете. Следећи пример истражује ефикасност различитих структура података за идентичан процес да би се утврдило да ли је елемент у структури података присутан.



Процењујемо време које је потребно да проверимо да ли је елемент присутан у свакој структури података — листи, скупу и речнику — и упоређујемо их.

ОптимизеДатаТипе.пи:

увоз Тимеи као тт
увоз насумично као рндобј
# Генеришите листу целих бројева
рандом_дата_лист = [ рндобј. рандинт ( 1 , 10000 ) за _ ин домет ( 10000 ) ]
# Направите скуп од истих података
рандом_дата_сет = комплет ( рандом_дата_лист )

# Направите речник са истим подацима као и кључеви
обј_ДатаДицтионари = { на једном: Ниједан за на једном ин рандом_дата_лист }

# Елемент за претрагу (постоји у подацима)
рандом_нумбер_то_финд = рндобј. избор ( рандом_дата_лист )

# Измерите време да проверите чланство на листи
лист_тиме = тт. Тимеи ( ламбда : рандом_нумбер_то_финд ин рандом_дата_лист , број = 1000 )

# Измерите време да проверите чланство у скупу
одредити време = тт. Тимеи ( ламбда : рандом_нумбер_то_финд ин рандом_дата_сет , број = 1000 )

# Измерите време да проверите чланство у речнику
дицт_тиме = тт. Тимеи ( ламбда : рандом_нумбер_то_финд ин обј_ДатаДицтионари , број = 1000 )

принт ( ф „Време провере чланства на листи: {лист_тиме:.6ф} секунди“ )
принт ( ф „Подесите време провере чланства: {сет_тиме:.6ф} секунди“ )
принт ( ф „Време провере чланства у речнику: {дицт_тиме:.6ф} секунди“ )

Овај код пореди перформансе листа, скупова и речника приликом провере чланства. Генерално, скупови и речници су знатно бржи од листа за тестове чланства јер користе претраживања заснована на хешовима, тако да имају просечну временску сложеност од О(1). Листе, с друге стране, морају да врше линеарне претраге које резултирају тестовима чланства са О(н) временском сложеношћу.

  Аутоматски генерисан снимак екрана описа рачунара

Користите уграђене функције уместо петљи

Бројне уграђене функције или методе у Питхон-у могу се користити за обављање типичних задатака као што су филтрирање, сортирање и мапирање. Коришћење ових рутина уместо креирања нечијих петљи помаже у убрзавању кода јер су често оптимизоване за перформансе.

Хајде да направимо неки пример кода да бисмо упоредили перформансе креирања прилагођених петљи коришћењем уграђених функција за типичне послове (као што су мап(), филтер() и сортед()). Проценићемо колико добро раде различите методе мапирања, филтрирања и сортирања.

БуилтИнФунцтионс.пи:

увоз Тимеи као тт
# Пример листе листе_бројева
бројеви_лист = листа ( домет ( 1 , 10000 ) )

# Функција за квадрат нумберс_лист користећи петљу
деф скуаре_усинг_лооп ( бројеви_лист ) :
квадратни резултат = [ ]
за на једном ин листа_бројева:
квадратни резултат. додати ( на једном ** 2 )
повратак квадратни резултат
# Функција за филтрирање листе парних бројева помоћу петље
деф филтер_евен_усинг_лооп ( бројеви_лист ) :
филтер_ресулт = [ ]
за на једном ин листа_бројева:
ако на једном % 2 == 0 :
филтер_ресулт. додати ( на једном )
повратак филтер_ресулт
# Функција за сортирање листе_бројева помоћу петље
деф сорт_усинг_лооп ( бројеви_лист ) :
повратак сортирано ( бројеви_лист )
# Измери време до квадратуре нумберс_лист користећи мап()
мап_тиме = тт. Тимеи ( ламбда : листа ( Мапа ( ламбда к: к ** 2 , бројеви_лист ) ) , број = 1000 )
# Измерите време за филтрирање парних бројева_лист користећи филтер()
филтер_тиме = тт. Тимеи ( ламбда : листа ( филтер ( ламбда к: к % 2 == 0 , бројеви_лист ) ) , број = 1000 )
# Измерите време за сортирање листе бројева помоћу сортед()
сортед_тиме = тт. Тимеи ( ламбда : сортирано ( бројеви_лист ) , број = 1000 )
# Измери време до квадратуре листе_бројева користећи петљу
лооп_мап_тиме = тт. Тимеи ( ламбда : скуаре_усинг_лооп ( бројеви_лист ) , број = 1000 )
# Измери време за филтрирање парних бројева_лист користећи петљу
лооп_филтер_тиме = тт. Тимеи ( ламбда : филтер_евен_усинг_лооп ( бројеви_лист ) , број = 1000 )
# Измери време за сортирање листе_бројева помоћу петље
лооп_сортед_тиме = тт. Тимеи ( ламбда : сорт_усинг_лооп ( бројеви_лист ) , број = 1000 )
принт ( „Листа бројева садржи 10000 елемената“ )
принт ( ф „Мапа() Време: {мап_тиме:.6ф} секунди“ )
принт ( ф „Време филтера(): {филтер_тиме:.6ф} секунди“ )
принт ( ф „Сортед() Тиме: {сортед_тиме:.6ф} сецондс“ )
принт ( ф „Време петље (мапе): {лооп_мап_тиме:.6ф} секунди“ )
принт ( ф „Време петље (филтер): {лооп_филтер_тиме:.6ф} секунди“ )
принт ( ф „Време петље (сортирано): {лооп_сортед_тиме:.6ф} секунди“ )

Вероватно ћемо приметити да су уграђене функције (мап(), филтер() и сортед()) брже од прилагођених петљи за ове уобичајене задатке. Уграђене функције у Питхон-у нуде сажетији и разумљивији приступ за обављање ових задатака и веома су оптимизоване за перформансе.

Оптимизујте петље

Ако је писање петљи неопходно, постоји неколико техника које можемо да урадимо да бисмо их убрзали. Генерално, петља ранге() је бржа од понављања уназад. То је зато што ранге() генерише итератор без инвертовања листе што може бити скупа операција за дугачке листе. Поред тога, пошто ранге() не прави нову листу у меморији, користи мање меморије.

ОптимизеЛооп.пи:

увоз Тимеи као тт
# Пример листе листе_бројева
бројеви_лист = листа ( домет ( 1 , 100000 ) )
# Функција за понављање листе обрнутим редоследом
деф лооп_реверсе_итератион ( ) :
ресулт_реверсе = [ ]
за ј ин домет ( само ( бројеви_лист ) - 1 , - 1 , - 1 ) :
ресулт_реверсе. додати ( бројеви_лист [ ј ] )
повратак ресулт_реверсе
# Функција за понављање листе користећи ранге()
деф лооп_ранге_итератион ( ) :
опсег_резултата = [ ]
за к ин домет ( само ( бројеви_лист ) ) :
опсег_резултата. додати ( бројеви_лист [ к ] )
повратак опсег_резултата
# Измери време потребно да се изврши обрнута итерација
реверсе_тиме = тт. Тимеи ( лооп_реверсе_итератион , број = 1000 )
# Измери време потребно да се изврши итерација опсега
опсег_време = тт. Тимеи ( лооп_ранге_итератион , број = 1000 )
принт ( „Листа бројева садржи 100000 записа“ )
принт ( ф „Време обрнуте итерације: {реверсе_тиме:.6ф} секунди“ )
принт ( ф „Време итерације опсега: {ранге_тиме:.6ф} секунди“ )

Избегавајте непотребне позиве функција

Има неких додатних трошкова сваки пут када се функција позове. Код ради брже ако се избегавају непотребни позиви функција. На пример, уместо да узастопно извршавате функцију која израчунава вредност, покушајте да сачувате резултат израчунавања у променљивој и користите га.

Алати за профилисање

Да бисмо сазнали више о перформансама вашег кода, поред уграђеног профилисања, можемо да користимо спољне пакете за профилисање као што су цПрофиле, Пифламе или СнакеВиз.

Цацхе Ресултс

Ако наш код треба да изврши скупе прорачуне, могли бисмо да размотримо кеширање резултата да бисмо уштедели време.

Рефакторинг кода

Рефакторисање кода ради лакшег читања и одржавања је понекад неопходан део оптимизације. Бржи програм такође може бити чистији.

Користите компилацију тачно на време (ЈИТ)

Библиотеке попут ПиПи или Нумба могу да обезбеде ЈИТ компилацију која може значајно да убрза одређене типове Питхон кода.

Надоградите Питхон

Уверите се да користите најновију верзију Питхона јер новије верзије често укључују побољшања перформанси.

Паралелизам и конкурентност

За процесе који се могу паралелизирати, истражите паралелне и технике синхронизације као што су вишепроцесна, нити или асинцио.

Запамтите да би бенчмаркинг и профилисање требало да буду главни покретачи оптимизације. Концентришите се на побољшање области нашег кода које имају најзначајније ефекте на перформансе и стално тестирајте своја побољшања да бисте били сигурни да имају жељене ефекте без уношења више недостатака.

Закључак

У закључку, оптимизација Питхон кода је кључна за побољшане перформансе и ефикасност ресурса. Програмери могу знатно повећати брзину извршавања и одзив својих Питхон апликација користећи различите технике као што су одабир одговарајућих структура података, коришћење уграђених функција, смањење додатних петљи и ефикасно управљање меморијом. Континуирано бенцхмаркинг и профилисање би требало да усмере напоре оптимизације, обезбеђујући да напредак кода одговара захтевима у стварном свету. Да би се гарантовао дугорочни успех пројекта и смањиле шансе за увођење нових проблема, оптимизација кода треба стално да буде балансирана са циљевима читљивости и могућности одржавања кода.