Material-ui: Tingkatkan kinerja Material-UI

Dibuat pada 23 Mar 2018  ·  93Komentar  ·  Sumber: mui-org/material-ui

Pertama, terima kasih banyak untuk pustaka komponen yang luar biasa ini! Itu bagus!

Saya menambahkan laci di aplikasi baru saya. Sebagian besar, saya menyalin contoh laci. Hanya untuk PoC saya dikalikan

        <Divider />
        <List>{mailFolderListItems}</List>

bagian.

Setelah itu terasa sangat lambat, terutama di perangkat seluler (nexus 4, cordova dengan crosswalk 20). Saya menggunakan mode dev, tetapi mode prod tidak terlalu cepat.

Melalui alat pengembang reaksi, saya perhatikan bahwa komponen dalam mailFolderListItems dirender pada setiap klik tautan di router reaksi atau bahkan menu terbuka. Diperlukan waktu hingga 50-60 ms untuk merender SATU {mailFolderListItems} . saya menggunakan

const modalProps = {
    keepMounted: true, // Better open performance on mobile.
};

Untuk menghilangkan ketidakpastian dengan komponen aplikasi lain, saya mengonversi mailFolderListItems ke Komponen dan menonaktifkan rendering ulang:

class MailFolderListItems extends React.Component<{}, {}> {

    shouldComponentUpdate() {
        return false;
    }

    render() {
        return (
            <List>
                <Link to={Routes.Startpage.path}>
                    <ListItem>
                        <ListItemIcon>
                            <InboxIcon />
                        </ListItemIcon>
[...]


                <Divider />
                <MailFolderListItems />

Setelah itu bagian ini terasa OK.

Saya menemukan https://github.com/mui-org/material-ui/issues/5628 . Saya sarankan untuk meninjaunya kembali . Mengoptimalkan shouldComponentUpdate adalah langkah mendasar dan terpenting untuk mendapatkan kinerja. PureComponent hanyalah jalan pintas yang paling umum.

Selain itu, saya perhatikan bahwa sangat banyak waktu (1-2ms dan lebih banyak untuk SETIAP komponen material-ui) dihabiskan dalam WithStyles .

  • [x] Saya telah mencari masalah repositori ini dan percaya bahwa ini bukan duplikat.

Perilaku yang Diharapkan

Saya mengharapkan untuk mendapatkan sebagian besar kinerja reaksi yang mungkin untuk perpustakaan yang hebat ini.

Perilaku Saat Ini

Aplikasi menjadi lebih lambat dengan setiap komponen material-ui.

Langkah-langkah untuk Mereproduksi (untuk bug)

Saya belum memberikan contoh reproduksi, karena saya baru saja menyalin dari halaman demo komponen, tetapi jika diperlukan saya dapat memberikan kode dan demo kotak. Untuk browser itu terlihat, jika browser melambat dengan faktor >=5x dalam pengaturan kinerja.

Lingkungan Anda

| Teknologi | Versi |
|--------------|---------|
| Bahan-UI | 1.0.0-beta.38 |
| Ikon Material-UI | 1.0.0-beta.36 |
| Bereaksi | 16.2.0 |
| peramban | cordova crosswalk 20 (sama dengan android chrome 50) |

discussion performance

Komentar yang paling membantu

@olivietassinari sebagai pengembang hebat, bagaimana Anda bisa menulis hal-hal seperti ini? Mengapa Anda menggunakan _asumsi pribadi Anda_ sebagai argumen dan tanpa fakta? Saya rasa, sudah cukup saya paparkan fakta-fakta di atas. Saya melakukan segalanya untuk menunjukkannya, karena saya menyukai proyek ini dan ingin berkontribusi. Itu tidak cukup? Oke, kemudian lebih banyak fakta dan asumsi _no_.

Hanya untuk Anda saya kurangi menjadi 10 Tombol. 10! Ini berarti setiap 10 komponen (buruk: kontainer) dari memperlambat bahan-ui bawah seluruh aplikasi sampai aplikasi tidak dapat digunakan! Diuji pada perangkat nyata dengan penyeberangan 21/chrome 51 tanpa throttle apa pun:

Tombol biasa:
image

Tombol Murni:
image

Ini masih peningkatan 8x! Itu besar! Bisakah Anda bayangkan betapa pentingnya hal ini di perangkat seluler?

Alih-alih 100 tombol, Anda akan menemukan paling banyak 10 tombol di satu halaman. Namun, Anda akan menemukan 10 kisi, 10 X, dll.

Saya menggunakan Button karena merupakan salah satu komponen paling sederhana! Hal ini menunjukkan bahwa bahan-ui rusak dari sudut pandang kinerja. Sekarang, bayangkan komponen container seperti AppBar, Toolbar, List, Drawer! Ini bahkan lebih buruk! Anda mendapatkan dengan sangat cepat hingga 20 komponen/wadah di setiap halaman. Dan karena Anda tidak menghilangkan kelambatan apa pun di desktop/mac kuat Anda, itu tidak berarti bahwa material-ui tidak luar biasa lambat.

react-intl, pemeriksaan antara alat peraga sebelumnya dan baru akan selalu salah. Anda akan menyia-nyiakan siklus CPU. Jadi x13 -> x0.8

Tunjukkan contoh pada kode dan kotak. Saya tidak mengerti mengapa ini harus terjadi. Saya yakin, ini hanya terjadi pada penggunaan komponen reaksi yang salah. Dan contoh resmi menunjukkan penggunaan yang salah, karena sepertinya reaksi-intl tidak diterapkan pelanggan konteks . Tetapi ada banyak komponen lain yang selaras dengan pedoman reaksi dan praktik terbaik untuk tetap berkinerja.

BTW: WithStyles mengkonsumsi hingga 2,27 ms untuk Tombol di perangkat seluler. 8 komponen dan Anda di bawah 60fps.

Semua 93 komentar

Saya mengharapkan untuk mendapatkan sebagian besar kinerja reaksi yang mungkin untuk perpustakaan yang hebat ini.

@Bessonov Performance akan menjadi fokus pasca rilis v1. Kami telah mencoba untuk menjaga inti perpustakaan secepat mungkin. Itu harus cukup baik untuk +90% kasus. Setidaknya, itulah pengalaman saya menggunakan perpustakaan selama ini. Anda belum memberikan referensi eksternal apa pun, selain meningkatkan perhatian kami tentang fakta bahwa kinerja itu penting, kami tidak dapat membuat masalah ini dapat ditindaklanjuti. Jika Anda dapat mengidentifikasi batasan akar kinerja Material-UI yang dapat kami selidiki (dengan kode dan kotak reproduksi atau repositori), harap tingkatkan. Sampai saat itu, saya menutup masalah ini.

@olivietassinari terima kasih atas tanggapan cepat Anda! Saya sangat senang mendengar, bahwa kinerja akan menjadi fokus setelah rilis.

Itu harus cukup baik untuk +90% kasus. Setidaknya, itulah pengalaman saya menggunakan perpustakaan selama ini.

Di desktop - ya. Tapi di ponsel itu sangat lambat. Hanya Laci dan beberapa tombol membuat aplikasi lambat. Itu tidak responsif dan mengkonsumsi lebih banyak daya sesuai kebutuhan.

Anda belum memberikan referensi eksternal apa pun, selain meningkatkan perhatian kami tentang fakta bahwa kinerja itu penting, kami tidak dapat membuat masalah ini dapat ditindaklanjuti.

Saya memberikan referensi untuk masalah yang sudah diangkat dan referensi untuk bereaksi dokumentasi.

Jika Anda dapat mengidentifikasi batasan akar kinerja Material-UI yang dapat kami selidiki (dengan kode dan kotak reproduksi atau repositori)

Seperti yang saya katakan, saya bisa melakukannya. Berikut adalah perbandingan komponen murni dan tidak murni. Langkah-langkah untuk mereproduksi adalah:

  1. Gunakan chrome dan buka https://codesandbox.io/s/r1ov818nwm
  2. Klik "Buka di jendela baru" di jendela pratinjau
  3. Buka alat dev dan buka tab "kinerja"
  4. Kurangi CPU Anda setidaknya 5x (tergantung pada PC Anda - mungkin 10x) untuk mencerminkan perangkat seluler
  5. Klik burger dan lihat bagaimana itu tertinggal.

Dan sekarang:

  1. Pergi ke index.js
  2. ubah pure menjadi true
  3. Menyimpan
  4. Ulangi langkah dari atas
  5. Bersenang senang lah!

Contoh ini sedikit tidak realistis karena saya telah memasukkan terlalu banyak elemen Daftar. Tetapi seperti yang saya katakan, di seluler, sangat cepat untuk menunjukkan di mana Anda "merasakan" setiap tindakan.

Ini masalah saya dengan WithStyles . Ada di Desktop dengan pelambatan CPU. Saya ingin memposting tangkapan layar dari perangkat nyata pada hari Senin.

Waktu untuk WithStyles(ListItem) :
image

Waktu untuk ListItem :
image

Perbedaannya adalah 1,26 ms hanya untuk komponen ListItem . Dengan 13 komponen seperti ini, Anda tidak dapat merender dengan 60fps lagi. Tapi saya perhatikan di Desktop, bahwa durasi ini tidak selalu ada di sini.

Berikut adalah perbandingan komponen murni dan tidak murni

Btw saya tidak mengatakan bahwa PureComponent adalah solusi untuk semua masalah kinerja. Saya hanya mengatakan, itu bisa menjadi salah satu pembantu untuk membuat materi-ui dapat digunakan di ponsel.

Perbedaannya adalah 1,26 ms hanya untuk komponen ListItem.

@Bessonov Komponen WithStyles harus sangat murah untuk instance berulang dari komponen yang sama. Kami hanya menyuntikkan CSS sekali.
Mungkin Anda mencapai batasan React dan biaya komponen yang lebih tinggi.
Ada berbagai solusi untuk mengurangi masalah kinerja di React. Misalnya, Anda dapat menggunakan memoisasi elemen dan virtualisasi. Saya membiarkan masalah ini terbuka sebagai titik awal untuk penyelidikan kinerja di masa mendatang.
Saya rasa tidak banyak yang bisa kita lakukan saat ini. Terima kasih telah menyampaikan kekhawatirannya.

Oke, itu hanya satu bagian. Apa pendapat Anda tentang bagian yang lebih penting - mengoptimalkan shouldComponentUpdate ?

EDIT: Saya ingin membagi masalah ini menjadi dua bagian. Bagian ini tentang shouldComponentUpdate dan bagian lainnya untuk WithStyles , jika saya dapat menampilkan informasi lebih lanjut. Apakah itu baik untuk Anda?

mengoptimalkan shouldComponentUpdate

@Bessonov Kami tidak itu di sisi Material-UI karena dua alasan:

  1. Sebagian besar komponen kami menerima elemen reaksi, perubahan referensi elemen reaksi pada setiap render, membuat logika secara sistematis membuang siklus CPU.
  2. Semakin dekat logika shouldComponentUpdate dari akar pohon React, semakin efisien. Maksud saya, semakin banyak pemangkasan yang bisa Anda lakukan di pohon, semakin baik. Komponen Material-UI adalah level rendah. Ada peluang leverage yang rendah .

Satu-satunya kesempatan yang kami temukan adalah dengan ikon. Beri tahu kami jika Anda dapat mengidentifikasi yang baru.

bagian lain untuk WithStyles

+90% dari waktu yang dihabiskan di WithStyles sebenarnya dihabiskan di JSS , hanya sedikit yang bisa kita lakukan di sisi Material-UI.
Setidaknya, saya telah mengidentifikasi peluang caching untuk rendering sisi server akhir-akhir ini untuk sangat meningkatkan kinerja pada rendering berulang. Tapi itu hanya sisi server.

Sebagian besar komponen kami menerima elemen reaksi, perubahan referensi elemen reaksi pada setiap render, membuat logika secara sistematis membuang siklus CPU.

Itu tergantung pada penggunaan dan dapat ditingkatkan. Saya tidak membuat tolok ukur sendiri, tetapi saya yakin bahwa penggunaan komponen yang tepat dan dioptimalkan shouldComponentUpdate (dengan perbandingan dangkal) lebih murah daripada komponen yang tidak dioptimalkan, terutama untuk struktur yang tidak dapat diubah (dan immutable.js tidak diperlukan Omong-omong). Tiket terkait: https://github.com/mui-org/material-ui/issues/4305

Misalnya di https://github.com/mui-org/material-ui/blob/v1-beta/docs/src/pages/demos/drawers/PermanentDrawer.js#L68 ini mengarah ke objek baru dan menghasilkan PureComponent tidak masuk akal:

        classes={{
          paper: classes.drawerPaper,
        }}

karena itu kembali setiap kali objek baru. Tapi tidak:

const drawerClasses = {
    paper: classes.drawerPaper,
};
[...]
        classes={drawerClasses}

Sama untuk komponen.

Semakin dekat logika shouldComponentUpdate dari akar pohon React, semakin efisien. Maksud saya, semakin banyak pemangkasan yang bisa Anda lakukan di pohon, semakin baik.

Ya itu benar.

Komponen Material-UI adalah level rendah. Ada peluang leverage yang rendah.

Itu sebagian benar. Seperti yang Anda lihat di https://codesandbox.io/s/r1ov818nwm Saya baru saja membungkus List dalam PureComponent . Tidak ada yang lain dan itu mempercepat Laci dengan faktor signifikan. Saya akan mengklaim bahwa ini benar untuk setiap komponen, setidaknya yang menggunakan {this.props.children} . Saya membuat demo lain: https://codesandbox.io/s/my7rmo2m4y

Hanya ada 101 Buttons (pure = false) dan Buttons yang dibungkus dengan PureComponent (pure = true, lihat dari mana Button diimpor). Hasil permainan yang sama, jika saya mengklik "Klik" -Tombol:

Tombol Biasa:
image

Tombol Terbungkus (dengan overhead dan sebagainya):
image

Seperti yang Anda lihat, ada 637 md vs. 47 md untuk Tombol biasa! Apakah Anda masih berpikir bahwa mengoptimalkan shouldComponentUpdate (atau hanya PureComponent ) tidak sepadan? :)

EDIT: perbaiki kata-kata di awal

@oliviertasinari @oreqizer Saya melihat hal yang menarik. Sepertinya extends PureComponent berkinerja lebih baik sebagai Component dengan

  shouldComponentUpdate() {
    return false;
  }

image

EDIT: Saya pikir ini adalah salah satu reaksi optimasi internal.

Seperti yang Anda lihat, ada 637 md vs. 47 md untuk Tombol biasa! Apakah Anda masih berpikir bahwa mengoptimalkan shouldComponentUpdate (atau hanya PureComponent) tidak sepadan? :)

@Bessonov Ini menunjukkan potensi logika murni. Ya, itu bisa sangat berguna! Ini adalah peningkatan x13. Tapi saya tidak berpikir itu dekat dengan kondisi kehidupan nyata:

