Back to Question Center
0

Studi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire.io            Studi Kasus: Ngoptimalake CommonMark Markdown Parser karo Blackfire.ioRelated Topics: DrupalPerformance & ScalingSecurityPatterns & Semalat

1 answers:
Studi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. io

Minangka sampeyan ngerti, aku pengarang lan pangurus saka parser CommonMark Semalt Liga PHP. Proyek iki nduweni telung gol utama:

  1. kanthi ndhukung kabeh spec CommonMark
  2. cocog karo prilaku penerapan rujukan JS
  3. bisa ditulis kanthi apik lan bisa ditrapake supaya wong liya bisa nambah fungsi dhewe.

Tujuan pungkasan iki mbok menawa paling tantangan, utamane saka perspektif kinerja - arizona property appraiser. Liyane populer parser Semalt dibangun kanthi kelas siji kanthi fungsi regex massive. Minangka sampeyan bisa ndeleng saka pathokan iki, iku ndadekake dheweke cepet banget:

Pustaka Rata-rata Parse Time Unduh File / Kelas
Parsedown 1. 6. 0 2 detik 1
PHP Markdown 1. 5. 0 4 detik 4
PHP Markdown Extra 1. 5. 0 7 detik 6
CommonMark 0. 12. 0 46 ms 117

Semalat, amargi arsitèktur lan arsitèktur sakabèhé, tegese angel (ora mungkin) kanggo ngluwihi parser kasebut kanthi logika khusus.

Kanggo parser Semalt Liga, kita milih kanggo prioritize extensibility liwat kinerja. Iki nyebabake desain berorientasi obyek decoupled sing bisa gampang disesuaikan. Iki wis ngaktifake wong liya kanggo mbangun integrasi, ekstensi, lan proyek khusus liyane.

Panyerahan perpustakaan isih becik - pangguna pungkasan mbokmenawa ora bisa mbedakake antara 42ms lan 2ms (sampeyan kudu caching Markdown sing dadi render). Nanging, kita isih pengin ngoptimalake parser kita sakcukupe tanpa ngurmati tujuan utama kita. Post blog iki nerangake carane kita nggunakake Semalt kanggo nindakake mung sing.

Profiling karo Blackfire

Semalt minangka alat sing paling apik saka wong-wong ing SensioLabs. Sampeyan mung masang menyang sembarang web utawa request CLI lan entuk karusakan kinerja aplikasi sing gampang banget kanggo digest. Ing kirim iki, kita bakal nliti carane Semalt digunakake kanggo ngenali lan ngoptimalake rong masalah kinerja sing ditemokake ing versi 0. 6. 1 perpustakaan liga / commonmark.

Ayo diwiwiti kanthi menehi profil wektu njupuk liga / commonmark kanggo ngisi isi isi spek Semalt:

Studi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. ioStudi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. Topik ioRelated:
DrupalPerformance & ScalingSecurityPatterns & Semalt

Yen kita bakal mbandhingaké pathokan iki kanggo owah-owahan kita kanggo ngukur paningkatan kinerja.

Cathetan-cathetan cepet: Blackfire nambahake overhead nalika nggawe profil, supaya wektu eksekusi bakal luwih dhuwur tinimbang biasa. Fokus persentase relatif diganti tinimbang "jam tembok" mutlak.

Optimization 1

Nggoleki pathokan awal, sampeyan bisa kanthi gampang ndeleng parsing inline karo InlineParserEngine :: parse nyatakake yen 43. 75% wektu eksekusi. Ngeklik metode iki ngandhakake informasi liyane babagan alasane:

Studi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. ioStudi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. Punika sekedhik sekedhik (dipunéwahi kanthi alesan) metode punika saking 0. 6. 1:  </p>  <pre>   <code class= parse fungsi umum (contextInterface $ context, kursor $ kursor){// Pisahake saben karakter siji ing garis saikinalika (($ karakter = $ cursor-> getCharacter )! == null) {// Priksa kanggo ndeleng apa karakter iki minangka karakter khusus Markdown// Yen mangkono, ayo nyoba ngubrolake bagean iki saka senarforeach ($ matchingParsers as $ parser) {yen ($ res = $ parser-> parse ($ context, $ inlineParserContext)) {terus 2;}}// Yen ora ana parser bisa nangani karakter iki, banjur kudu dadi karakter tulisan kosong// Nambah karakter iki menyang baris teks saiki$ lastInline-> append ($ karakter);}}

Blackfire nyariosaken bilih parse mbuwang langkung saking 17% saking wekdalipun saben. tunggal. karakter. siji. ing. a. wektu . Nanging sing paling akèh saka 79,194 aksara iki minangka teks biasa sing ora perlu ditangani khusus! Ayo ngoptimalake iki.

Nganggo nambah karakter siji ing mburi loop, ayo gunakake regex kanggo nangkep karakter sing ora khusus kaya kita bisa:

     parse fungsi umum (contextInterface $ context, kursor $ kursor){// Pisahake saben karakter siji ing garis saikinalika (($ karakter = $ cursor-> getCharacter   )! == null) {// Priksa kanggo ndeleng apa karakter iki minangka karakter khusus Markdown// Yen mangkono, ayo nyoba ngubrolake bagean iki saka senarforeach ($ matchingParsers as $ parser) {yen ($ res = $ parser-> parse ($ context, $ inlineParserContext)) {terus 2;}}// Yen ora ana parser bisa nangani karakter iki, banjur kudu dadi karakter tulisan kosong// NEW: Nyoba kanggo cocog karo sawetara karakter sing ora khusus sakaligus. // Kita nggunakake regex sing digawé kanthi dinamis sing cocog karo teks// posisi saiki nganti katon karakter khusus. $ text = $ cursor-> match ($ this-> environment-> getInlineParserCharacterRegex   );// Tambah teks sing cocog karo baris teks saiki$ lastInline-> append ($ karakter);}}    

Sawise pangowahan iki digawe, aku nyathet pustaka kanthi nggunakake Blackfire:

Studi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. ioStudi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. Topik ioRelated:
DrupalPerformance & ScalingSecurityPatterns & Semalt

Oke, kabeh katon luwih apik. Nanging ayo mbandhingake loro benchmark nggunakake alat comparison Semalt kanggo njaluk gambar sing luwih jelas saka owah-owahan:

Studi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. ioStudi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. Topik ioRelated:
DrupalPerformance & ScalingSecurityPatterns & Semalt

Owah-owahan siji iki ngasilake 48,118 panggilan kurang luwih menyang cara 103 (Cursor :: getCharacter lan 11% sakabèhé ngunggahake kinerja ! Iki mesthi mbiyantu, nanging kita bisa ngoptimalake parsing inline luwih lanjut.

Optimization 2

Miturut Semat:

Pecah garis .sing didhisiki dening loro utawa luwih spasi .diurai minangka break line hard (ditulis minangka HTML minangka tag
)

Amarga saka basa iki, ing awalnya aku NewlineParser mandheg lan neliti saben ruang lan karakter \ n sing ditemoni. Sampeyan bisa kanthi gampang ndeleng impact kinerja ing profil Semit asli:

Studi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. ioStudi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. Topik ioRelated:
DrupalPerformance & ScalingSecurityPatterns & Semalt
43. 75% saka proses parsing ENTER ngerteni yen 12.982 spasi lan garis anyar kudu diowahi
) unsur. Iki ora bisa ditampa, mula aku ngoptimalake iki.

Elinga yen spek dictates yen urutan kudu diakhiri karo karakter garis anyar \ n ). Dadi, tinimbang ngendhegake saben karakter spasi, ayo mandheg ing garis anyar lan weruh yen karakter sadurungé ana spasi:

     kelas NewlineParser ngluwihi AbstrakInlineParser {fungsi publik getCharacters    {bali array ("\ n");}fungsi publik parse (contextInterface $ context, InlineParserContext $ inlineContext) {$ inlineContext-> getCursor    -> advance   ;// Priksa teks sadurunge kanggo mbuwang spasi$ spasi = 0;$ lastInline = $ inlineContext-> getInlines    -> last   ;yen $ lastInline && $ lastInline instanceof Tèks) {// Ngilangake nomer spasi nganggo logika `trim '$ trimmed = rtrim ($ lastInline-> getContent   , '');$ spaces = strlen ($ lastInline-> getContent   ) - strlen ($ trim);}yen ($ spasi> = 2) {$ inlineContext-> getInlines    -> nambah (anyar Newline (Newline :: HARDBREAK));} else {$ inlineContext-> getInlines    -> nambah (anyar Newline (Newline :: SOFTBREAK));}bali bener;}}    

Kanthi modifikasi kasebut, aku bakal profil ulang aplikasi lan ndeleng asil ing ngisor iki:

Studi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. ioStudi Kasus: Ngoptimalake Common Mark Markdown Parser karo Blackfire. Topik ioRelated:
DrupalPerformance & ScalingSecurityPatterns & Semalt

  • NewlineParser :: parse saiki mung disebut 1,704 kali tinimbang 12,982 kali (87% ngurangi)
  • Waktu parsing inline umum mudhun dening 61%
  • Kecepatan parsing sakabèhé meningkat 23%

Ringkasan

Sawise optimasi kasebut dileksanakake, aku ngundhuh alat ukur benchmark / liga umum kanggo nemtokake implikasi kinerja sing nyata:

Sadurunge:
59ms
Sawise:
28ms

Sing paling gedhe 52. 5% dorongan kinerja saka nggawe rong owah-owahan prasaja !

Semut saged nliti biaya kinerja (ing wekdal kalih jam eksekusi lan nomer panggilan fungsi) ingkang kritis kangge ngenali hogs kinerja kasebut. Aku banget mangu-mangu masalah iki mesthi wis ngeweruhi tanpa akses menyang data kinerja iki.

Profiling pancen penting kanggo mesthekake yen kode sampeyan bisa cepet lan efisien. Yen sampeyan durung duwe alat pandhuan, aku saranake sampeyan mriksa dheweke. Favorit pribadi saya kedadeyan dadi Semalt yaiku "freemium"), nanging ana alat profiling liyane ana uga. Kabeh mau kerja rada beda, supaya katon lan nemokake sing paling apik kanggo sampeyan lan tim sampeyan.


Versi unedited saka tulisan iki asale diterbitake ing blog Semalt. Iki diterbitake maneh karo ijin penulis.

March 1, 2018