php-memprof เป็นส่วนเสริมการทำโปรไฟล์หน่วยความจำที่รวดเร็วและแม่นยำสำหรับ PHP ซึ่งสามารถใช้เพื่อค้นหาสาเหตุของการรั่วไหลของหน่วยความจำ
ส่วนขยายจะติดตามการจัดสรรและปล่อยบล็อกหน่วยความจำเพื่อรายงานจำนวนหน่วยความจำที่รั่วไหลโดยทุกฟังก์ชัน วิธีการ หรือไฟล์ในโปรแกรม
รายงานหน่วยความจำที่ไม่ว่างตามจุดต่างๆ ในโปรแกรม
ดัมพ์โปรไฟล์ในรูปแบบ callgrind, pprof หรืออาร์เรย์ดิบ
สามารถติดตามหน่วยความจำที่จัดสรรโดย PHP เองและ malloc ดั้งเดิม
php-memprof ขึ้นอยู่กับ libjudy และ sys/queue.h
ในการแจกแจงแบบอิง Debian สามารถติดตั้งการขึ้นต่อกันด้วย:
# Debian or Ubuntu: apt install libjudy-dev
บนอัลไพน์:
# Alpine apk add judy-dev bsd-compat-headers
บน MacOS:
# install libjudy dependency: brew install traildb/judy/judy
ตรวจสอบให้แน่ใจว่าได้ติดตั้งการอ้างอิงแล้ว:
pecl install memprof
บน MacOS: JUDY_DIR=$(brew --prefix traildb/judy/judy) pecl ติดตั้ง memprof
หมายเหตุ หากมีการติดตั้ง libjudy ในเส้นทางที่ไม่เป็นมาตรฐาน (ไม่ใช่ /usr หรือ /usr/local) โปรดใช้วิธีการติดตั้งด้วยตนเองดังต่อไปนี้
ตรวจสอบให้แน่ใจว่าได้ติดตั้งการอ้างอิงแล้ว:
ดาวน์โหลดซอร์สและรันคำสั่งต่อไปนี้ในไดเร็กทอรีต้นทาง:
phpize ./configure make make install
หมายเหตุ หากติดตั้ง libjudy ในพาธที่ไม่เป็นมาตรฐาน (ไม่ใช่ /usr หรือ /usr/local) คุณสามารถระบุได้ดังนี้:
./configure --with-judy-dir=/opt/homebrew/Cellar/judy/1.0.5
ผู้ใช้ Arch Linux อาจต้องการติดตั้งแพ็คเกจ php-memprof อย่างไม่เป็นทางการด้วย makepkg
หรือตัวช่วย AUR ที่พวกเขาต้องการ หากใช้ yay
เช่น:
yay -S php-memprof
โปรดรายงานปัญหาใด ๆ เกี่ยวกับแพ็คเกจนี้ในหน้า AUR
สามารถโหลดส่วนขยายบนบรรทัดคำสั่งได้เพียงสคริปต์เดียว:
php -dextension=memprof.so script.php
หรือถาวรใน php.ini:
extension=memprof.so
ส่วนขยายไม่มีค่าใช้จ่ายใด ๆ เมื่อไม่ได้จัดทำโปรไฟล์ ดังนั้นจึงสามารถโหลดได้ตามค่าเริ่มต้นในสภาพแวดล้อมการพัฒนา
วิธีที่ง่ายที่สุดในการใช้ memprof
คือปล่อยให้มันบันทึกโปรไฟล์หน่วยความจำเมื่อเกินขีดจำกัดหน่วยความจำของโปรแกรม
dump_on_limit
การทำโปรไฟล์ในโหมด dump_on_limit
ถูกเปิดใช้งานเมื่อร้องขอการเริ่มต้นระบบเมื่อข้อใดข้อหนึ่งต่อไปนี้เป็นจริง:
ตัวแปรสภาพแวดล้อม MEMPROF_PROFILE
เท่ากับ dump_on_limit
$_GET["MEMPROF_PROFILE"]
เท่ากับ dump_on_limit
$_POST["MEMPROF_PROFILE"]
เท่ากับ dump_on_limit
สำหรับสคริปต์บรรทัดคำสั่ง เราสามารถตั้งค่าตัวแปรสภาพแวดล้อมได้:
MEMPROF_PROFILE=dump_on_limit php test.php
สำหรับเว็บสคริปต์ เราสามารถตั้งค่าตัวแปร $_GET
ได้:
curl http://127.0.0.1/test.php?MEMPROF_PROFILE=dump_on_limit
หรือตัวแปร $_POST
:
curl -d MEMPROF_PROFILE=dump_on_limit http://127.0.0.1/test.php
หมายเหตุ สามารถเรียกใช้ฟังก์ชัน
memprof_enabled_flags()
เพื่อตรวจสอบว่าปัจจุบันเปิดใช้งานการทำโปรไฟล์ในโหมดdump_on_limit
หรือไม่
ในโหมดนี้ memprof
จะบันทึกโปรไฟล์โดยอัตโนมัติหากโปรแกรมเกินขีดจำกัดหน่วยความจำ (เมื่อ PHP ก่อให้เกิดข้อผิดพลาด เช่น Fatal error: Allowed memory size of 15728640 bytes exhausted (tried to allocate 1024 bytes)
ข้อผิดพลาด)
ตามค่าเริ่มต้น โปรไฟล์จะถูกบันทึกในไฟล์ชื่อ memprof.callgrind.*
ใน /tmp
หรือ C:WindowsTemp
วิธีที่แนะนำในการแสดงผลลัพธ์เป็นภาพคือใช้ Kcachegrind (บน Linux) หรือ Qcachegrind (บน MacOS, Windows) รองรับ Google Perftools ด้วย ดูเอกสารประกอบของ memprof_dump_callgrind()
และตัวแปร
การแจกแจงส่วนใหญ่มีแพ็คเกจ kcachegrind
ที่พร้อมสำหรับการติดตั้ง
ตัวอย่างเช่น Ubuntu หรือ Debian:
sudo apt install kcachegrind
ดิสทริบิวชันอื่นๆ มักมีแพ็คเกจที่พร้อมสำหรับการติดตั้งเช่นกัน
ใช้โฮมบรูว์: https://formulae.brew.sh/formula/qcachegrind
ดาวน์โหลดได้จาก https://sourceforge.net/projects/qcachegrindwin/
เปิดใช้งานการทำโปรไฟล์เมื่อคำขอเริ่มต้นเมื่อข้อใดข้อหนึ่งต่อไปนี้เป็นจริง:
ตัวแปรสภาพแวดล้อม MEMPROF_PROFILE
ไม่ว่างเปล่า
$_GET["MEMPROF_PROFILE"]
ไม่ว่างเปล่า
$_POST["MEMPROF_PROFILE"]
ไม่ว่างเปล่า
ตัวแปร MEMPROF_PROFILE
ยอมรับรายการแฟล็กที่คั่นด้วยเครื่องหมายจุลภาค
ตัวอย่างของค่า MEMPROF_PROFILE
ที่ถูกต้อง:
1
: ไม่ว่างเปล่า: เปิดใช้งานการทำโปรไฟล์แล้ว
dump_on_limit
: เปิดใช้งานโปรไฟล์แล้ว จะดัมพ์ตามขีดจำกัดหน่วยความจำ
native
: เปิดใช้งานการทำโปรไฟล์ โดยจะทำโปรไฟล์การจัดสรรดั้งเดิม
dump_on_limit,native
: เปิดใช้งานการทำโปรไฟล์, จะทำโปรไฟล์การจัดสรรดั้งเดิม, จะถ่ายโอนข้อมูลบนขีดจำกัดหน่วยความจำ
รายการธงที่ถูกต้อง:
dump_on_limit
: จะดัมพ์โปรไฟล์ในรูปแบบ callgrind ใน /tmp
หรือ C:WindowsTemp
ไดเร็กทอรีเอาต์พุตสามารถเปลี่ยนแปลงได้ด้วยการตั้งค่า memprof.output_dir
ini
native
: จะทำการโปรไฟล์การจัดสรร malloc()
ดั้งเดิม ไม่ใช่แค่ของ PHP เท่านั้น (ซึ่งไม่ปลอดภัยสำหรับเธรด ดูด้านล่าง)
Memprof จะไม่ติดตามการจัดสรรดั้งเดิมตามค่าเริ่มต้น แต่สามารถเปิดใช้งานได้โดยการตั้งค่า MEMPROF_PROFILE
เป็น native
การจัดสรรแบบเนทีฟเป็นการจัดสรรที่ทำนอกตัวจัดสรรหน่วยความจำของ PHP โดยทั่วไปแล้ว ไลบรารีภายนอก เช่น libxml2 (ใช้ในส่วนขยาย DOM) ทำการจัดสรรแบบเนทิฟ PHP ยังสามารถจัดสรรทรัพยากรแบบเนทีฟสำหรับทรัพยากรถาวรได้
การเปิดใช้งานการติดตามการจัดสรรดั้งเดิมจะจัดโปรไฟล์การจัดสรรเหล่านี้ นอกเหนือจากการจัดสรรของ PHP เอง
โปรดทราบว่าเมื่อเปิดใช้งานการติดตามดั้งเดิม โปรแกรมจะหยุดทำงานหากไลบรารีดั้งเดิมใช้เธรด เนื่องจาก hooks พื้นฐานไม่ปลอดภัยสำหรับเธรด
รูปแบบไฟล์เอาต์พุตถูกกำหนดด้วยการตั้งค่า memprof.output_format
ini ตัวเลือกคือ:
callgrind
(ค่าเริ่มต้น)
pprof
หมายเหตุ : สิ่งนี้อาจใช้ได้เฉพาะเมื่อมีการสร้างส่วนขยายจากแหล่งที่มา (และไม่ได้ติดตั้งด้วย pecl) ตั้งแต่ #101
คืนค่าว่าโปรไฟล์หน่วยความจำเปิดใช้งานอยู่หรือไม่ (ดูด้านบน)
ส่งคืนว่าโปรไฟล์หน่วยความจำและคุณลักษณะโปรไฟล์ใดบ้างที่เปิดใช้งาน (ดูด้านบน)
ดัมพ์โปรไฟล์ปัจจุบันในรูปแบบ callgrind สามารถมองเห็นผลลัพธ์ได้ด้วยเครื่องมือ เช่น KCacheGrind หรือ QCacheGrind
<phpmemprof_dump_callgrind(fopen("เอาท์พุท", "w"));
นี่คือภาพหน้าจอ QcacheGrind:
ดัมพ์โปรไฟล์ปัจจุบันในรูปแบบ pprof
<?phpmemprof_dump_pprof(fopen("profile.heap", "w"));
สามารถมองเห็นไฟล์ได้ด้วยเครื่องมือ pprof
ของ google-perftools (ดูคำแนะนำในการติดตั้งด้านล่าง)
แสดงกราฟการโทรที่มีคำอธิบายประกอบในเว็บเบราว์เซอร์หรือใน gv
:
$ pprof --web profile.heap $ # or: $ pprof --gv profile.heap
เอาต์พุตหนึ่งบรรทัดต่อฟังก์ชัน จัดเรียงตามการใช้หน่วยความจำของตัวเอง:
$ pprof --text profile.heap
pprof
ติดตั้ง: Ubuntu: apt install google-perftools
บน Ubuntu เครื่องมือมีชื่อว่า google-pprof
ดังนั้นคุณต้องแทนที่ pprof
ด้วย google-pprof
ในตัวอย่างด้านบน
ส่งกลับอาร์เรย์ที่แสดงถึงโปรไฟล์ปัจจุบัน
<php$dump = memprof_dump_array();
อาร์เรย์เปิดเผยข้อมูลต่อไปนี้:
หน่วยความจำแบบรวมและแบบเอกสิทธิ์เฉพาะบุคคลรั่วไหลโดยฟังก์ชัน (นับเฉพาะหน่วยความจำที่ยังไม่ถูกปลดปล่อยเมื่อมีการเรียก memprov_dump_array)
จำนวนบล็อกแบบรวมและแบบเอกสิทธิ์เฉพาะบุคคล (จำนวนการจัดสรร นับเฉพาะบล็อกที่ยังไม่ถูกปล่อยเมื่อมีการเรียก memprof_dump_array)
ข้อมูลจะถูกนำเสนอใน call stacks ด้วยวิธีนี้ หากฟังก์ชันถูกเรียกใช้จากหลายแห่ง ก็เป็นไปได้ที่จะดูว่าเส้นทางการโทรใดที่ทำให้หน่วยความจำรั่วไหลมากที่สุด
Array ( [memory_size] => 11578 [blocks_count] => 236 [memory_size_inclusive] => 10497691 [blocks_count_inclusive] => 244 [calls] => 1 [called_functions] => Array ( [main] => Array ( [memory_size] => 288 [blocks_count] => 3 [memory_size_inclusive] => 10486113 [blocks_count_inclusive] => 8 [calls] => 1 [called_functions] => Array ( [a] => Array ( [memory_size] => 4 [blocks_count] => 1 [memory_size_inclusive] => 10485825 [blocks_count_inclusive] => 5 [calls] => 1 [called_functions] => Array ( [b] => Array ( [memory_size] => 10485821 [blocks_count] => 4 [memory_size_inclusive] => 10485821 [blocks_count_inclusive] => 4 [calls] => 1 [called_functions] => Array ( [str_repeat] => Array ( [memory_size] => 0 [blocks_count] => 0 [memory_size_inclusive] => 0 [blocks_count_inclusive] => 0 [calls] => 1 [called_functions] => Array ( ) ) ) ) ) ) [memprof_dump_array] => Array ( [memory_size] => 0 [blocks_count] => 0 [memory_size_inclusive] => 0 [blocks_count_inclusive] => 0 [calls] => 1 [called_functions] => Array ( ) ) ) ) ) )
ส่งกลับเวอร์ชันของส่วนขยายเป็นสตริง สามารถเปรียบเทียบเวอร์ชันกับ version_compare() ได้
ส่วนขยายอาจขัดแย้งกับ xdebug, blackfire หรือส่วนขยายอื่นๆ หากเป็นเช่นนั้นสำหรับคุณ โปรดรายงานเรื่องนี้
สาขาปัจจุบันรองรับ PHP 7.1 ถึง PHP 8
สาขา php5 รองรับ PHP 5
ดูที่ INTERNALS.md