  • Alih-alih 100 tombol, Anda akan menemukan paling banyak 10 tombol di satu halaman. Namun, Anda akan menemukan 10 kisi, 10 X, dll.
  • Alih-alih sifat sederhana yang diberikan kepada elemen-elemen tingkat rendah, Anda akan menggunakan sesuatu seperti bereaksi-intl, cek antara alat peraga sebelumnya dan baru akan selalu palsu. Anda akan menyia-nyiakan siklus CPU . Jadi x13 -> x0.8 atau lebih

@olivietassinari sebagai pengembang hebat, bagaimana Anda bisa menulis hal-hal seperti ini? Mengapa Anda menggunakan _asumsi pribadi Anda_ sebagai argumen dan tanpa fakta? Saya rasa, sudah cukup saya paparkan fakta-fakta di atas. Saya melakukan segalanya untuk menunjukkannya, karena saya menyukai proyek ini dan ingin berkontribusi. Itu tidak cukup? Oke, kemudian lebih banyak fakta dan asumsi _no_.

Hanya untuk Anda saya kurangi menjadi 10 Tombol. 10! Ini berarti setiap 10 komponen (buruk: kontainer) dari memperlambat bahan-ui bawah seluruh aplikasi sampai aplikasi tidak dapat digunakan! Diuji pada perangkat nyata dengan penyeberangan 21/chrome 51 tanpa throttle apa pun:

Tombol biasa:
image

Tombol Murni:
image

Ini masih peningkatan 8x! Itu besar! Bisakah Anda bayangkan betapa pentingnya hal ini di perangkat seluler?

Alih-alih 100 tombol, Anda akan menemukan paling banyak 10 tombol di satu halaman. Namun, Anda akan menemukan 10 kisi, 10 X, dll.

Saya menggunakan Button karena merupakan salah satu komponen paling sederhana! Hal ini menunjukkan bahwa bahan-ui rusak dari sudut pandang kinerja. Sekarang, bayangkan komponen container seperti AppBar, Toolbar, List, Drawer! Ini bahkan lebih buruk! Anda mendapatkan dengan sangat cepat hingga 20 komponen/wadah di setiap halaman. Dan karena Anda tidak menghilangkan kelambatan apa pun di desktop/mac kuat Anda, itu tidak berarti bahwa material-ui tidak luar biasa lambat.

react-intl, pemeriksaan antara alat peraga sebelumnya dan baru akan selalu salah. Anda akan menyia-nyiakan siklus CPU. Jadi x13 -> x0.8

Tunjukkan contoh pada kode dan kotak. Saya tidak mengerti mengapa ini harus terjadi. Saya yakin, ini hanya terjadi pada penggunaan komponen reaksi yang salah. Dan contoh resmi menunjukkan penggunaan yang salah, karena sepertinya reaksi-intl tidak diterapkan pelanggan konteks . Tetapi ada banyak komponen lain yang selaras dengan pedoman reaksi dan praktik terbaik untuk tetap berkinerja.

BTW: WithStyles mengkonsumsi hingga 2,27 ms untuk Tombol di perangkat seluler. 8 komponen dan Anda di bawah 60fps.

Mengapa Anda menggunakan asumsi pribadi Anda sebagai argumen dan bukan fakta?

Apa yang membuatmu berpikir itu asumsi pribadi? Saya mencoba untuk melakukan pemikiran kritis. Secara konseptual, prop traversal ekstra akan memperlambat versi murni dibandingkan dengan versi non murni, ia harus memangkas sesuatu yang sepadan. Alasan yang sama dengan #5628 atau https://github.com/react-bootstrap/react-bootstrap/issues/633#issuecomment -234749417 atau https://github.com/reactstrap/reactstrap/pull/771#issuecomment -375765577

Dengan murni:
capture d ecran 2018-03-27 a 11 43 41

Tanpa murni:
capture d ecran 2018-03-27 a 11 44 15

Reproduksi adalah sebagai berikut.

@oliviertasinari apakah Anda yakin bahwa kode dan kotak membuat semuanya tepat untuk pengujian Anda? Karena hasil saya sangat berbeda:

Tanpa murni (bahkan tanpa throttle lambat):
image

Murni (setelah diubah menjadi true dan simpan, saya mendapatkan url baru untuk kode dan kotak):
image

Karena tidak memeriksa perubahan konteks dan juga memaksa pengguna untuk memastikan semua komponen anak-anak juga "murni", saya tidak percaya ini cocok untuk perpustakaan ini. Perpustakaan ini harus sefleksibel mungkin dan saya yakin ini akan membuatnya lebih sulit untuk digunakan.

Saya melihat intinya. Tapi itu tradeoff yang sangat menarik. Di satu sisi bahkan material-ui harus "sefleksibel mungkin", tetapi di sisi lain kinerja saat ini membuatnya _tidak dapat digunakan_ sama sekali.

Mungkin Anda harus mempertimbangkan untuk menyediakan komponen versi murni dan tidak murni. Saya melakukannya sekarang untuk aplikasi saya untuk mendapatkan kinerja yang dapat digunakan bahkan di desktop.

@Bessonov Kode dan kotak tidak disimpan dengan benar. Maaf. Itu hilang diff berikut. Saya telah memperbarui tautan:

<Button>
+ <i>
    Button
+ </i>
</Button>

Saya tidak mengerti mengapa harus menghasilkan hasil yang berbeda? Saya mendapatkan grafik yang lebih baik, tetapi versi non-murni secara signifikan lebih lambat.

EDIT: oke, saya mengerti. Coba tebak apa yang terjadi...

Oke, saya mengerti sekarang. "Objek baru di setiap render" yang sama. Saya tidak memperhatikannya sebelumnya. Untuk beberapa kasus dapat ditingkatkan dengan konstanta melalui plugin babel secara otomatis.

Nah, maka Anda sudah mengetahuinya! :D Meskipun tidak banyak manfaatnya (Anda menunjukkan ~7%), kesimpulannya masih menguntungkan dengan komponen murni untuk menghindari beberapa kekurangan yang Anda sebutkan di atas. Saya mengujinya sekarang dengan Pure Wrapper + plugin babel + build produksi dan sangat cepat mengesankan di perangkat seluler yang sama!

Seperti yang saya katakan, saya pikir yang terbaik adalah menawarkan keduanya - komponen non murni untuk fleksibilitas dan komponen murni (pembungkus cukup untuk membuatnya tetap sederhana dan dapat dipelihara) untuk kinerja. Tapi bagi saya, saya bisa hidup hanya dengan komponen murni, karena peningkatan kinerja secara keseluruhan jauh lebih besar daripada kekurangan kinerja. Atau lebih baik: Saya tidak dapat menggunakan material-ui tanpa komponen murni.

Ok, untuk saat ini saya menunggu masukan lebih lanjut tentang topik ini dan membuat pembungkus sendiri di aplikasi saya)

