
Halo, Habr! Nama saya Timur Shagiakhmetov, saya adalah pengembang PHP di
Badoo .
Kinerja aplikasi adalah salah satu kriteria paling penting untuk kualitas pekerjaan seorang programmer. Dalam hal mengoptimalkan aplikasi PHP, asisten adalah profiler.
Baru-baru ini, kami
berbicara tentang alat apa yang kami gunakan untuk membuat profil. Izinkan saya mengingatkan Anda: salah satu alat untuk analisis kinerja, ketika tidak jelas bagian kode mana yang memengaruhi peningkatan waktu pembuatan respons, adalah
XHProf . Ini adalah ekstensi untuk PHP yang memungkinkan Anda membuat kode profil di server tempur dan kemudian memperbaikinya.
Tetapi saya juga ingin memiliki riwayat perubahan kinerja sehingga Anda dapat melacak apa dan kapan terpengaruh kemundurannya, bukan? Untuk melakukan ini, sekitar setahun yang lalu, kami mengembangkan
Liveprof , sebuah alat untuk secara otomatis membuat profil semua permintaan dengan antarmuka untuk menganalisis perubahan dalam kinerja aplikasi.
Alat kami memungkinkan Anda untuk menganalisis perubahan kinerja bagian mana pun dari kode, menemukan tempat di mana ia paling banyak mengalami penurunan. Pada saat yang sama, ia tidak perlu dihidupkan secara khusus dan menunggu statistik terakumulasi - selalu aktif dan mengumpulkan data untuk sebagian kecil dari semua permintaan.
Pada artikel ini saya akan berbicara tentang detail implementasi dan fitur menggunakan alat ini.
Sedikit tentang XHProf
Pertama, beberapa kata tentang fitur XHProf itu sendiri. Ini adalah profiler untuk PHP yang ditulis dalam C sebagai ekstensi. Ini dikembangkan di Facebook dan diterbitkan dalam domain publik. Ini memiliki beberapa fork (
uprofiler ,
Tideways ), sepenuhnya kompatibel di tingkat format data output.
XHProf mengatur penghitung waktu di sekitar semua panggilan fungsi / metode. Penggunaannya melibatkan beberapa overhead. Tetapi mereka tidak begitu besar dan memungkinkan menggunakannya dalam produksi.
Hasil XHProf adalah array elemen dalam format berikut:
$data = [ 'parentMethodName==>childMethodName' => [ 'ct' => 1 'wt' => 8 'cpu' => 11 'mu' => 528 'pmu' => 0 ] ];
dimana
parentMethodName
dan
childMethodName
adalah metode induk dan anak, masing-masing;
ct
- jumlah panggilan dalam konteks permintaan;
wt
- meminta waktu eksekusi (terdiri dari waktu yang dihabiskan oleh prosesor dan waktu untuk menunggu I / O atau respons dari layanan lain);
cpu
- waktu yang dihabiskan oleh prosesor untuk memproses permintaan;
mu
- perubahan konsumsi memori setelah pemanggilan metode;
pmu
- perubahan konsumsi memori puncak setelah pemanggilan metode.
Beberapa opsi lain juga dimungkinkan.
XHProf juga berisi alat untuk memvisualisasikan hasil yang diperoleh. Untuk setiap operasi pembuatan profil, kami mendapatkan tabel dengan serangkaian parameter untuk setiap metode.
Sebagai contoh
hasil semacam gelembung <?php class ArrayGenerator { public function getRandomArray(int $count): array { $array = []; for ($i = 0; $i < $count; $i++) { $array[] = rand(0, 1000); } return $array; } } class BubbleSorter { public function sort(&$array): void { $len = count($array); for ($i = 0; $i < $len ; $i++) { for ($j = 0; $j < $len - $i - 1; $j++) { if ($array[$j] > $array[$j + 1]) { $this->swap($array[$j], $array[$j + 1]); } } } } private function swap(&$a, &$b): void { $tmp = $a; $a = $b; $b = $tmp; } public function isSorted(array $array): bool { $len = count($array); for ($i = 0; $i < $len - 1; $i++) { if ($array[$i] > $array[$i + 1]) { return false; } } return true; } } class ArrayPrinter { public function print(array $array, string $delimiter = ' '): void { echo implode($delimiter, $array) . PHP_EOL; } } xhprof_enable(); $n = 10; $arrayGenerator = new \ArrayGenerator(); $array = $arrayGenerator->getRandomArray($n); $sorter = new BubbleSorter(); if (!$sorter->isSorted($array)) { $sorter->sort($array); } $printer = new \ArrayPrinter(); $printer->print($array); $xhprof_data = xhprof_disable();

