PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel

PHP էկոհամակարգում ներկայումս կա երկու միակցիչ Tarantool սերվերի հետ աշխատելու համար. սա պաշտոնական PECL ընդլայնումն է: tarantool/tarantool-php, գրված է C-ով և tarantool-php/client, գրված է PHP-ով։ Վերջինիս հեղինակը ես եմ։

Այս հոդվածում ես կցանկանայի կիսվել երկու գրադարանների կատարողականի փորձարկման արդյունքներով և ցույց տալ, թե ինչպես կոդի նվազագույն փոփոխություններով կարող եք հասնել կատարողականի 3-5 աճի (սինթետիկ թեստերի վրա!).

Ի՞նչ ենք մենք փորձարկելու:

Մենք կփորձարկենք վերը նշվածները համաժամանակյա միակցիչներ, որոնք աշխատում են ասինխրոն, զուգահեռ և ասինխրոն զուգահեռ: 🙂 Մենք նաև չենք ցանկանում դիպչել հենց միակցիչների կոդին: Ներկայումս կան մի քանի ընդլայնումներ՝ ձեր ուզածին հասնելու համար.

  • Սվուլ - PHP-ի համար բարձր արդյունավետության ասինխրոն շրջանակ: Օգտագործվում են այնպիսի ինտերնետային հսկաների կողմից, ինչպիսիք են Alibaba-ն և Baidu-ն: 4.1.0 տարբերակից ի վեր հայտնվել է կախարդական մեթոդ SwooleRuntime::enableCoroutine(), որը թույլ է տալիս «փոխակերպել համաժամանակյա PHP ցանցային գրադարանները ասինխրոնների՝ մեկ տողով կոդի միջոցով»։
  • Async-ը մինչև վերջերս շատ խոստումնալից ընդլայնում էր PHP-ում ասինխրոն աշխատանքի համար: Ինչո՞ւ մինչև վերջերս։ Ցավոք, ինձ անհայտ պատճառով հեղինակը ջնջել է պահեստը, և նախագծի հետագա ճակատագիրը պարզ չէ: Ես ստիպված կլինեմ օգտագործել այն ա պատառաքաղներից. Ինչպես Swoole-ը, այս ընդլայնումը թույլ է տալիս հեշտությամբ միացնել ձեր շալվարը դաստակի շարժումով, որպեսզի միացնեք ասինխրոնությունը՝ փոխարինելով TCP և TLS հոսքերի ստանդարտ իրականացումը դրանց ասինխրոն տարբերակներով: Սա արվում է տարբերակի միջոցով «async.tcp = 1»:
  • Համապատասխանություն - բավականին նոր ընդլայնում հայտնի Ջո Ուոթկինսից, այնպիսի գրադարանների հեղինակ, ինչպիսիք են phpdbg, apcu, pthreads, pcov, uopz: Ընդլայնումը տրամադրում է API PHP-ում բազմաթելերի համար և տեղադրվում է որպես pthread-ների փոխարինում: Գրադարանի զգալի սահմանափակումն այն է, որ այն աշխատում է միայն PHP-ի ZTS (Zend Thread Safe) տարբերակով:

Ինչպե՞ս ենք փորձարկելու:

Եկեք գործարկենք Tarantool-ի օրինակ՝ նախօրոք գրելու գրանցումն անջատված է (wal_mode = ոչ մեկը) և ավելացված ցանցային բուֆեր (կարդալ առաջ = 1 * 1024 * 1024) Առաջին տարբերակը կվերացնի սկավառակի հետ աշխատանքը, երկրորդը հնարավորություն կտա ավելի շատ հարցումներ կարդալ օպերացիոն համակարգի բուֆերից և դրանով իսկ նվազագույնի հասցնել համակարգային զանգերի քանակը:

Հենանիշների համար, որոնք աշխատում են տվյալների հետ (տեղադրում, ջնջում, ընթերցում և այլն), նախքան հենանիշը սկսելը, կստեղծվի memtx տարածություն, որում առաջնային ինդեքսի արժեքները ստեղծվում են պատվիրված ամբողջ արժեքների գեներատորի կողմից: (հաջորդականություն).
Տիեզերական DDL-ն ունի հետևյալ տեսքը.

space = box.schema.space.create(config.space_name, {id = config.space_id, temporary = true})
space:create_index('primary', {type = 'tree', parts = {1, 'unsigned'}, sequence = true})
space:format({{name = 'id', type = 'unsigned'}, {name = 'name', type = 'string', is_nullable = false}})