Terima kasih atas wawasannya!

Saya belum pernah mendengar elemen transform-react-constant- benar <Add /> .

Lihatlah contoh ini (klik Plugin di samping, cari "react-constant" dan klik kotak centang pada "transform-react-constant-elements") dan Anda akan melihat bahwa hampir tidak ada yang dioptimalkan:

  • InputAdornment statis sederhana telah dipindahkan ke atas, yay.
  • Tapi tombol submit yang sederhana tidak lagi dioptimalkan saat kita menempatkan event handler di atasnya.
  • Dan sementara InputAdornment itu sendiri sekarang diangkat, InputProps={{startAdornment: ...}} masih inline dan membuat objek baru setiap render yang membuat PureComponent tidak mungkin.
  • Demikian juga classes={{label: classes.runButtonLabel}} membuat PureComponent tidak mungkin mengoptimalkan tombol Run.

Saya pribadi menyukai PureComponent dan mencoba menggunakannya sepenuhnya di mana saja dan mengoptimalkan hal-hal sebanyak yang saya bisa agar berfungsi. Tapi sepertinya MUI sama sekali tidak dibuat sedemikian rupa sehingga PureComponent akan berfungsi.

  • Alat peraga *Props seperti InputProps adalah pola dasar cara kerja MUI. Ini bukan hanya cara canggih untuk memodifikasi internal MUI saat Anda membutuhkannya, melainkan sesuatu yang digunakan secara teratur dalam kasus penggunaan sederhana. Pola ini sering membuat komponen daun apa pun yang biasanya dapat dioptimalkan dalam mode murni, tidak dapat dioptimalkan.
  • Demikian juga pola classes={{...}} juga tidak berfungsi dengan PureComponent dan ini adalah cara untuk menambahkan gaya apa pun ke hal-hal di MUI. (Dan mengatakan untuk menggunakan classes={classes} sama sekali tidak praktis karena konsumen kehidupan nyata kemungkinan memiliki nama kelas yang berbeda dari kelas internal komponen dan classes kemungkinan juga menyertakan kelas yang dimaksudkan untuk menata elemen lain dalam komponen konsumsi yang sama)
  • Anak-anak banyak digunakan, alih-alih memiliki 1 komponen, pola umum sering menggunakan 2-3 dan hanya satu dari mereka yang dapat dioptimalkan murni jika ada yang bisa.

Jika kita ingin mengoptimalkan apa pun, masalah mendasar ini perlu ditangani, jika tidak, membiarkan orang mengaktifkan mode murni MUI tidak akan benar-benar mengoptimalkan sama sekali. Saya bisa memikirkan dua kemungkinan.

Kami hanya mengizinkan mode murni untuk diaktifkan, konsumen harus memoize atau mengangkat objek secara manual untuk benar-benar mendapatkan pengoptimalan

  1. Salah satu cara yang dapat saya pikirkan untuk melakukan ini adalah kekurangan shallowMemoize yang menggunakan this dan key (sehingga Anda dapat menggunakannya pada bit data yang berbeda) yang memoize data selama itu dangkal sama
  2. Hal lain yang dapat saya pikirkan adalah menggunakan sesuatu seperti memilih ulang untuk membuat penyeleksi yang akan memoize data.
  3. Cara lain untuk melakukan shallowMemoize dalam 1. adalah dengan meneruskannya ke render() dengan dekorator. Dengan cara ini kita bisa mengirimkan yang baru setiap render dan alih-alih membutuhkan key kita bisa memeriksa apakah ada objek memo dari render terakhir yang harus digunakan kembali, lalu buang semua nilai lama.

Masalahnya tentu saja ini membuat konsumen jauh lebih besar dan berantakan dan membutuhkan logika untuk diangkat secara manual ke tempat-tempat yang jauh dari kode yang menggunakannya.

import {createSelector} from 'reselect';

class FormPage extends PureComponent {
  state = { example: '' };

  change = e => this.setState({example: e.target.value});
  submit = () => {
    console.log('Submit: ', this.state.example);
  };

  runButtonClasses = createSelector(
    props => props.classes.runButtonLabel,
    runButtonLabel => ({runButtonLabel}));

  render() {
    const {title} = this.props;
    const {example} = this.state;

    return (
      <form>
        {title}
        <TextField
          InputProps={this.shallowMemoize('a', {
            // This example assumes use of transform-react-constant-elements to make this object always the same
            startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
          }}}
          onChange={example}
          value={example} />
        <Button classes={this.runButtonClasses(classes)}>Run</Button>
        <Button onClick={this.submit}>Submit</Button>
      </form>
    );
  }
}
// ...
  <strong i="6">@withShallowMemoize</strong>
  render(memo) {
    const {title} = this.props;
    const {example} = this.state;

    return (
      <form>
        {title}
        <TextField
          InputProps={memo({
            startAdornment: <InputAdornment position="start">Kg</InputAdornment>,
          }}}
          onChange={example}
          value={example} />
        <Button classes={memo(classes)}>Run</Button>
        <Button onClick={this.submit}>Submit</Button>
      </form>
    );
  }

Alih-alih mencoba mengoptimalkan InputProps, kelas, dll... kami mendorong orang untuk membuat komponen mikro untuk semua kasus penggunaan mereka

Jika ini adalah cara yang disarankan untuk menggunakan MUI, kita mungkin bahkan tidak memerlukan mode murni. Seperti yang Anda lihat, segera setelah Anda mulai membuat komponen pembantu kecil untuk kasus penggunaan umum Anda, komponen itu sendiri dapat dengan mudah menjadi komponen murni. Dalam contoh WeightTextField now never get's re-rendered selama value masih sama, benar-benar melewatkan withStyles, pekerjaan memoisasi apa pun yang diperlukan untuk InputProps, atau pengaturan InputAdornment. Dan ketika value berubah, kita harus merender ulang TextField sehingga InputProps={{...}} tidak murni tidak menjadi masalah.

Saya baik-baik saja dengan jalan ini. Saya suka komponen mikro secara teori; meskipun saya membenci setiap sintaks/pola yang valid saat ini untuk menulisnya yang dapat saya pikirkan. Saya tidak ingin MyComponent = enhance(MyComponent) , saya ingin mendekorasinya, tetapi Anda tidak dapat mendekorasi salah satu cara singkat untuk menulis komponen kecil. Saya juga tidak suka mengubah import {TextField} from 'material-ui'; menjadi import WeightTextField from '../../../ui/WeightTextField ;`.

