Bagaimana cara paling mudah mengidentifikasi kemacetan dalam performa render React?

Aug 15 2020

Saya mengalami masalah dengan mengidentifikasi kemacetan dalam kinerja render saat bekerja pada penampil JSON. Dengan sedikit elemen, ini bekerja dengan baik, tetapi pada titik tertentu menjadi sangat lambat.

Memeriksa profiler, tampaknya elemen dirender cukup cepat, tetapi saya telah memperhatikan beberapa masalah yang saya tidak yakin bagaimana cara mengejarnya.

Gambaran

  • Aplikasi ini adalah penampil JSON yang memungkinkan Anda memperluas / meminimalkan semua elemen sekaligus, serta elemen individual.
  • Performa baik-baik saja dengan beberapa elemen, tetapi tampaknya menurun secara dramatis seiring dengan bertambahnya jumlah elemen.
  • Saat membuat profil kedua metode filter objek saya performance.now()serta memeriksa waktu render di React DevTools, angkanya tampak baik-baik saja. Saya bisa saja salah menafsirkannya.
  • Saya sudah mencoba menggunakan React.memo()elemen stateless (terutama kunci / nilai yang merupakan komponen yang paling sering dirender), tetapi tampaknya tidak meningkatkan kinerja secara nyata. Memang, saya tidak yakin apakah saya cukup memahami alasan di balik memoizing komponen React untuk mengimplementasikan ini secara berguna.

Penerapan

  • Saat ini, aplikasi saya memuat data ke induk yang dimasukkan ke dalam komponen yang memuat pohon JSON menggunakan elemen rekursif.
  • Memuat umpan JSON dari URL mengubah status komponen induk, yang difilter menggunakan metode pembantu yang menggunakan nilai yang dimasukkan ke dalam bidang masukan.

Masalah

Ada dua fungsi yang mereproduksi waktu respons yang lambat dengan dokumen JSON (tidak terlalu besar):

  • Tombol luaskan semua
  • Beberapa penekanan tombol pertama pada kueri filter

Dengan penerapan saat ini, baik pemfilteran maupun perluasan semua memicu display: noneperubahan pada elemen turunan, dan perilaku tersebut membuat saya percaya bahwa saya melakukan sesuatu yang tidak efisien untuk menangani kasus penggunaan ini.

Langkah Reproduksi

Kode tersedia di sini: https://codesandbox.io/s/react-json-view-4z348

Dengan produksi yang dibangun di sini (tidak berkinerja lebih baik): https://csb-4z348.vercel.app/

Untuk mereproduksi masalah, bermain-main dengan fungsi Perluas Semua (tanda tambah di sebelah masukan filter) dan beberapa masukan filter.

Kemudian, coba muat umpan JSON dengan lebih banyak elemen (Anda dapat mengujinya di umpan API GitHub saya ) dan mencoba memfilter / memperluas semua. Perhatikan hit kinerja utama.

Apa yang saya perhatikan

  • Saat mencatat useEffect, meminimalkan tampaknya menyebabkan ~ 2x lebih banyak perenderan daripada memperluas semua.
  • Saat masukan filter menjadi lebih spesifik, kinerja (secara logis) meningkat karena lebih sedikit elemen yang dirender.

Pertanyaan

Meskipun saya akan menghargai dorongan ke arah yang benar untuk kasus khusus ini, yang paling membuat saya penasaran adalah cara terbaik untuk mengidentifikasi apa yang menyebabkan masalah kinerja ini.

Saya telah melihat ke dalam jendela output, tetapi itu bukan pilihan pertama saya, dan saya cukup yakin saya melakukan sesuatu yang salah, daripada penyebabnya adalah terlalu banyak elemen yang diberikan.

Saya menghargai waktu Anda, dan sebelumnya terima kasih atas tip yang dapat Anda berikan!

Jawaban

2 HarrisonGrieve Aug 16 2020 at 15:50

Sepertinya saya telah menjawab pertanyaan saya sendiri. Masalahnya adalah masalah rekonsiliasi karena menggunakan UUID sebagai penyangga utama dalam komponen anak saya, yang menyebabkannya dirender ulang setiap kali status minimalisasi berubah. Dari dokumen:

Kunci harus stabil, dapat diprediksi, dan unik. Kunci yang tidak stabil (seperti yang dihasilkan oleh Math.random ()) akan menyebabkan banyak instance komponen dan node DOM dibuat ulang secara tidak perlu, yang dapat menyebabkan penurunan performa dan status hilang di komponen anak.

Saya akan meninggalkan langkah-langkah di sini untuk orang lain yang mengalami masalah ini.


Setelah (terlalu lama) menggali performance profiler, saya perhatikan bahwa setiap kali saya meminimalkan atau memperluas elemen, setiap turunan sedang dipasang lagi. Setelah berkonsultasi dengan Google dengan kueri yang lebih spesifik, saya menemukan entri blog ini dan menyadari bahwa saya melakukan kesalahan kinerja yang mencolok ini.

Begitu saya menemukan sumber masalahnya, saya menemukan banyak referensi lain tentangnya.

Setelah memperbaiki penyangga kunci, waktu interaksi menjadi ~ 60% lebih cepat untuk meminimalkan / memperluas semua.

Akhirnya, saya mengotomatiskan beberapa komponen lain yang terkait dengan filter instan dan akhirnya tampaknya berfungsi sebaik yang saya inginkan untuk saat ini.

Terima kasih kepada siapa pun yang telah melihat ini sementara itu, dan saya harap ini berguna bagi siapa saja yang mungkin menemukan ini.