Jika anda memanggil file_exists($path) dan $path merujuk kepada bucket Amazon S3, anda tidak sedang mengakses cakera tempatan—anda sedang membuat permintaan rangkaian. Semakan satu baris tersebut menjadi satu perjalanan pergi-balik (round-trip) ke S3 yang boleh menambah puluhan milisaat kepada setiap permintaan.
PHP menyembunyikan storan jauh di sebalik pembungkus aliran (stream wrappers). Fungsi seperti fopen(), file_exists(), is_dir(), unlink() dan file_put_contents() disalurkan melalui pembungkus ini, yang menterjemah panggilan tersebut kepada operasi API S3. Pemetaan tersebut adalah ringkas:
file_exists()→ HeadObjectis_dir()→ ListObjectsunlink()→ DeleteObjectfile_put_contents()→ PutObject
Setiap panggilan mengalami kependaman (latency) yang sama seperti permintaan API S3 yang berkaitan. Apabila skrip menyemak berpuluh-puluh fail, ia mewujudkan corak gaya N+1: satu lompatan rangkaian untuk setiap semakan.
Mengapa ia penting sekarang
Dalam persekitaran pembangunan tipikal, sistem fail berada pada mesin yang sama, jadi semakan tersebut kembali hampir serta-merta. Dalam pengeluaran (production), di mana aset berada di S3, kod yang sama mewujudkan penurunan prestasi yang mendadak. AWS SDK menyimpan sebahagian hasil dalam memori, menjadikan semakan berulang dalam satu proses PHP kelihatan pantas. Walau bagaimanapun, kebanyakan penggunaan (deployment) PHP memulakan proses baharu untuk setiap permintaan web, sekali gus mengosongkan cache setiap kali. Hasilnya: satu perjalanan pergi-balik rangkaian penuh untuk setiap laluan unik pada setiap permintaan.
Sebuah laman web WordPress pernah mengambil masa sepuluh saat untuk memaparkan halaman utamanya. Pertanyaan pangkalan data adalah pantas, tetapi halaman tersebut mencetuskan 73 panggilan S3 individu hanya untuk menyusun kandungan. Setiap panggilan adalah permintaan sejuk (cold request), menukarkan file_exists() yang kelihatan tidak berbahaya kepada kelewatan yang ketara.
Strategi mitigasi
- Simpan cache merentasi permintaan – Pindahkan cache dalam proses ke storan kongsi seperti Redis. Apabila satu permintaan mendapati sesuatu kunci wujud di S3, permintaan seterusnya akan membaca hasil cache tersebut dan bukannya menghubungi S3 semula.
- Gunakan aliran kerja mengutamakan tempatan (local-first) – Tulis fail ke cakera tempatan, kemudian selaraskannya (sync) ke S3 secara asinkronus. Laluan permintaan utama hanya menyentuh sistem fail tempatan; kos rangkaian beralih ke tugasan latar belakang (background job).
- Audit kod sumber – Cari secara sistematik fungsi sistem fail yang mungkin diselesaikan kepada pembungkus jauh. Tandakan mana-mana fungsi yang muncul di dalam gelung (loop) yang padat atau laluan kritikal permintaan.
- Periksa data APM – Jika masa tindak balas melonjak manakala metrik pangkalan data kekal mendatar, teliti masa SDK storan. Peningkatan mendadak dalam kependaman SDK sering kali menunjukkan panggilan S3 yang tersembunyi.
Kesimpulan utama: satu fungsi yang kelihatan seperti semakan tempatan dalam mikrosaat boleh menyembunyikan kependaman rangkaian selama puluhan milisaat. Anggap file_exists() pada S3 sebagai panggilan luaran, simpan hasilnya dalam cache, dan alihkan beban kerja berat keluar daripada laluan permintaan. Jika tidak, kependaman tersembunyi akan terus memperlahankan laman web anda, satu demi satu permintaan rangkaian yang tidak kelihatan.