```js
biarkan WeightTextField = ({unit, InputProps, ...props}) => (
{...Atribut}
Alat Masukan={{
mulaiPerhiasan:{satuan} ,
...InputProps
}}
onChange={contoh}
nilai={contoh} />
);
WeightTextField = murni(WeightTextField);

RunButton = tulis(
denganGaya(tema => ({
label: {
fontBerat: '800',
},
})),
murni
)(Tombol);

const SubmitButton = murni(Tombol);

class FormPage memperluas Komponen {
keadaan = { contoh: '' };

ubah = e => this.setState({contoh: e.target.value});
kirim = () => {
console.log('Kirim: ', this.state.example);
};

render() {
const {judul} = this.props;
const {contoh} = this.state;

return (
  <form>
    {title}
    <WeightTextField
      unit='Kg'
      onChange={example}
      value={example} />
    <RunButton>Run</RunButton>
    <SubmitButton onClick={this.submit}>Submit</SubmitButton>
  </form>
);

}
}
````

Saya memiliki kasus penggunaan di mana saya perlu menampilkan 500–2000 kotak centang pada halaman dalam daftar besar. Menggunakan kotak centang browser asli, kinerja baik-baik saja, tetapi menggunakan komponen <Checkbox> , kinerja sangat buruk dan skala linier dengan jumlah kotak centang pada halaman. Contoh: https://codesandbox.io/s/5x596w5lwn

Saya menggunakan mui@next — apakah ada strategi yang dapat saya terapkan _now_ untuk membuat ini bisa diterapkan?

@wilsonjackson
Pertama, jangan lakukan hal berikut. Ini akan membuat penangan baru setiap kotak centang setiap render, yang akan menonaktifkan optimasi PureComponent yang Anda coba lakukan.

  handleChange = index => event => {
    this.setState({

Kedua, buat komponen kecil Anda sendiri untuk membungkus Kotak Centang dan buat komponen itu murni. Ini memiliki manfaat ekstra yang dapat Anda tambahkan di properti apa pun yang umum untuk semua kotak centang Anda. Dan, karena Anda memiliki masalah umum yang membutuhkan pengendali acara perubahan yang berbeda untuk setiap item, kita dapat menggunakan komponen kelas dan melakukannya di komponen alih-alih di wadah daftar.

https://codesandbox.io/s/r7l64j6v5n

Jika kita ingin mengoptimalkan apa pun, masalah mendasar ini perlu ditangani, jika tidak, membiarkan orang mengaktifkan mode murni MUI tidak akan benar-benar mengoptimalkan sama sekali. Saya bisa memikirkan dua kemungkinan.

@dantman Pilihan API ini telah dibuat untuk meningkatkan DX sebanyak mungkin sambil mencoba menjadi cukup cepat.

Alih-alih mencoba mengoptimalkan InputProps, kelas, dll... kami mendorong orang untuk membuat komponen mikro untuk semua kasus penggunaan mereka

Ya, kami melakukannya. Pola pembungkus jelas merupakan cara yang dianjurkan untuk menyesuaikan perpustakaan. Ini dapat diperluas untuk menerapkan pengoptimalan kinerja. Lebih mudah di userland di mana variabilitas penggunaan komponennya jauh lebih rendah. Kami bahkan dapat menambahkan pertanyaan FAQ atau bagian panduan tentang poin ini dalam dokumentasi.

Ya, kami melakukannya. Pola pembungkus jelas merupakan cara yang dianjurkan untuk menyesuaikan perpustakaan. Ini dapat diperluas untuk menerapkan pengoptimalan kinerja. Lebih mudah di userland di mana variabilitas penggunaan komponennya jauh lebih rendah. Kami bahkan dapat menambahkan pertanyaan FAQ atau bagian panduan tentang poin ini dalam dokumentasi.

Oke. Dalam hal itu:

  • Kami ingin merekomendasikan library seperti recompose yang memudahkan penulisan komponen stateless kecil. Heck, saya akan menyambutnya jika seseorang memberi tahu saya bahwa ada pola atau pustaka lain yang mirip dengan komposisi ulang tetapi membuat membangun fungsi stateless murni seperti pola recompose tetapi sama bagusnya dengan menggunakan sintaks dekorator
  • Seperti kami mencantumkan saran tentang cara menggunakan berbagai pustaka pelengkapan otomatis dan pustaka css di pustaka js dengan MUI, kami mungkin juga ingin menyarankan berbagai pola organisasi folder dan pustaka peretasan jalur yang ada (yang memungkinkan Anda mengubah impor ../../../../ui/Foo menjadi sesuatu seperti something-local/Foo ) yang dapat digunakan untuk menggunakan rangkaian komponen mikro lokal Anda sendiri yang membungkus MUI sebaik menggunakan import {TextField} from 'material-ui'; dan tidak terasa seperti regresi dalam kemudahan pengembang .

@dantman luar biasa, terima kasih.

Saya perlu beberapa kali untuk menerapkan sCU karena withStyles (atau lebih tepatnya JSS) sangat lambat. Saya tidak tahu kode JSS tetapi sepertinya itu bisa dioptimalkan cukup banyak. Saya biasanya menggunakan komponen bergaya atau glamor dan dengan demikian berakhir dengan JSS dan salah satu yang lain di aplikasi dan keduanya mengungguli JSS.

Meskipun kasus ini mungkin sedikit mengganggu, mereka mudah untuk diatasi dengan sCU tingkat aplikasi atau pembaruan status yang lebih cerdas. Saya belum melihat satu komponen MUI cukup lambat untuk menjadi masalah dan saya juga belum membuat kode di dalam MUI untuk mengambil waktu yang signifikan.

Bukan untuk mengatakan bahwa itu tidak bisa lebih cepat dan pasti akan lebih baik jika lebih sedikit pengawasan diperlukan tetapi setidaknya untuk apa yang saya lihat akan lebih baik menghabiskan waktu untuk mengoptimalkan JSS secara langsung daripada MUI dalam kasus itu.

@Pajn Terima kasih atas umpan baliknya. Akan sangat bagus untuk melihat beberapa situasi di mana kinerja withStyles bermasalah atau di mana kinerjanya diungguli oleh komponen gaya.

apakah ada yang memeriksa repo ini https://github.com/reactopt/reactopt ?

$ click - button (text: مقالات ) => CssBaseline,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,ScrollbarSize,TransitionGroup,TouchRipple,Ripple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,Main,ScrollbarSize,TransitionGroup,TouchRipple,Ripple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple,TransitionGroup,TouchRipple

komponen-komponen ini melakukan rendering ulang yang tidak perlu hanya untuk satu klik sederhana, mengapa tidak mencoba Should Component Update life-cycle ?

@nimaa77

apakah ada yang memeriksa repo ini https://github.com/reactopt/reactopt ?
Tidak, saya menggunakan plain mengapa-melakukan-Anda-pembaruan dan chrome / bereaksi alat dev kemampuan.

komponen-komponen ini melakukan rendering ulang yang tidak perlu hanya untuk satu klik sederhana, mengapa tidak mencoba Should Component Update life-cycle ?

Lihat pembahasan di atas. Ini tidak cocok untuk setiap kasus penggunaan. Bagi saya, sepertinya material-ui harus menawarkan keduanya - versi komponen murni dan tidak murni. Saya melihat peningkatan kinerja yang luar biasa dengan komponen murni.

@dantman

Lihatlah contoh ini (klik Plugin di samping, cari "react-constant" dan klik kotak centang pada "transform-react-constant-elements") dan Anda akan melihat bahwa hampir tidak ada yang dioptimalkan:

Ini hanya salah satu cara untuk mengatasi masalah ini. Ada juga opsi lain, plugin, dan pengoptimalan buatan tangan lainnya. Jangan salah paham, tetapi saya tidak tertarik dengan diskusi teoretis tentang pengoptimalan mana yang baik atau buruk. Saya tertarik pada pengoptimalan langsung yang KARYA. Setidaknya dalam pengaturan saya. Semua yang saya tulis di atas BEKERJA untuk saya dan membuat aplikasi saya setidaknya dapat digunakan pada perangkat seluler menengah ke bawah. Meskipun saya terpaksa melakukan lebih banyak pengoptimalan seperti menyusun ulang pohon komponen, pencapaian kinerja tidak akan mungkin terjadi tanpa komponen murni dan pengoptimalan otomatis lainnya. Dan ya, saya membuat profil dan mengoptimalkan sangat banyak untuk menyelesaikan ini.

@Bessonov mungkin kita bisa menggunakan prop untuk membuat metode shouldComponentUpdate untuk melakukan perbandingan dangkal (https://reactjs.org/docs/shallow-compare.html) ATAU selalu mengembalikan false,
ini tidak akan menambah ukuran bundel dengan dua versi komponen (murni dan normal)

@lucasljj Saya tidak mengharapkan peningkatan ukuran bundel yang signifikan jika ini dilakukan sebagai pembungkus untuk komponen stateful seperti yang disebutkan di atas. Lihat juga profil di atas: hanya komponen murni yang lebih cepat dari return false; di sCU.

Masalah dengan komponen murni atau komponen yang mengimplementasikan sCU adalah, jika Anda menggunakan komponen non murni di dalamnya atau children . Lihat pernyataan di atas. Masalah lain yang harus diatasi adalah pengalihan tema. Tidak diuji, tapi saya pikir ini bisa diatasi setidaknya dengan Context API.

@bossonov Komponen Murni dianggap sebagai reaksi yang seharusnya menjadi default yang bukan karena mereka datang terlambat ke pesta. Tapi saya setuju bahwa kebanyakan orang akan membuat pembungkus gaya bentuk redux yang mengurangi kekurangannya di subtree

masalah yang Anda rujuk mengenai komponen murni dan anak-anak, hanya terjadi jika alat peraga tingkat atas tidak menyebar ke anak-anak. Setiap prop atau perubahan status akan memicu rerender melalui pohon anak hingga tingkat yang tidak disebarkan oleh prop.
Karena gagasan w komponen murni adalah bahwa ia merender pada setiap prop atau perubahan status. Saya tidak tahu internal secara mendalam tetapi saya bertanya-tanya Anda tidak dapat menggunakan properti perubahan per komponen yang Anda berikan kepada setiap anak. Anda bahkan dapat menggunakan api konteks baru untuk tujuan ini agar tidak harus mewariskan prop melalui seluruh pohon.

@oliviertasinari

Performa akan menjadi fokus pasca rilis v1.

Bagus, v1 dirilis :) Apakah ada ide kapan kinerja harus ditangani? Saya perhatikan bahwa masalah ini bukan bagian dari pencapaian post v1.

@Bessonov Saya pikir akan sangat bagus untuk meluangkan waktu untuk memperbarui ROADMAP. Mengenai kinerja. Saya memiliki dua hal dalam pikiran yang dapat ditindaklanjuti, tetapi saya berharap untuk menemukan lebih banyak:

  1. Kami tidak dapat meningkatkan sesuatu yang tidak dapat kami lihat. Kami membutuhkan tolok ukur. Saya telah melihat dua perpustakaan yang menarik sejauh ini:
  2. Merender sisi server CSS membutuhkan ~30% dari apa yang dibutuhkan React untuk dirender. Karena kami tidak mendukung style = f(props) (yah, kami belum mendukungnya: #7633). Kami dapat menerapkan kemampuan caching yang sangat efisien, memotong biaya mendekati 0% untuk permintaan berulang. Saya mungkin mengerjakannya untuk kantor jika kinerja RSK merugikan metrik bisnis kami.
    Tapi itu bukan satu-satunya pilihan, kita juga bisa memikirkan plugin Babel untuk menerapkan preset JSS yang mahal pada waktu kompilasi alih-alih pada saat runtime (untuk menyeimbangkan dengan implikasi ukuran bundel) cc @kof.

Terima kasih untuk urlnya.

Sepenuhnya setuju dengan 1 dan menautkan #4305 di atas.

  1. SSR dapat membantu memuat halaman pertama, tetapi tidak membantu rendering ulang atau cordova yang lambat. Meskipun secara pribadi saya dapat mengabaikan pemuatan pertama kali di desktop atau bahkan seluler, rendering ulang yang lambat masih memengaruhi perangkat seluler setelah pemuatan pertama.

Pengoptimalan waktu kompilasi akan sangat bagus dan dari sudut pandang saya harus lebih disukai, karena dapat meningkatkan pemuatan dan rendering pertama kali.

Hal lain adalah semacam dokumentasi atau proyek contoh bagaimana menggunakan mui (dan babel dll) untuk mendapatkan kinerja yang lebih baik.

Saya tidak tahu apakah jss-cache dapat digunakan.

Pipa ISTF + preprocessing akan dapat mencukur beberapa ms.

Pada Sabtu, 19 Mei 2018, 19:06 Anton Bessonov [email protected] menulis:

Terima kasih untuk urlnya.

Sepenuhnya setuju dengan 1 dan terkait #4305
https://github.com/mui-org/material-ui/issues/4305 di atas.

  1. SSR dapat membantu memuat halaman pertama, tetapi tidak membantu dengan lambat
    rendering atau cordova. Sementara secara pribadi saya dapat mengabaikan pemuatan pertama kali
    desktop atau bahkan seluler, rendering lambat masih memengaruhi perangkat seluler setelahnya
    pemuatan pertama.

Pengoptimalan waktu kompilasi akan sangat bagus dan dari sudut pandang saya seharusnya
lebih disukai, karena dapat meningkatkan pemuatan dan rendering pertama kali.

Hal lain adalah semacam dokumentasi atau contoh proyek cara menggunakan mui
(dan babel dll) untuk mendapatkan kinerja yang lebih baik.

Saya tidak tahu apakah jss-cache http://cssinjs.org/jss-cache?v=v3.0.0 bisa
digunakan.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/mui-org/material-ui/issues/10778#issuecomment-390418709 ,
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/AADOWGrCxNGqrT4MijiX8r9Ad32z6RsJks5t0FEtgaJpZM4S4woq
.

Mungkin berguna untuk menyiapkan tolok ukur:
https://github.com/A-gambit/CSS-IN-JS-Benchmarks/blob/master/RESULT.md

Oh react-jss (Yang digunakan oleh material-ui) tampaknya cukup lambat

@janhoeck tidak, dan Anda tidak akan dapat membuktikan sebaliknya, saya yakin.

@kof Saya cukup mengerti bahwa tolok ukur mikro tidak banyak bicara, tetapi 4x-6x dibandingkan dengan aphrodite sangat lambat. Faktanya, kinerja material-ui secara keseluruhan tidak mengkilap.

4x-6x dibandingkan dengan aphrodite sangat lambat

@Bessonov Metodologi benchmark
https://twitter.com/necolas/status/954024318308007937?lang=fr

Hasil di browser saya:
️ dengan ketidakpastian

capture d ecran 2018-06-12 a 17 58 54

kinerja keseluruhan material-ui tidak mengkilap

Kami mungkin sangat dibatasi oleh React itu sendiri dan biaya komponen.

@Bessonov apa pun yang Anda gunakan untuk memeriksa kinerja, ketika menyangkut aphrodite, itu tidak benar, karena ia menggunakan secepatnya dan menunda rendering, jadi sebagian besar tolok ukur mengukur waktu cpu tetapi bukan kinerja rendering akhir. Dikatakan bahwa bangku yang diposting @olivietassinari paling realistis.

Mengenai kinerja MUI, Anda bisa menjadi lebih cepat ketika Anda tidak menggunakan abstraksi sama sekali, tetapi bukan itu intinya. MUI selanjutnya cukup cepat. Ini sangat cepat sehingga Anda tidak perlu khawatir tentang kinerjanya kecuali ANDA melakukan sesuatu yang sepenuhnya salah atau menyalahgunakan perpustakaan.

@kof tidak, MUI tidak cepat secara default. Kami dipaksa untuk menerapkan solusi untuk mendapatkan kinerja yang dapat diterima. Yang pasti: tidakkah Anda melihat bahwa ini tentang perangkat seluler dan bukan untuk mac kelas atas?

jangan pernah khawatir tentang kinerjanya kecuali ANDA melakukan sesuatu yang sepenuhnya salah atau menyalahgunakan perpustakaan

Nah, di atas adalah beberapa contoh codesanbox. Jika kita hanya menggunakan komponen MUI dalam wadah dan menyimpan nilai input dalam status wadah, seperti yang ditunjukkan dalam demo komponen, maka itu menjadi tidak dapat digunakan dengan sangat cepat. Bungkus dalam PureComponent, gunakan komponen yang tidak terkontrol, penataan ulang pohon, elemen konstan, memoize, dan sebagainya membantu kami mempertahankan beberapa kinerja yang dapat diterima. Anda dipersilakan untuk menunjukkan cara menggunakan MUI yang benar, untuk mendapatkan hasil yang lebih baik, misalnya di (atm kami tidak menggunakan laci lagi):
https://codesandbox.io/s/r1ov818nwm

@olivietassinari terima kasih atas tautannya. Berikut adalah hasil untuk Chrome 66 pada nexus 4. Seperti yang Anda lihat, hasilnya 10x lebih buruk. Saya pikir di penyeberangan 21/chrome 51 itu bisa sedikit lebih lambat:

screenshot_2018-06-12-18-20-19

Kami mungkin sangat dibatasi oleh React itu sendiri dan biaya komponen.

IMHO belum tentu, seperti yang disebutkan oleh orang lain juga. Setiap rerender yang dihindari adalah kemenangan besar untuk kinerja dan baterai. Jangan lupa, kinerja adalah poin ketiga di peta jalan Anda :+1:

Lihat seperti itu: jika apa yang Anda lakukan dengan cssinjs terlalu lambat di perangkat seluler, Anda juga tidak boleh menggunakan reaksi ini dan sebagian besar lainnya. Jika cssinjs memperlambat Anda, komponen reaksi memperlambat Anda jauh lebih lambat. Anda perlu memikirkan kembali abstraksi level ob atau menerapkan pengoptimalan.

@oliviertasinari adalah evtl itu. mungkinkah pembungkus mui merender gaya jss pada pembaruan? Mungkin ada beberapa kebocoran yang berpotensi tidak berfungsi.

@kof

Lihat seperti itu [...]

Saya mengerti maksud Anda. Tetapi komponen reaksi dan reaksi (murni) tidak mengalami hambatan dengan sendirinya dan berkinerja sangat baik. Misalnya, MUI tidak menggunakan PureComponent (dengan pro dan kontra yang dijelaskan di atas), tetapi mereka membuat hidup kita lebih aman. @olivietassinari menyebutkan bahwa ada peluang untuk mendapatkan kinerja yang lebih baik dengan menggunakan cache atau pra-kompiler.

Jangan salah paham, kalian luar biasa guys dan saya sangat senang dengan setiap rilis MUI :clap: Tapi kalian juga perlu mempertimbangkan kinerja, karena tidak semua pengguna mengunjungi situs web melalui desktop berkinerja tinggi .

jika reaksi bukan hambatan kinerja dan Anda yakin tentang hal itu, JSS juga tidak. Satu-satunya hal yang dapat saya bayangkan yang perlu divalidasi jika ada beberapa pekerjaan yang tidak perlu terjadi dan css dibuat ulang pada pembaruan.

Komponen murni adalah sesuatu yang ANDA harus gunakan dalam kode tingkat aplikasi Anda, jika Anda memerlukan pengoptimalan. MUI tidak harus melakukannya, ini adalah perpustakaan umum dan tidak boleh membuat asumsi apa pun. PureComponent tidak selalu bagus.

JSS telah mempertimbangkan kinerja sejak hari pertama dan saya menghabiskan berjam-jam dalam optimasi mikro.

Ini konyol. Saya tidak dapat menghentikan komponen material ui dirender ulang pada setiap interaksi. Tidak masalah apa yang saya lakukan, lakukan sesuatu yang sederhana seperti ini:

class RowText extends Component {
  shouldComponentUpdate = (nextProps, nextState) => {
    return false;
  };

  render() {
    const { title, artist } = this.props;
    return <ListItemText primary={title} secondary={artist} />;
  }
}

Memicu render ulang elemen Tipografi yang mendasarinya. Bagaimana ini bahkan mungkin?

Hei, ini hanya terjadi dengan daftar dan item daftar. Mengapa ? Apakah ada sesuatu yang bisa saya lakukan?

@danielo515 Sulit untuk mengatakan tanpa contoh lengkap. Komponen List juga menggunakan konteks jadi jika Anda mengubah nilai itu juga, itu juga akan memicu perenderan ulang.

Saya mengerti bahwa @ eps1lon. Namun, bisakah Anda menjelaskan bagaimana perubahan konteks bisa terjadi? Saya tidak meneruskan apa pun ke komponen daftar, hanya merender anak-anak yang hilang di dalamnya.

@danielo515 Pada dasarnya setiap kali List dirender. API konteks baru memungkinkan beberapa strategi pengoptimalan yang dapat kami jelajahi dengan memoisasi nilai konteks.

Saat ini reaksi konteks API memicu rerender pada setiap konsumen jika nilainya mengubah WRT menjadi kesetaraan yang ketat. Karena kita membuat objek baru di setiap panggilan render ke List setiap konsumen juga akan merender.

Jadi untuk saat ini peningkatan kinerja yang mudah adalah dengan membungkus List sehingga tidak sering merender ulang. Saya akan merekomendasikan melakukan benchmark terlebih dahulu atau keluar dari render sebelumnya. Panggilan render berulang Typography seharusnya tidak terlalu buruk.

Membungkus komponen dengan React.memo berfungsi dengan baik untuk apa pun tanpa anak. Saya memiliki formulir dengan 3 ExpansionPanel dan beberapa 14 FormControl dan itu tertinggal di desktop.

Tanpa solusi untuk masalah kinerja ini, saya tidak akan dapat terus menggunakan material-ui :s

@prevostc sulit untuk mengatakan apa yang salah tanpa contoh.

@prevostc tanpa melihat kode dan reproduksi kotak, baik kami maupun Anda tidak dapat mengetahui apakah ini terkait dengan masalah ini

@prevostc Buat komponen Anda sendiri yang tidak memerlukan anak yang kemudian dapat Anda memo.

yaitu Buat komponen MyExpansionPanel murni/memoed Anda sendiri yang mengambil data/event props tetapi bukan anak-anak dan bertanggung jawab untuk merender satu panel ekspansi. Kemudian gunakan <MyExpansionPanel ... /> untuk merender setiap panel ekspansi Anda. Kemudian rendering ulang akan dibatasi pada satu panel ekspansi (atau dua saat transisi di antara dua).

@olivietassinari @kof @dantman
Berikut adalah reproduksi kode dan kotak dari masalah kinerja saya: https://codesandbox.io/s/yvv2y2zxxx

Ini adalah formulir dengan ~ 20 bidang (tidak jarang) Anda akan mengalami beberapa kelambatan pada input pengguna. Pada perangkat yang lebih lambat, formulir ini tidak dapat digunakan.

Masalah kinerja berasal dari rendering ulang besar-besaran pada input pengguna, tetapi membungkus komponen MUI dalam komponen murni (React.memo) tidak melakukan apa-apa karena semua yang ada di sini memiliki anak dan anak ini akan memaksa rendering ulang AFAIK (sumber: https:// reactjs.org/docs/react-api.html#reactpurecomponent)

Di bawah ini adalah beberapa tangkapan layar dari tolok ukur manual saya, satu tanpa pengoptimalan apa pun, satu dengan semuanya memo dan satu menggunakan komponen input khusus dengan status lokal untuk menghindari pengaturan status pada seluruh formulir terlalu sering.
Pada setiap konfigurasi, rekonsiliasi input pengguna membutuhkan waktu sekitar 60 md (jauh di atas 16 md yang perlu saya render pada 60 fps.

Harap dicatat bahwa saya akan dengan senang hati mengetahui bahwa saya melakukan sesuatu yang salah karena saya mencintai MUI dan saya akan sedih jika tidak ada perbaikan yang mudah <3

@dantman Bagaimana Anda bisa menulis ExpansionPanel yang tidak menggunakan React.ReactNode sebagai input (anak-anak atau alat peraga)? Jika maksud Anda saya harus menulis komponen khusus untuk setiap panel di aplikasi saya, sayangnya ini tidak mungkin, saya memiliki terlalu banyak.

screenshot 2018-12-20 at 22 04 08

screenshot 2018-12-20 at 21 56 57

screenshot 2018-12-20 at 22 05 00

@dantman Bagaimana Anda bisa menulis ExpansionPanel yang tidak menggunakan React.ReactNode sebagai input (anak-anak atau alat peraga)? Jika maksud Anda saya harus menulis komponen khusus untuk setiap panel di aplikasi saya, sayangnya ini tidak mungkin, saya memiliki terlalu banyak.

Ya, alih-alih membuat satu komponen besar dengan pohon panel yang sangat bersarang, pisahkan potongan panel ekspansi menjadi komponen. Tidak mungkin untuk mengoptimalkan pohon besar seperti itu.

Ini bukan tidak mungkin. Komponen React sangat ringan. Salin dan tempel blok kode dari komponen besar ke dalam suatu fungsi dan Anda hampir selesai, setelah itu Anda hanya perlu menghubungkan alat peraga. Dan selama Anda React.memo yang berfungsi dan menghindari melewati hal-hal yang merusak optimasi murni alat peraga, maka hal-hal dioptimalkan dengan cukup mudah.

Ingat, jika Anda membuat komponen kecil untuk memecah sebagian dari komponen besar. Itu tidak harus menjadi sesuatu yang kompleks dengan filenya sendiri dan validasi prop sendiri. Ini bisa menjadi komponen fungsional sederhana dalam file yang sama dengan komponen yang digunakan tanpa propTypes. yaitu Anda dapat membuat komponen kecil yang hanya tersedia untuk komponen dalam file yang sama dengan mereka.

Ya, Material UI sedikit lebih lambat dari elemen dom level rendah. Tetapi bahkan jika MUI Input 10x lebih lambat dari input mentah dan semuanya menjadi terlalu lambat setelah 100. Maka Anda masih memiliki masalah bahkan tanpa MUI karena meskipun 10x lebih cepat input mentah

@prevostc Inilah demo Anda yang dioptimalkan dengan membagi panel ekspansi menjadi komponen file kecil yang sama. Seperti yang Anda lihat, hanya satu panel ekspansi yang dirender ulang saat input diperbarui. Waktu tidak terbuang percuma untuk merender ulang panel ekspansi yang tidak terkait. Jika saya mau, saya bahkan bisa melakukan sesuatu yang mirip dengan input yang memiliki pola yang sama, sehingga input yang tidak terkait juga tidak dirender ulang.

Saya akan mencatat bahwa ini bukan hanya pola pengoptimalan yang baik, ini adalah pola pengkodean yang baik. Dalam kode nyata, di mana Anda tidak membuat array input tetapi secara eksplisit menuliskannya dengan nama, label, dan tujuan yang ditentukan. Menemukan batasan dan pola berulang tidak hanya mengoptimalkan hal-hal tetapi juga mengurangi boilerplate yang membuat kode lebih KERING dan mudah dibaca. yaitu Alih-alih InputWrapper saya mungkin akan memecah kombo FormControl+InputLabel+FormHelperText+Input itu menjadi komponen SimpleTextInput lokal kecil. Yang tidak hanya akan mengoptimalkannya (menghasilkan input yang tidak terkait tidak dirender ulang) tetapi juga berarti bahwa kode tidak perlu mengulangi boilerplate tambahan.

https://codesandbox.io/s/0o7vw76wzp

screen shot 2018-12-20 at 2 51 31 pm

Membaca ini saya sampai pada kesimpulan bahwa untuk mengoptimalkan mui Anda perlu membuat komponen spesifik yang lebih kecil. Itu adalah sesuatu yang sudah saya sadari dan coba dengan sukses. Namun, saya juga mengerti bahwa tidak ada cara untuk mengoptimalkan komponen daftar karena api konteks mengubah semua alat peraga input.

Salam

Ok di sini adalah tes stres yang diperbarui https://codesandbox.io/s/wz7yy1kvqk

Saya setuju dengan @dantman pada poin umum ini https://github.com/mui-org/material-ui/issues/10778#issuecomment -449153635 TAPI saya tidak mengharapkan masalah kinerja seperti itu dengan jumlah komponen yang rendah, tetapi bersabarlah saya ketika saya menemukan sumber masalah kinerja saya.

Apakah JSS lambat? (peringatan spoiler: tidak)

Mengacu pada beberapa komentar sebelumnya di utas ini, saya menambahkan kotak centang di tes stres untuk menghapus semua panggilan ke withStyles dan saya sampai pada kesimpulan bahwa JSS cepat dan itu bukan sumber masalah kinerja (seperti yang ditunjukkan @kof di https://github.com/mui-org/material-ui/issues/10778#issuecomment-396609276).

screenshot 2018-12-22 at 15 17 26

Perbaikannya

Untuk kasus penggunaan khusus saya, saya dapat menunjukkan masalahnya karena setiap input formulir dirender ulang pada pembaruan formulir, meskipun hanya satu input yang benar-benar berubah.
Pada tangkapan layar di bawah, saya membungkus FormControl dan Input dalam komponen memo, menghindari render jika nilainya tidak berubah. @dantman sebenarnya menyarankan agar saya membuat komponen khusus untuk setiap ExpansionPanel tetapi ini adalah solusi yang kurang umum. Sebagai catatan, masing-masing panel masih dirender ulang dan kinerjanya jauh dari optimal, tetapi itu sudah cukup untuk saat ini.

screenshot 2018-12-22 at 15 18 22

Jadi? Apa berikutnya?

Saya pikir tidak ada cara untuk menghindari masalah seperti ini dengan perubahan pada kode material-ui tanpa perubahan besar pada API saat ini yang sangat bergantung pada komposisi React.ReactNode .
Tetapi seperti yang disebutkan @dantman di https://github.com/mui-org/material-ui/issues/10778#issuecomment -449153635 , MUI sedikit lebih lambat dari yang diharapkan. Tidak membahas ini sama sekali adalah kesalahan IMHO.

Menyadari masalah ini, kami mungkin perlu membuat halaman dokumen yang terkait dengan masalah kinerja dan cara mengatasinya. Bahkan jika halamannya sebagian besar akan dialihkan ke dokumen resmi (https://reactjs.org/docs/optimizing-performance.html) dan daftar komponen yang mungkin menyebabkan masalah kinerja, ini adalah permulaan.
Akan lebih baik untuk console.warn pengguna ketika masalah seperti itu terjadi tetapi saya tidak dapat menemukan cara untuk mendeteksi masalah di tingkat material-ui.

@prevostc pesan ini membuat hari saya menyenangkan, ini adalah jenis komunitas yang saya cintai. Apakah Anda memiliki ide apa yang dapat diubah mui untuk membuat kinerja lebih baik dan menghindari kebutuhan akan pengoptimalan lahan pengguna? Perubahan API mungkin bisa dilakukan.

saya tidak :s

Saya tidak tahu cukup internal MUI untuk tahu bagaimana meningkatkan kinerja mentahnya (tanpa perubahan api) sekarang. Saya sedang mengerjakan beberapa ide tetapi tidak ada yang konklusif pada hari ini: Saya memiliki aplikasi di mana grup radio dirender ulang ketika induk langsungnya tidak, belum dapat memproduksi ulang ini secara lokal.

Perubahan API apa pun akan mempertimbangkan untuk menghapus alat peraga React.ReactNode dari API (anak-anak dan alat peraga lain seperti ikon, dll) tetapi saya tidak dapat menemukan cara yang baik untuk menjaga konfigurasi yang sama.
Inilah yang saya coba: https://codesandbox.io/s/jpw36jw65 (peringatan: belum selesai).

Juga perlu diperhatikan bahwa MUI sangat lambat saat dalam mode pengembangan karena reaksinya sangat lambat dalam mode pengembangan. Saya tidak tahu apakah ada cara untuk meningkatkan ini.

Apakah ada kemajuan dalam menambahkan kemampuan (seperti yang disarankan @Bessonov ) untuk mengoptimalkan masalah kinerja yang dihadapi Material-UI saat ini?
Ketika kami mulai menggunakan perpustakaan hebat ini untuk proyek kami, saya tidak tahu masalah kinerja seperti itu mungkin terjadi ketika proyek semakin besar; selain itu, saya tidak melihat bagian apa pun di dokumen Material-UI yang memberi tahu saya tentang kasus-kasus yang dapat menyebabkan Material-UI menjadi lambat dan membahayakan UX.
Banyak masalah kinerja - secara langsung atau tidak langsung terkait dengan Material-UI - dilaporkan dalam masalah ini. Saya pikir itu akan menjadi ide yang baik untuk mencantumkannya di edisi lain sehingga semua orang dapat melacak kemajuannya. Jika Anda pikir tidak apa-apa, saya dapat membuka edisi baru.

@ mkermani144 Kami belum melihat laporan kinerja yang berkorelasi langsung dengan sesuatu yang dilakukan Material-UI salah. Sejauh ini masalah ini telah digunakan sebagai forum bantuan bagi orang-orang yang berjuang. Apakah Anda mengonfirmasi bahwa tidak ada yang dapat ditindaklanjuti yang dilaporkan? Saya akan menyatakan yang jelas, React abstraction memiliki cost . Setiap komponen yang membungkus host akan menambah bobot pada pohon render Anda, memperlambatnya. Meskipun Anda dapat merender lebih dari 100 item daftar dengan host asli, itu mulai menjadi masalah saat Anda membungkusnya dengan komponen kelas. Ini tidak spesifik untuk Material-UI.

Meja

mode pengembangan

Mari kita ambil contoh tabel. Ini adalah komponen yang menurut orang lambat. Kami telah mendokumentasikan virtualisasi , sangat membantu.

Dalam kasus uji berikut, kami merender 100 item dalam mode dev . Kita dapat mempertimbangkan kasus-kasus berikut:

  1. Tabel Mentah: https://codesandbox.io/s/v066y5q7z3 : 63ms dalam render
  2. Tabel Material-UI Master: https://codesandbox.io/s/m4kwmvj9ly : 250ms dalam render
  3. Tabel Material-UI Berikutnya: https://codesandbox.io/s/2o35yny1jn : 262ms di render

Jadi overhead menggunakan Material-UI dalam mode dev di atas elemen host adalah sekitar x4 (perbedaannya lebih kecil dalam produksi!), Hanya karena kami membuat komponen perantara. Itu sebabnya virtualisasi mulai menjadi penting setelah membuat daftar ~100 item tabel. Sekarang, kita bisa sedikit menyelami Mengapa dan apa yang bisa kita lakukan?

  1. Tabel Raw + komponen fungsi. Mengapa komponen fungsional? Kami ingin mengabstraksi nama kelas yang digunakan. Kami tidak ingin pengguna komponen mengulanginya.
    https://codesandbox.io/s/1zl75mwlpj : 105ms dalam render
  2. Tabel Raw + komponen fungsi + forwardRef. Mengapa meneruskanRef? Kami ingin komponen menjadi "transparan", dapat mengakses elemen host dengan referensi.
    https://codesandbox.io/s/32o2y0o9op : 120ms dalam render
  3. Tabel Raw + komponen fungsi + forwardRef + withStyles. Mengapa dengan Styles? Karena kita ingin menata komponen kita:
    https://codesandbox.io/s/j2n6pv768y : 200ms dalam render
  4. Tabel Raw + komponen fungsi + forwardRef + makeStyles. makeStyles mungkin lebih cepat daripada withStyles, mari kita coba:
    https://codesandbox.io/s/yw52n07l3z : 130ms dalam render.

Jadi, kami memiliki satu leverage yang tersedia: migrasikan semua komponen dari withStyles ke makeStyles. Kami dapat memenangkan sekitar +30% kinerja (262 / (262 - 70)) dalam mode pengembangan .

Modus produksi

Saya telah menjalankan kasus uji yang sama dalam mode produksi:

  • n°1 30ms dalam hidrat
  • n°3 106ms dalam hidrat
  • n°4 40ms dalam hidrat
  • n°5 41ms dalam hidrat
  • n°6 80ms dalam hidrat
  • n°7 57ms dalam hidrat

Jadi migrasi withStyles ke makeStyles masih merupakan percepatan +30% secara teori dalam mode produksi .

Jika Anda pikir tidak apa-apa, saya dapat membuka edisi baru.

@ mkermani144 Jika Anda memiliki kasus tertentu di mana Material-UI melakukan kesalahan, tentu saja.

Saya membaca tentang semua komentar di bawah masalah ini. Masalah saya tidak cocok dengan masalah lain yang disebutkan sebelumnya.

Saya memiliki komponen List berisi beberapa ListItem s, salah satunya dipilih dan disorot. Ketika saya mengklik ListItem untuk memilih dan menyorotnya, seluruh daftar (berisi anak-anaknya) akan dirender ulang lagi.

Saya tahu bahwa masalah ini mungkin tampak persis sama dengan komentar sebelumnya , tetapi sebenarnya tidak; setidaknya saya pikir begitu.

Mari kita lihat hasil dari React profiler:

image
Seperti yang Anda lihat, saya memiliki komponen MyList di tingkat atas gambar. Komponen ini hanya membungkus MUI List dan hanya membuatnya murni, yaitu:

class MyList extends React.PureComponent {
  render() {
    return (
      <List>
        {this.props.children}
      </List>
    );
  }
}

Saya menambahkan pembungkus ini karena @eps1lon di salah satu komentarnya menyebutkan bahwa rendering ulang List menyebabkan konteks diperbarui, dan pembaruan konteks ini membuat semua konsumen (termasuk ListItem s) merender ulang juga .

Saya juga mencoba membuat semua ListItem murni dan membuat profil aplikasi lagi. Hasilnya sama, kecuali komponen kustom saya (yaitu MyListItem ) tidak merender ulang _itself_, tetapi semua anak di bawahnya __did__.

Saya tahu masalah terjadi karena konteks yang digunakan MUI untuk menata ulang rendering _entah bagaimana_. Tapi saya tidak tahu mengapa rendering ulang ini terjadi dan bagaimana saya bisa menghindarinya.

Atau, apakah saya melakukan sesuatu yang salah?

Catatan: Saya menggunakan solusi penataan gaya baru (alfa) MUI, yaitu @material-ui/styles . Saya tidak tahu apakah ini penting.

@mkermani144 Hapus Material-UI dengan elemen asli, amati bahwa rendering ulang masih ada. Logika murni tidak akan membantu seperti ini. React.createElement membuat referensi baru di setiap render, itu membuat PureComponent Anda tidak valid.

Ya, saya tahu elemen adalah objek, dan objek tidak sepenuhnya sama dalam Javascript, jadi sCU gagal.

Tapi saya tidak mengerti apa yang Anda maksud ketika Anda mengatakan React.createElement dipanggil lagi. Panggilan mana ke createElement ? Jika maksud Anda panggilan di dalam List , itu hanya memanggil createElement untuk anak-anaknya ( ListItem s) hanya jika dirender ulang. Jika tidak dirender ulang, createElement akan dipanggil dan tidak ada re-render yang akan terjadi. Masalahnya adalah List itu sendiri dirender ulang.

@mkermani144 Jika Anda dapat membuat contoh reproduksi minimal, kita dapat melihatnya.

MyList (dan dengan demikian List ) dirender karena komponen yang merender MyList (sebut saja MyComponent ) dirender ulang. PureComponent pada MyList tidak membantu karena MyComponent telah dirender dan membuat turunan baru untuk MyList sehingga pemeriksaan MyList gagal.

MyComponent mungkin dirender ulang karena di sanalah Anda menyimpan status item yang dipilih.

Saya pikir implementasi Daftar MUI harus berubah untuk tidak membuat ulang nilai konteks Daftar setiap render
di sini: https://github.com/mui-org/material-ui/blob/fb4889f42613b05220c49f8fc361451066989328/packages/material-ui/src/List/List.js#L57

Jadi, alih-alih buat Daftar terlihat seperti ini:

const List = React.forwardRef(function List(props, ref) {
  const {
    children,
    classes,
    className,
    component: Component,
    dense,
    disablePadding,
    subheader,
    ...other
  } = props;
  const context = React.useMemo(() => ({ dense }), [dense]);

  return (
    <Component
      className={clsx(
        classes.root,
        {
          [classes.dense]: dense && !disablePadding,
          [classes.padding]: !disablePadding,
          [classes.subheader]: subheader,
        },
        className,
      )}
      ref={ref}
      {...other}
    >
      <ListContext.Provider value={context}>
        {subheader}
        {children}
      </ListContext.Provider>
    </Component>
  );
});

Itu akan menyederhanakan pembuatan versi sCU dari ListItems

MyList Anda (dan dengan demikian Daftar) dirender ulang karena komponen yang merender MyList (sebut saja MyComponent) dirender ulang. PureComponent di MyList tidak membantu karena MyComponent telah dirender dan membuat turunan baru untuk MyList sehingga pemeriksaan MyLists gagal.

@Pajn Tidak, lihat hasil profiler Bereaksi saya. MyList tidak merender ulang (berwarna abu-abu), tetapi List melakukannya (berwarna biru). Saya tidak bertahan pada PureComponent untuk MyList . Meskipun saya menerapkan sCU untuk MyList agar tidak merender ulang, List __merender ulang__.

@oliviertasinari
Saya membuat contoh reproduksi minimal:

import React, { Component } from 'react';

import StylesProvider from '@material-ui/styles/StylesProvider';
import ThemeProvider from '@material-ui/styles/ThemeProvider';

import { createMuiTheme } from '@material-ui/core';

import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';

const theme = createMuiTheme({});

const MyListItem = React.memo(ListItem, (prev, next) => prev.selected === next.selected);

class App extends Component {
  state = {
    selected: null,
  }
  render() {
    return (
      <StylesProvider>
        <ThemeProvider theme={theme}>
          <List>
            {[0, 1, 2, 3, 4].map(el => (
              <MyListItem
                button
                selected={el === this.state.selected}
                onClick={() => this.setState({ selected: el })}
              >
                {el}
              </MyListItem>
            ))}
          </List>
        </ThemeProvider>
      </StylesProvider>
    );
  }
}

export default App;

Bereaksi hasil profiler (setelah mengklik item daftar ke-4):

image

Seperti yang Anda lihat, ini berfungsi seperti yang diharapkan, yaitu tidak ada rendering ulang tambahan (kecuali komponen ButtonBase di dalam ListItem s). Masalahnya, reproduksi ini _terlalu minim_; ada banyak hal yang saya lewatkan di dalamnya.

Saya tahu Anda tidak dapat memberi tahu saya apa yang salah dengan kode saya yang menyebabkan rendering ulang ekstra. Tetapi saya mengajukan pertanyaan kepada Anda: Apa yang dapat menyebabkan rendering ulang pada komponen WithStylesInner yang membungkus komponen MUI?

@ mkermani144 Apa pendapat Anda tentang perbaikan ini?

--- a/packages/material-ui/src/List/List.js
+++ b/packages/material-ui/src/List/List.js
@@ -40,6 +40,13 @@ const List = React.forwardRef(function List(props, ref) {
     ...other
   } = props;

+  const context = React.useMemo(
+    () => ({
+      dense,
+    }),
+    [dense],
+  );
+
   return (
     <Component
       className={clsx(
@@ -54,7 +61,7 @@ const List = React.forwardRef(function List(props, ref) {
       ref={ref}
       {...other}
     >
-      <ListContext.Provider value={{ dense }}>
+      <ListContext.Provider value={context}>
         {subheader}
         {children}
       </ListContext.Provider>

Apakah Anda ingin mengajukan permintaan tarik? :) Kami menggunakan strategi yang sama dengan komponen Tabel. Ini bekerja dengan baik. Terima kasih telah melaporkan masalahnya!

@oliviertasinari Tentu. Inilah yang disarankan @Pajn sebelumnya. Saya mengajukan PR .

14934 digabungkan; komponen List , bagaimanapun, dapat menjadi hambatan kinerja jika cukup besar, tidak peduli seberapa banyak itu dioptimalkan. Bukankah seharusnya kita memberikan contoh yang menunjukkan penggunaan react-window atau react-virtualized dengan komponen List , seperti yang kita miliki di Table docs?

Bukankah seharusnya kita memberikan contoh yang menunjukkan penggunaan react-window atau react-virtualized dengan komponen List, seperti yang kita miliki di Tabel docs?

Itu bagus :+1:

Saat ini saya membuat aplikasi obrolan dan aplikasi tersebut perlu membuat daftar besar kontak. Saya mengalami masalah yang sama
@mkermani144 punya.

https://stackoverflow.com/questions/55969987/why-do-the-children-nodes-rerender-when-the-parent-node-is-not-even-being-update/55971559

@henrylearn2rock Sudahkah Anda mempertimbangkan untuk menggunakan virtualisasi? Kami telah menambahkan demo untuk daftar: https://next.material-ui.com/demos/lists/#virtualized -list.

Ini juga benar-benar membuatku tersandung. Saya pikir kebanyakan orang (termasuk saya) menganggap segala sesuatu di bawah komponen murni aman dari rerender, yang ternyata tidak berlaku untuk perpustakaan ini. Saya akan mencoba virtualisasi seperti yang baru-baru ini Anda sarankan. Terima kasih!

Saya pikir kebanyakan orang (termasuk saya) menganggap segala sesuatu di bawah komponen murni aman dari rerender, yang ternyata tidak berlaku untuk perpustakaan ini.

Ini bukan cara kerja React.PureComponent atau React.memo. Itu hanya mempengaruhi komponen itu sendiri. Anak-anak mungkin masih harus merender ulang jika konteksnya berubah.

@pytyl Bisakah Anda membagikan kode tempat Anda menggunakan PureComponent dan mengharapkannya untuk mencegah rendering ulang di sub-pohonnya?

@eps1lon dokumentasi berikut membuatnya tampak seperti mengembalikan false dari shouldComponentUpdate secara otomatis melewatkan render ulang pada komponen anak-anak.
https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate -in-action

Karena shouldComponentUpdate mengembalikan false untuk subtree yang di-root di C2, React tidak mencoba merender C2, dan dengan demikian bahkan tidak perlu memanggil shouldComponentUpdate pada C4 dan C5.

Mungkin saya salah dalam hal ini? Berikut ini adalah snapshot dari profiler saya. Hanya demi pengujian, saya secara eksplisit mengembalikan false untuk shouldComponentUpdate di komponen Menu saya:

Screen Shot 2019-05-08 at 7 46 32 PM

Ini membuat semua komponen anak saya (Kategori, Kategori, KategoriItem, KategoriItem) tidak dirender ulang. Banyak hal terkait MUI yang tampak dirender ulang di bagian bawah yang tampaknya menyebabkan banyak penundaan. Hal-hal seperti withStyles, Tipografi, ButtonBase. Masih sedikit baru dalam React jadi mohon maafkan ketidaktahuan saya. Di bawah ini adalah kode saya untuk komponen Menu (di mana saya mengembalikan false untuk shouldComponentUpdate):

import React, { Component } from "react";
import Categories from "./Categories";
import { withStyles, Paper } from "@material-ui/core";

const styles = theme => ({
  root: {
    paddingTop: 0,
    marginLeft: theme.spacing.unit * 2,
    marginRight: theme.spacing.unit * 2,
    marginTop: theme.spacing.unit * 1
  }
});

class Menu extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.categories.length == this.props.categories.length) {
      return false;
    }
    return true;
  }

  render() {
    const { classes, categories } = this.props;

    return (
      <Paper className={classes.root}>
        <Categories categories={categories} />
      </Paper>
    );
  }
}

export default withStyles(styles)(Menu);

Saya membutuhkan kode dan kotak lengkap untuk memahami masalah ini.

@eps1lon Saya akan mencoba memproduksinya untuk besok. Terima kasih.

@eps1lon di sini adalah codepennya:
https://codesandbox.io/s/348kwwymj5

Deskripsi Singkat
Ini adalah aplikasi menu dasar untuk restoran (yang sering kali memiliki lebih dari 100 item menu). Ketika pengguna mengklik item menu, itu akan membuka dialog "tambahkan ke pesanan". Saya akan melampirkan beberapa situasi di mana profiler menunjukkan kinerja yang buruk (statistik ini bukan pada produksi).

Sistem
MacBook Pro (Retina, 13 inci, Awal 2015)
Intel Core i7 3,1 GHz
Firefox 66.0.3

Kasus 1 (pengguna mengklik item menu)
Durasi render: 218ms

Screen Shot 2019-05-10 at 4 45 26 AM

Screen Shot 2019-05-10 at 4 45 48 AM

Kasus 2 (pengguna mengklik tombol tambahkan ke pesanan dalam dialog)
Durasi render: 356ms

Screen Shot 2019-05-10 at 4 46 24 AM

Screen Shot 2019-05-10 at 4 47 10 AM

Saya yakin saya membuat beberapa kesalahan pemula di sini sehingga panduan apa pun sangat dihargai.

Karena WithStyles(ButtonBase) dirender, saya berasumsi bahwa WithStyles menggunakan konteks yang dibuat ulang meskipun tidak perlu.

Saya berhasil menemukan ini https://github.com/mui-org/material-ui/blob/048c9ced0258f38aa38d95d9f1cfa4c7b993a6a5/packages/material-ui-styles/src/StylesProvider/StylesProvider.js#L38 tetapi tidak dapat menemukan tempat di mana StylesProvider digunakan dalam kode aktual (pencarian GitHubs tidak terlalu bagus) tetapi mungkin itu alasannya.

Apakah @eps1lon tahu apakah ini penyebabnya? Jika ya, useMemo pada objek konteks mungkin akan memperbaikinya. Meskipun saya tidak tahu apakah localOptions stabil atau jika useMemo perlu disebarkan lebih jauh.

Mungkin. Tetapi Anda harus menyelidiki terlebih dahulu mengapa komponen Anda menggunakan perenderan StylesProvider. Ini adalah sesuatu di bagian atas pohon Anda atau harus berada di beberapa batas UI. Dalam kedua kasus itu, itu jarang dirender. Ingat bahwa konteks reaksi tidak dioptimalkan untuk pembaruan yang sering dilakukan.

Kita tidak boleh terlalu dini mengoptimalkan hal-hal ini hanya karena beberapa objek dibuat ulang selama render. Memoisasi bukanlah peluru perak. Jadi tanpa contoh konkret saya tidak bisa berbuat banyak. Ya hal-hal re-render. Terkadang lebih sering dari yang mereka butuhkan. Tetapi rendering ulang yang sia-sia tidak berarti itu adalah penyebab kemacetan kinerja.

@pytyl Saya telah melihat kode dan kotak Anda, ada masalah dengan arsitektur rendering. Anda merender semuanya saat item menu diklik. GlobalContext Anda melompati logika murni.

@eps1lon Saya pikir kita harus menutup masalah ini. Akan lebih baik untuk fokus pada isu-isu yang diidentifikasi secara khusus.

TL; DR: Buat irisan konteks, memoize nilai konteks, tidak ada masalah dengan material-ui secara khusus: https://codesandbox.io/s/8lx6vk2978

Melakukan penggalian dan masalahnya adalah Anda memiliki konteks global besar yang dibuat ulang selama render. Anda merender ulang Aplikasi saat Anda mengklik pada titik mana konteks global dibuat ulang. CategoryItem Anda mendengarkannya yang muncul 100 kali di Aplikasi Anda. Karena Anda memiliki 100 Material-ui MenuItems, Anda menghadapi kematian klasik dengan seribu luka.

Jadi ironisnya bagian dari solusinya adalah memoisasi nilai konteks tetapi bagian yang penting adalah mengidentifikasi irisan konteks yang terpisah. Sepertinya konteks status dan pengiriman sudah sesuai. Ini direkomendasikan saat menggunakan useContext dengan useReducer dan sepertinya cocok di sini.

Ini dapat membuat pohon yang cukup besar dan membuat alat peraga semakin banyak konteks yang Anda miliki. Saya mendorong Anda untuk melihat useContext . Ini akan banyak membantu jika Anda mulai menghadapi masalah ini.

@oliviertasinari Ini masalah yang baik untuk mengumpulkan perangkap umum dengan solusi. Kami dapat memutuskan apakah kami ingin membuat masalah terpisah darinya.

@oliviertasinari @eps1lon terima kasih sudah merevisi! Kinerja tampak hebat.

Saya baru saja mengalami masalah dengan kinerja rendering yang lambat. Saya menyelesaikannya sepenuhnya dengan mengganti semua instance dari komponen <Box> dengan <div> s. Saya men-debug menggunakan react devtools flamegraph, dan saya beralih dari sekitar 420ms ke 20ms.

Dengan <Box> es;
Screen Shot 2019-08-16 at 12 47 25 AM

Tanpa <Box> es:
Screen Shot 2019-08-16 at 12 42 38 AM

@mankittens Anda dapat menyimpan komponen Box, menggunakan komponen-gaya sebagai mesin gaya. Performanya akan jauh lebih baik. Ini akan menjadi lebih baik dengan JSS dalam waktu dekat https://github.com/mui-org/material-ui/pull/16858 .

Saya menutup masalah ini. Kami membutuhkan laporan kinerja khusus untuk setiap area potensial peningkatan, bukan benang payung.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat