Semua yang saya baca tentang praktik pengkodean PHP yang lebih baik terus mengatakan jangan gunakan require_once
karena kecepatan.
Kenapa ini?
Apa cara yang tepat / lebih baik untuk melakukan hal yang sama require_once
? Jika itu penting, saya menggunakan PHP 5.
php
performance
require-once
Uberfuzzy
sumber
sumber
Jawaban:
require_once
daninclude_once
keduanya mengharuskan sistem menyimpan log dari apa yang sudah termasuk / diperlukan. Setiap*_once
panggilan berarti memeriksa log itu. Jadi pasti ada beberapa pekerjaan tambahan yang dilakukan di sana tetapi cukup untuk merusak kecepatan seluruh aplikasi?... Aku benar-benar ragu itu ... Tidak, kecuali Anda berada di benar-benar hardware lama atau melakukan itu banyak .
Jika Anda sedang melakukan ribuan
*_once
, Anda bisa melakukan pekerjaan sendiri dengan cara yang lebih ringan. Untuk aplikasi sederhana, hanya memastikan Anda hanya disertakan sekali harus cukup tetapi jika Anda masih mendapatkan kesalahan mendefinisikan kembali, Anda bisa sesuatu seperti ini:Saya pribadi akan tetap dengan
*_once
pernyataan tetapi pada patokan juta pass konyol, Anda dapat melihat perbedaan antara keduanya:10-100 × lebih lambat dengan
require_once
dan anehnyarequire_once
tampaknya lebih lambathhvm
. Sekali lagi, ini hanya relevan dengan kode Anda jika Anda menjalankan*_once
ribuan kali.sumber
Utas ini membuat saya merasa ngeri, karena sudah ada "solusi yang diposting", dan itu, untuk semua maksud dan tujuan, salah. Mari kita hitung:
Definisinya sangat mahal di PHP. Anda dapat mencarinya atau mengujinya sendiri, tetapi satu-satunya cara efisien mendefinisikan konstanta global dalam PHP adalah melalui ekstensi. (Konstanta kelas sebenarnya kinerja yang lumayan bijaksana, tapi ini adalah poin yang diperdebatkan, karena 2)
Jika Anda menggunakan dengan
require_once()
tepat, yaitu, untuk memasukkan kelas, Anda bahkan tidak perlu mendefinisikan; periksa saja apakahclass_exists('Classname')
. Jika file yang Anda sertakan berisi kode, yaitu Anda menggunakannya dengan cara prosedural, sama sekali tidak ada alasan yangrequire_once()
harus diperlukan untuk Anda; setiap kali Anda memasukkan file yang Anda anggap melakukan panggilan subrutin.Jadi untuk sementara, banyak orang yang menggunakan
class_exists()
metode ini untuk inklusi mereka. Saya tidak suka karena ini jelek, tetapi mereka punya alasan bagus untuk:require_once()
cukup tidak efisien sebelum beberapa versi PHP yang lebih baru. Tapi itu sudah diperbaiki, dan menurut pendapat saya bahwa bytecode tambahan yang harus Anda kompilasi untuk kondisional, dan panggilan metode tambahan, akan jauh melebihi pemeriksaan hashtable internal apa pun.Sekarang, sebuah pengakuan: hal ini sulit untuk diuji, karena hanya menyumbang sedikit waktu eksekusi.
Berikut adalah pertanyaan yang harus Anda pikirkan: termasuk, sebagai aturan umum, mahal dalam PHP, karena setiap kali penerjemah menemukan satu harus beralih kembali ke mode parse, menghasilkan opcodes, dan kemudian melompat kembali. Jika Anda memiliki 100+ termasuk, ini pasti akan memiliki dampak kinerja. Alasan mengapa menggunakan atau tidak menggunakan require_once adalah pertanyaan yang sangat penting adalah karena ini membuat susah untuk cache opcode. Sebuah penjelasan untuk ini dapat ditemukan di sini, tapi apa ini intinya adalah bahwa:
Jika selama parse time, Anda tahu persis apa yang termasuk file yang akan Anda butuhkan untuk seluruh umur permintaan,
require()
yang di awal dan cache opcode akan menangani semua yang lain untuk Anda.Jika Anda tidak menjalankan opcode cache, Anda berada di tempat yang sulit. Memasukkan semua menyertakan Anda ke dalam satu file (jangan lakukan ini selama pengembangan, hanya dalam produksi) pasti dapat membantu mengurai waktu, tetapi itu menyebalkan untuk dilakukan, dan juga, Anda perlu tahu persis apa yang akan Anda sertakan selama permintaan.
Autoload sangat mudah, tetapi lambat, dengan alasan bahwa logika autoload harus dijalankan setiap kali menyertakan. Dalam praktiknya, saya telah menemukan bahwa autoloading beberapa file khusus untuk satu permintaan tidak menyebabkan terlalu banyak masalah, tetapi Anda seharusnya tidak autoloading semua file yang Anda perlukan.
Jika Anda memiliki 10 termasuk (ini adalah bagian paling belakang dari perhitungan amplop), semua wanking ini tidak sepadan: hanya mengoptimalkan permintaan basis data Anda atau sesuatu.
sumber
define()
,require_once()
dandefined()
semua memakan waktu sekitar 1-2 mikrodetik pada komputer saya.Saya jadi penasaran dan melihat tautan Adam Backstrom ke Tech Your Universe . Artikel ini menjelaskan salah satu alasan yang mengharuskan harus digunakan alih-alih require_once. Namun, klaim mereka tidak sesuai dengan analisis saya. Saya akan tertarik melihat di mana saya mungkin telah misanalysed solusinya. Saya menggunakan PHP 5.2.0 untuk perbandingan.
Saya mulai dengan membuat 100 file header yang menggunakan require_once untuk memasukkan file header lainnya. Masing-masing file ini terlihat seperti:
Saya membuat ini menggunakan Bash hack cepat:
Dengan cara ini saya bisa dengan mudah bertukar antara menggunakan require_once dan membutuhkan ketika menyertakan file header. Saya kemudian membuat app.php untuk memuat seratus file. Ini terlihat seperti:
Saya membandingkan header require_once dengan header yang menggunakan file header seperti:
Saya tidak menemukan banyak perbedaan ketika menjalankan ini dengan require vs require_once. Sebenarnya, tes awal saya sepertinya menyiratkan bahwa require_once sedikit lebih cepat, tapi saya tidak perlu percaya itu. Saya mengulangi percobaan dengan 10.000 file input. Di sini saya memang melihat perbedaan yang konsisten. Saya menjalankan tes beberapa kali, hasilnya dekat tetapi menggunakan require_once menggunakan rata-rata 30,8 pengguna jiffies dan 72,6 sistem jiffies; menggunakan memerlukan menggunakan rata-rata 39,4 pengguna jiffies dan 72,0 sistem jiffies. Oleh karena itu, tampak bahwa bebannya sedikit lebih rendah menggunakan require_once. Namun, waktu jam dinding sedikit meningkat. 10.000 panggilan need_once menggunakan rata-rata 10,15 detik untuk menyelesaikan dan rata-rata 10.000 panggilan menggunakan 9,84 detik.
Langkah selanjutnya adalah melihat perbedaan-perbedaan ini. Saya menggunakan strace untuk menganalisis panggilan sistem yang sedang dibuat.
Sebelum membuka file dari require_once, panggilan sistem berikut dilakukan:
Ini kontras dengan membutuhkan:
Tech Your Universe menyiratkan bahwa require_once harus membuat lebih banyak panggilan lstat64. Namun, keduanya melakukan panggilan lstat64 dengan jumlah yang sama. Mungkin, perbedaannya adalah saya tidak menjalankan APC untuk mengoptimalkan kode di atas. Namun, selanjutnya saya membandingkan output strace untuk seluruh proses:
Secara efektif ada sekitar dua panggilan sistem per file header saat menggunakan require_once. Salah satu perbedaannya adalah require_once memiliki panggilan tambahan ke fungsi time ():
Panggilan sistem lainnya adalah getcwd ():
Ini disebut karena saya memutuskan jalur relatif yang direferensikan dalam file hdrXXX. Jika saya menjadikan ini sebagai referensi absolut, maka satu-satunya perbedaan adalah panggilan waktu tambahan (NULL) yang dibuat dalam kode:
Ini tampaknya menyiratkan bahwa Anda dapat mengurangi jumlah panggilan sistem dengan menggunakan jalur absolut daripada jalur relatif. Satu-satunya perbedaan di luar itu adalah panggilan waktu (NULL) yang tampaknya digunakan untuk menginstruksikan kode untuk membandingkan apa yang lebih cepat.
Satu catatan lain adalah bahwa paket optimasi APC memiliki opsi yang disebut "apc.include_once_override" yang mengklaim bahwa itu mengurangi jumlah panggilan sistem yang dilakukan oleh require_once dan panggilan include_once (lihat dokumentasi PHP ).
sumber
Bisakah Anda memberi kami tautan ke praktik pengkodean ini yang mengatakan untuk menghindarinya? Sejauh yang saya ketahui, ini sepenuhnya bukan masalah . Saya belum melihat kode sumber sendiri, tapi saya akan membayangkan bahwa satu-satunya perbedaan antara
include
daninclude_once
adalah yanginclude_once
menambahkan nama file ke array dan memeriksa array setiap kali. Akan mudah untuk menjaga array itu diurutkan, jadi mencari di atasnya harus O (log n), dan bahkan aplikasi menengah-hanya akan memiliki beberapa lusin termasuk.sumber
Cara yang lebih baik untuk melakukan sesuatu adalah menggunakan pendekatan berorientasi objek dan menggunakan __autoload () .
sumber
__autoload()
tidak disarankan dan mungkin akan usang di masa mendatang, Anda harus menggunakanspl_autoload_register(...)
hari-hari ini ... PS2: jangan salah, saya kadang-kadang menggunakan fungsi pengisian otomatis; )Itu tidak menggunakan fungsi yang buruk. Ini adalah pemahaman yang salah tentang bagaimana dan kapan menggunakannya, dalam basis kode keseluruhan. Saya hanya akan menambahkan sedikit konteks pada gagasan yang mungkin disalahpahami ini:
Orang seharusnya tidak berpikir bahwa require_once adalah fungsi yang lambat. Anda harus memasukkan kode Anda dengan satu atau lain cara. Kecepatan
require_once()
vsrequire()
bukan masalahnya. Ini tentang kinerja yang menghambat peringatan yang dapat menyebabkan penggunaannya secara membabi buta. Jika digunakan secara luas tanpa mempertimbangkan konteks, ini dapat menyebabkan pemborosan memori yang besar atau kode yang boros.Apa yang saya lihat itu benar-benar buruk, adalah ketika kerangka kerja monolitik besar menggunakan
require_once()
semua cara yang salah, terutama dalam lingkungan berorientasi objek (OO) yang kompleks.Ambil contoh penggunaan
require_once()
di bagian atas setiap kelas seperti yang terlihat di banyak perpustakaan:Jadi
User
kelas dirancang untuk menggunakan ketiga kelas lainnya. Cukup adil!Tapi sekarang bagaimana jika pengunjung menelusuri situs dan bahkan tidak masuk dan kerangka memuat:
require_once("includes/user.php");
untuk setiap permintaan tunggal.Ini termasuk 1 + 3 kelas yang tidak perlu yang tidak akan pernah digunakan selama permintaan khusus itu. Beginilah kerangka kerja yang kembung akhirnya menggunakan 40 MB per permintaan dibandingkan dengan 5 MB atau kurang.
Cara lain yang bisa disalahgunakan, adalah ketika kelas digunakan kembali oleh banyak orang lain! Katakanlah Anda memiliki sekitar 50 kelas yang menggunakan
helper
fungsi. Untuk memastikanhelpers
tersedia untuk kelas-kelas tersebut ketika mereka dimuat, Anda mendapatkan:Tidak ada yang salah di sini. Namun jika satu permintaan halaman menyertakan 15 kelas yang sama. Anda menjalankan
require_once
15 kali, atau untuk visual yang bagus:Penggunaan require_once () secara teknis mempengaruhi kinerja untuk menjalankan fungsi itu 14 kali, selain harus mengurai baris-baris yang tidak perlu. Dengan hanya 10 kelas yang sangat sering digunakan dengan masalah yang sama, itu bisa menjelaskan 100+ baris kode berulang yang agak tidak berguna.
Dengan itu, mungkin layak digunakan
require("includes/helpers.php");
di bootstrap aplikasi atau kerangka kerja Anda. Tapi karena semuanya relatif, itu semua tergantung apakah bobot versus frekuensi penggunaanhelpers
kelas layak menghemat 15-100 barisrequire_once()
. Tetapi jika probabilitas tidak menggunakanhelpers
file pada permintaan yang diberikan tidak ada, makarequire
seharusnya harus di kelas utama Anda sebagai gantinya. Memilikirequire_once
di setiap kelas secara terpisah menjadi pemborosan sumber daya.The
require_once
Fungsi ini berguna bila diperlukan, tetapi tidak harus dianggap sebagai solusi monolitik untuk menggunakan mana-mana untuk memuat semua kelas.sumber
Wiki PEAR2 (bila ada) digunakan untuk membuat daftar alasan yang baik untuk meninggalkan semua arahan yang memerlukan / menyertakan yang mendukung pemuatan otomatis , setidaknya untuk kode pustaka. Ini mengikat Anda ke struktur direktori yang kaku ketika model kemasan alternatif seperti phar berada di cakrawala.
Pembaruan: Karena versi arsip web dari wiki jelek sekali, saya telah menyalin alasan paling meyakinkan di bawah ini:
sumber
The
*_once()
fungsi -stat setiap direktori induk untuk memastikan file Anda termasuk tidak sama sebagai salah satu yang sudah dimasukkan. Itu bagian dari alasan perlambatan.Saya sarankan menggunakan alat seperti Pengepungan untuk pembandingan. Anda dapat mencoba semua metodologi yang disarankan dan membandingkan waktu respons.
Lebih lanjut tentang
require_once()
ada di Tech Your Universe .sumber
Bahkan jika
require_once
daninclude_once
lebih lambat daripadarequire
daninclude
(atau alternatif apa pun yang mungkin ada), kita berbicara tentang tingkat terkecil optimasi mikro di sini. Waktu Anda jauh lebih baik dihabiskan untuk mengoptimalkan perulangan atau kueri basis data yang buruk daripada mengkhawatirkan sesuatu seperti iturequire_once
.Sekarang, orang dapat membuat argumen yang mengatakan bahwa
require_once
praktik pengkodean yang buruk dapat dilakukan karena Anda tidak perlu memperhatikan menjaga kebersihan dan keteraturan Anda, tetapi itu tidak ada hubungannya dengan fungsi itu sendiri dan terutama bukan kecepatannya.Jelas, autoloading lebih baik demi kebersihan kode dan kemudahan pemeliharaan, tetapi saya ingin menjelaskan bahwa ini tidak ada hubungannya dengan kecepatan .
sumber
Anda menguji, menggunakan menyertakan, alternatif oli dan __autoload (); dan mengujinya dengan sesuatu seperti APC diinstal.
Saya ragu menggunakan konstanta akan mempercepat.
sumber
Ya, ini sedikit lebih mahal daripada yang dibutuhkan (). Saya pikir intinya adalah jika Anda dapat menjaga kode Anda cukup teratur untuk tidak duplikat termasuk, jangan gunakan fungsi * _once (), karena akan menghemat beberapa siklus.
Tetapi menggunakan fungsi _once () tidak akan mematikan aplikasi Anda. Pada dasarnya, jangan gunakan itu sebagai alasan untuk tidak perlu mengatur termasuk Anda . Dalam beberapa kasus, menggunakannya masih tidak dapat dihindari, dan itu bukan masalah besar.
sumber
Saya pikir dalam dokumentasi PEAR, ada rekomendasi untuk mengharuskan, require_once, sertakan dan sertakan_once. Saya memang mengikuti pedoman itu. Aplikasi Anda akan lebih jelas.
sumber
Ini tidak ada hubungannya dengan kecepatan. Ini tentang gagal dengan anggun.
Jika require_once () gagal, skrip Anda selesai. Tidak ada yang diproses. Jika Anda menggunakan include_once () skrip Anda yang lain akan mencoba untuk melanjutkan render, sehingga pengguna Anda berpotensi tidak akan mengetahui apa pun yang gagal dalam skrip Anda.
sumber
Pendapat pribadi saya adalah bahwa penggunaan require_once (atau include_once) adalah praktik yang buruk karena require_once memeriksa Anda jika Anda sudah menyertakan file itu dan menekan kesalahan dua file yang dimasukkan yang mengakibatkan kesalahan fatal (seperti duplikat fungsi / kelas / dll.) .
Anda harus tahu jika Anda perlu memasukkan file.
sumber