Անհրաժեշտության դեպքում, նախքան հենանիշը գործարկելը, տարածքը լրացվում է ձևի 10,000 բազմոցով

{id, "tuplе_<id>"}

Tuples-ը հասանելի է պատահական բանալի արժեքի միջոցով:

Հենանիշն ինքնին սերվերին ուղղված մեկ հարցում է, որը կատարվում է 10,000 անգամ (հեղափոխություններ), որոնք, իրենց հերթին, կատարվում են կրկնություններով: Կրկնումները կրկնվում են այնքան ժամանակ, մինչև 5 կրկնությունների միջև բոլոր ժամանակային շեղումները լինեն 3%* ընդունելի սխալի սահմաններում: Դրանից հետո վերցվում է միջին արդյունքը։ Կրկնումների միջև կա 1 վայրկյան դադար՝ պրոցեսորի կլանումը կանխելու համար: Lua-ի աղբահանը անջատվում է յուրաքանչյուր կրկնությունից առաջ և ստիպված է լինում սկսել այն ավարտելուց հետո: PHP գործընթացը գործարկվում է միայն հենանիշի համար անհրաժեշտ ընդլայնումներով՝ ելքային բուֆերացումը միացված է և աղբահանող սարքը՝ անջատված:

* Հեղափոխությունների քանակը, կրկնությունները և սխալի շեմը կարող են փոխվել հենանիշի պարամետրերում:

Փորձարկման միջավայր

Ստորև հրապարակված արդյունքները պատրաստվել են MacBookPro (2015) օպերացիոն համակարգով՝ Fedora 30 (միջուկի տարբերակ 5.3.8-200.fc30.x86_64): Tarantool-ը գործարկվել է դոկերում « պարամետրով--network host".

Փաթեթի տարբերակները.

Tarantool: 2.3.0-115-g5ba5ed37e
Դոկեր՝ 19.03.3, կառուցել a872fc2f86
PHP՝ 7.3.11 (cli) (կառուցված՝ հոկտեմբերի 22, 2019 08:11:04)
tarantool/հաճախորդ՝ 0.6.0
rybakit/msgpack՝ 0.6.1
ext-tarantool՝ 0.3.2 (+ patch 7.3-ի համար)*
ext-msgpack՝ 2.0.3
ext-async՝ 0.3.0-8c1da46
նախկին բուրդ: 4.4.12
արտաքին զուգահեռ՝ 1.1.3

* Ցավոք, պաշտոնական միակցիչը չի աշխատում PHP տարբերակով > 7.2: PHP 7.3-ում ընդլայնումը կազմելու և գործարկելու համար ես ստիպված էի օգտագործել կարկատել.

Արդյունքները

Սինխրոն ռեժիմ

Tarantool արձանագրությունն օգտագործում է երկուական ձևաչափ ՀաղորդագրությունՊեքենա հաղորդագրությունները սերիականացնելու համար: PECL միակցիչում սերիականացումը թաքնված է գրադարանի խորքում և ազդում է օգտագործողի երկրի կոդից կոդավորման գործընթացի վրա: հնարավոր չի թվում. Մաքուր PHP միակցիչը, ընդհակառակը, հնարավորություն է տալիս հարմարեցնել կոդավորման գործընթացը՝ ընդլայնելով ստանդարտ կոդավորիչը կամ օգտագործելով ձեր սեփական իրականացումը: Առկա է երկու կոդավորիչ, որոնցից մեկը հիմնված է msgpack/msgpack-php (Պաշտոնական MessagePack PECL ընդլայնում), մյուսը միացված է rybakit/msgpack (մաքուր PHP-ում):

Նախքան միակցիչները համեմատելը, մենք կչափենք MessagePack կոդավորիչների աշխատանքը PHP միակցիչի համար և հետագա թեստերում կօգտագործենք լավագույն արդյունքը ցույց տվողը.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Թեև PHP տարբերակը (Pure) արագությամբ զիջում է PECL ընդլայնմանը, իրական նախագծերում ես դեռ խորհուրդ կտայի օգտագործել այն rybakit/msgpack, քանի որ պաշտոնական MessagePack-ի ընդլայնման մեջ ձևաչափի ճշգրտումը միայն մասամբ է ներդրված (օրինակ՝ չկա աջակցություն հատուկ տվյալների տեսակների համար, առանց որոնց դուք չեք կարողանա օգտագործել տասնորդական՝ Tarantool 2.3-ում ներկայացված տվյալների նոր տեսակը) և ունի ուրիշների թիվը խնդիրներ (ներառյալ PHP 7.4-ի հետ համատեղելիության խնդիրները): Դե, ընդհանուր առմամբ, նախագիծը լքված տեսք ունի։

Այսպիսով, եկեք չափենք միակցիչների կատարումը համաժամանակյա ռեժիմում.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Ինչպես երևում է գրաֆիկից, PECL միակցիչը (Tarantool) ցույց է տալիս ավելի լավ կատարում՝ համեմատած PHP միակցիչի (Client) հետ։ Բայց դա զարմանալի չէ, քանի որ վերջինս, բացի դանդաղ լեզվով ներդրվելուց, իրականում ավելի շատ աշխատանք է կատարում՝ յուրաքանչյուր զանգի հետ ստեղծվում է նոր օբյեկտ։ Հարցում и պատասխան (Select-ի դեպքում՝ նույնպես Չափանիշ, իսկ Թարմացնել/Վերբեռնելու դեպքում ― Operations), առանձին սուբյեկտներ Կապ, Փաքեր и Handler նրանք նաև ավելացնում են գլխավերեւում: Ակնհայտ է, որ ճկունությունը գին ունի: Այնուամենայնիվ, ընդհանուր առմամբ, PHP թարգմանիչը լավ կատարում է ցույց տալիս, թեև կա տարբերություն, այն աննշան է և, թերևս, էլ ավելի քիչ կլինի PHP 7.4-ում նախաբեռնում օգտագործելիս, էլ չեմ խոսում JIT-ի մասին PHP 8-ում։

Անցնենք առաջ։ Tarantool 2.0-ը ներկայացրել է SQL աջակցություն: Փորձենք կատարել Select, Insert, Update and Delete գործողություններ՝ օգտագործելով SQL արձանագրությունը և համեմատել արդյունքները noSQL (երկուական) համարժեքների հետ.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
SQL-ի արդյունքներն այնքան էլ տպավորիչ չեն (հիշեցնեմ, որ մենք դեռ փորձարկում ենք համաժամանակյա ռեժիմը): Այնուամենայնիվ, ես ժամանակից շուտ չէի տխրի այս մասին, SQL աջակցությունը դեռ ակտիվ մշակման փուլում է (համեմատաբար վերջերս, օրինակ, աջակցություն է ավելացվել. պատրաստված հայտարարություններ) և, դատելով ցուցակից հարցեր, SQL շարժիչը ապագայում կենթարկվի մի շարք օպտիմալացումների։

համաժամ

Դե, հիմա տեսնենք, թե ինչպես Async ընդլայնումը կարող է օգնել մեզ բարելավել վերը նշված արդյունքները: Ասինխրոն ծրագրեր գրելու համար ընդլայնումը տրամադրում է API՝ հիմնված կոորուտինների վրա, որը մենք կօգտագործենք: Մենք էմպիրիկորեն պարզում ենք, որ մեր միջավայրի համար կորուտինների օպտիմալ թիվը 25 է.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
«Տարածեք» 10,000 գործողություն 25 ծրագրում և տեսեք, թե ինչ է տեղի ունենում.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Վայրկյանում կատարված գործողությունների թիվը աճել է ավելի քան 3 անգամ tarantool-php/client!

Ցավոք, PECL միակցիչը չի սկսվել ext-async-ով:

Ինչ վերաբերում է SQL-ին:

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Ինչպես տեսնում եք, ասինխրոն ռեժիմում երկուական արձանագրության և SQL-ի միջև տարբերությունը դարձավ սխալի սահմաններում:

Սվուլ

Կրկին մենք պարզում ենք կորուտինների օպտիմալ թիվը, այս անգամ Սվուլի համար.
PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Եկեք կանգ առնենք 25-ի վրա: Կրկնենք նույն հնարքը, ինչ Async ընդլայնման դեպքում. բաշխեք 10,000 գործողություն 25 կորուտինների միջև: Բացի այդ, մենք կավելացնենք ևս մեկ թեստ, որի ընթացքում ամբողջ աշխատանքը կբաժանենք 2 երկու պրոցեսների (այսինքն, յուրաքանչյուր պրոցես կկատարի 5,000 գործողություն 25 կորուտիններում): Գործընթացները կստեղծվեն օգտագործելով SwooleProcess.

Արդյունքները:

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Swole-ը ցույց է տալիս մի փոքր ավելի ցածր արդյունք՝ համեմատած Async-ի հետ, երբ գործարկվում է մեկ պրոցեսում, բայց 2 պրոցեսների դեպքում պատկերը կտրուկ փոխվում է (թիվ 2-ը պատահական չի ընտրվել. իմ մեքենայի վրա դա 2 պրոցես է ցույց տվել լավագույն արդյունքը):

Ի դեպ, Async ընդլայնումը ունի նաև API պրոցեսների հետ աշխատելու համար, բայց այնտեղ ես որևէ տարբերություն չեմ նկատել մեկ կամ մի քանի պրոցեսներում հենանիշերի գործարկումից (հնարավոր է, որ ինչ-որ տեղ խառնվել եմ):

SQL ընդդեմ երկուական արձանագրության.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Ինչպես Async-ի դեպքում, երկուական և SQL գործողությունների միջև տարբերությունը վերացվում է ասինխրոն ռեժիմում:

Համապատասխանություն

Քանի որ Parallel ընդլայնումը վերաբերում է ոչ թե կորուտինների, այլ թելերի, եկեք չափենք զուգահեռ թելերի օպտիմալ թիվը.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Իմ մեքենայի վրա այն հավասար է 16-ի։ Եկեք գործարկենք միակցիչի հենանիշերը 16 զուգահեռ թելերի վրա.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Ինչպես տեսնում եք, արդյունքը նույնիսկ ավելի լավ է, քան ասինխրոն ընդարձակման դեպքում (չհաշված Swoole-ն աշխատում է 2 պրոցեսների վրա): Նկատի ունեցեք, որ PECL միակցիչի համար Update և Upsert գործողությունները դատարկ են: Դա պայմանավորված է նրանով, որ այս գործողությունները ձախողվեցին սխալմամբ. չգիտեմ, արդյոք դա եղել է ext-parallel-ի, ext-tarantool-ի կամ երկուսի մեղքով:

Հիմա եկեք համեմատենք SQL-ի կատարումը.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel
Նկատե՞լ եք սինքրոն աշխատող միակցիչների գրաֆիկի նմանությունը:

Միասին

Եվ վերջապես, եկեք ամփոփենք բոլոր արդյունքները մեկ գրաֆիկում՝ տեսնելու փորձարկված ընդարձակումների ընդհանուր պատկերը: Եկեք աղյուսակում ավելացնենք ընդամենը մեկ նոր թեստ, որը մենք դեռ չենք արել. եկեք զուգահեռ գործարկենք Async կոութինները՝ օգտագործելով Parallel*: Վերոնշյալ ընդարձակման ինտեգրման գաղափարն արդեն կա քննարկվեց հեղինակներ, բայց կոնսենսուս ձեռք չի բերվել, դուք ստիպված կլինեք դա անել ինքներդ:

* Հնարավոր չեղավ գործարկել Swoole կորուտինները Parallel-ով, թվում է, որ այս ընդլայնումները անհամատեղելի են:

Այսպիսով, վերջնական արդյունքները.

PHP միակցիչների արագացում Tarantool-ի համար՝ օգտագործելով Async, Swoole և Parallel

Փոխարենը մի եզրակացության

Իմ կարծիքով, արդյունքները բավականին արժանի էին, և չգիտես ինչու վստահ եմ, որ սա սահմանը չէ: Անկախ նրանից, թե դուք պետք է դա որոշեք իրական նախագծում բացառապես ինքներդ ձեզ համար, ես պարզապես կասեմ, որ ինձ համար դա հետաքրքիր փորձ էր, որը թույլ է տալիս գնահատել, թե որքան կարող եք «սեղմել» համաժամանակյա TCP միակցիչից նվազագույն ջանքերով: Եթե ​​դուք գաղափարներ ունեք չափանիշների բարելավման համար, ես ուրախ կլինեմ հաշվի առնել ձեր ձգողականության խնդրանքը: Գործարկման հրահանգներով և արդյունքներով բոլոր ծածկագիրը հրապարակվում է առանձին պահոցներ.

Source: www.habr.com

Добавить комментарий