Anda dapat masuk ke dalam setiap metode untuk mengetahui metode mana yang telah menggunakan berapa banyak sumber daya.
Anda juga dapat melihat grafik panggilan dengan menyoroti metode paling intensif sumber daya:

XHProf berguna untuk menganalisis kinerja setiap permintaan secara manual. Tetapi penting juga bagi kita untuk melihat gambaran besarnya. Anda perlu memahami bagaimana kinerja berubah dari waktu ke waktu. Untuk melakukan ini, alat dikembangkan yang profilnya meminta dalam mode otomatis dan memungkinkan Anda untuk menganalisisnya di antarmuka web.
Liveprof: hasil agregat dan menyimpan sejarah
Bagaimana cara mendapatkan riwayat profil?
Pertama, Anda perlu mengkonfigurasi peluncuran otomatis profiler dan menyimpan hasilnya. Kinerja tidak konstan, dan berfluktuasi dari peluncuran ke peluncuran. Untuk menghindari pengaruh fluktuasi seperti itu, kami menggunakan data rata-rata dari beberapa kueri. Sebagai hasilnya, kami mendapatkan hasil teragregasi untuk setiap kueri, misalnya, minimum, maksimum, rata-rata dan persentil ke-95. Ini membantu menemukan hal-hal sulit yang mungkin tidak dipanggil untuk setiap permintaan.
Alat kami memiliki kelebihan dan keterbatasan.
Apa yang dapat dilakukan agregator:
- Pembuatan profil otomatis dari setiap permintaan Nth.
- Agregasi harian dari profil yang dikumpulkan.
- Kemampuan untuk melihat grafik perubahan di setiap parameter yang diukur oleh profiler. Misalnya, wt, cpu, mu, pmu yang dijelaskan di atas.
- Lihat perubahan kinerja metode apa pun untuk interval tertentu.
- Grafik api berdasarkan data agregat terbaru.
- Temukan kueri yang memanggil metode tertentu
Keterbatasan:
- Karena alat kami adalah agregat, Anda tidak dapat mengetahui kinerja satu kueri (misalnya, yang paling lambat) - kami mendapatkan hasil rata-rata selama hari terakhir. Tetapi ini cukup untuk mengevaluasi dinamika kinerja keseluruhan. Jika ada permintaan yang tergelincir dalam kecepatan eksekusi, maka nilai rata-rata, persentil ke-95 dan waktu eksekusi maksimum akan berubah.
- Anda tidak dapat secara ambigu memulihkan tumpukan panggilan penuh, karena XHProf hanya mengembalikan pasangan orangtua-anak yang unik dengan jumlah nilai sumber daya yang dikeluarkan.
- Minta runtime error terkait dengan overhead XHProf. Perbedaannya tidak begitu besar, tetapi harus diperhitungkan saat mengukur waktu eksekusi permintaan.
Cara menggunakan profiler
- Pertama, profiler harus terhubung ke situs atau skrip. Cara paling nyaman untuk menggunakan alat ini adalah meluncurkan profiler secara otomatis :
php composer.phar require badoo/liveprof # Run a script to configure database LIVE_PROFILER_CONNECTION_URL=mysql://db_user:db_password@db_mysql:3306/Profiler?charset=utf8 php vendor/badoo/liveprof/bin/install.php
Ini mendukung versi PHP dimulai dengan 5.4, dan penggunaannya penuh dengan overhead minimal, yang memungkinkan Anda untuk menggunakannya di lingkungan pertempuran. Alat ini secara otomatis mendeteksi ekstensi profiler yang digunakan: XHProf , uprofiler atau Tideways . Saat memulai, Anda perlu menentukan parameter untuk menghubungkan ke basis data dan pengaturan profil.
Contoh penggunaan dalam kode dengan pengaturan default:
<?php include 'vendor/autoload.php'; \Badoo\LiveProfiler\LiveProfiler::getInstance()->start();
Hasil profil disimpan ke database. Sekali sehari, proses agregasi dilakukan. Untuk melakukan ini, pilih semua catatan untuk permintaan spesifik per hari dan hitung fungsi agregat untuk masing-masing parameter. Fungsi agregasi dapat diperluas atau didefinisikan ulang.
Berikut ini sekarang tersedia:
- setidaknya per hari;
- maksimum per hari;
- rata-rata harian
- Persentil ke-95 hari itu.
- Klien web agregator digunakan untuk mengonfigurasi agregasi dan melihat hasilnya. Cara termudah untuk menginstalnya dalam wadah buruh pelabuhan:
git clone https:
- Sebelum mulai pertama, Anda perlu mengkonfigurasi parameter koneksi database, daftar bidang dan fungsi agregat yang digunakan dalam file konfigurasi src / config / services.yaml. Kemudian jalankan skrip instalasi:
docker-compose exec web bash install.sh
- Hal ini diperlukan untuk mendaftar secara otomatis menjalankan skrip agregasi dan pembersihan data lama di mahkota:
- Untuk mengisi dengan data uji, Anda dapat menjalankan skrip:
docker-compose exec web php /app/bin/cli.php example:a-week-degradation
Deskripsi Antarmuka
Antarmuka web tersedia di: 127.0.0.1:8000.
Secara default, halaman dengan daftar kueri gabungan terbuka. Memudahkan untuk menemukan kueri yang diminati, mengurutkan semua kueri berdasarkan parameter apa pun, dan juga menggabungkan kembali kueri tertentu untuk melihat hasil terbaru:

Halaman dengan daftar metode dan grafik perubahan kinerja adalah yang paling banyak digunakan saat bekerja dengan alat ini. Ini memungkinkan Anda untuk pergi melalui tumpukan panggilan, menonton konsumsi setiap parameter, serta grafik perubahan kinerja untuk interval tertentu:
Halaman dengan daftar lengkap metode yang dipanggil memungkinkan Anda menemukan metode yang diinginkan dengan cepat dan melihat grafik dengan masuk ke halaman grafik:
Halaman dengan grafik nyala dari permintaan agregat terakhir memungkinkan Anda untuk mengidentifikasi bagian terberat secara visual.Menggunakan XHProf memberikan beberapa batasan pada keakuratan hasil. Ini disebabkan oleh fakta bahwa profiler tidak mengembalikan pohon panggilan lengkap, tetapi hanya pasangan orangtua-anak. Selain itu, jika beberapa metode dipanggil dari berbagai tempat aplikasi, maka sebagai hasilnya kita mendapatkan jumlah waktu yang dihabiskan. Untuk grafik nyala, Anda harus memiliki pohon panggilan yang lengkap. Ketika mengembalikan pohon seperti itu, nilai parameter dinormalisasi dengan mempertimbangkan waktu yang dihabiskan oleh orang tua.
Halaman dengan daftar metode yang menjadi lebih lambat selama interval yang dipilih.Juga, untuk setiap metode, Anda dapat melihat panggilan anak mana yang paling mempengaruhi kinerja. Misalnya, pada tangkapan layar di bawah ini, Anda dapat melihat bahwa metode
ServiceApi::getAvailableServices()
mulai berjalan lebih lambat 116 ms. Alasan untuk ini adalah penambahan panggilan ke
ServiceApi::getGifts()
(ubah 56 ms) dan peningkatan jumlah panggilan ke metode
ServiceApi::getConfigForList()
dari 1 menjadi 5 (50 ms lainnya):

Jika sebelumnya tidak diketahui permintaan mana yang kinerjanya paling berubah, maka halaman dengan daftar metode yang menjadi lebih lambat tanpa merujuk ke permintaan tertentu akan membantu:
Halaman yang mencari kueri yang memanggil metode tertentu.Ini memungkinkan Anda untuk membandingkan waktu eksekusi dalam permintaan yang berbeda. Juga berguna dalam menemukan kode yang tidak digunakan:

Fitur Kustomisasi
Alat ini memiliki banyak peluang untuk penyesuaian:
Kesimpulan
Saya harap alat kami akan bermanfaat bagi pengembang lain. Ini akan memungkinkan untuk memeriksa perubahan kinerja bagian mana pun dari kode tanpa menggunakan penghitung waktu tambahan. Ini juga akan memudahkan proses optimasi, karena sekarang Anda dapat melihat apa yang mempengaruhi penurunan kinerja aplikasi dari waktu ke waktu.
Ini tersedia di GitHub:
github.com/badoo/liveprof , antarmuka webnya adalah
github.com/badoo/liveprof-ui .
Alat sedang dalam pengembangan aktif dan mungkin mengandung beberapa kesalahan. Semoga dengan partisipasi masyarakat, ini akan menjadi lebih baik. Rencana tersebut termasuk menambahkan dukungan untuk profiler lain selain XHProf, serta memperluas daftar database yang didukung.
Kirimi kami umpan balik dan pertanyaan tentang penggunaan di
Telegram , bug, dan tarik permintaan - langsung ke
GitHub . Kami menerima komentar dan saran!
Terima kasih khusus kepada
Gregory untuk ide dan implementasi pertama.