คุณไม่สามารถคำนวณรอยเท้าที่แน่นอนของตัวแปรย้อนหลังได้เนื่องจากสองตัวแปรสามารถใช้พื้นที่ที่จัดสรรเดียวกันในหน่วยความจำร่วมกันได้
ลองแชร์หน่วยความจำระหว่างอาร์เรย์สองอาร์เรย์ดูว่าการจัดสรรอาร์เรย์ที่สองมีค่าใช้จ่ายครึ่งหนึ่งของหน่วยความจำของอาร์เรย์แรก เมื่อเรายกเลิกการตั้งค่าหน่วยความจำแรกหน่วยความจำที่สองเกือบทั้งหมดยังคงใช้อยู่
echo memory_get_usage()."\n"; // <-- 433200
$c=range(1,100);
echo memory_get_usage()."\n"; // <-- 444348 (+11148)
$d=array_slice($c, 1);
echo memory_get_usage()."\n"; // <-- 451040 (+6692)
unset($c);
echo memory_get_usage()."\n"; // <-- 444232 (-6808)
unset($d);
echo memory_get_usage()."\n"; // <-- 433200 (-11032)
ดังนั้นเราจึงไม่สามารถสรุปได้ว่าอาร์เรย์ที่สองใช้หน่วยความจำครึ่งหนึ่งเนื่องจากมันกลายเป็นเท็จเมื่อเรายกเลิกการตั้งค่าอันแรก
สำหรับมุมมองแบบเต็มเกี่ยวกับวิธีการจัดสรรหน่วยความจำใน PHP และสำหรับการใช้งานใดฉันขอแนะนำให้คุณอ่านบทความต่อไปนี้อาร์เรย์ PHP (และค่า) มีขนาดใหญ่แค่ไหน? (คำแนะนำ: ใหญ่!)
ข้อมูลพื้นฐานเกี่ยวกับการนับอ้างอิงในเอกสาร PHP นอกจากนี้ยังมีข้อมูลจำนวนมากเกี่ยวกับการใช้หน่วยความจำและการอ้างอิงนับถึงส่วนข้อมูลที่ใช้ร่วมกัน
โซลูชันต่างๆที่เปิดเผยในที่นี้เหมาะสำหรับการประมาณ แต่ไม่มีใครสามารถจัดการกับการจัดการหน่วยความจำ PHP ที่ละเอียดอ่อนได้
- การคำนวณพื้นที่ที่จัดสรรใหม่
หากคุณต้องการพื้นที่ที่จัดสรรใหม่หลังจากการมอบหมายงานคุณต้องใช้memory_get_usage()
ก่อนและหลังการจัดสรรเนื่องจากการใช้กับสำเนาจะทำให้คุณมีมุมมองที่ผิดพลาดเกี่ยวกับความเป็นจริง
// open output buffer
echo "Result: ";
// call every function once
range(1,1); memory_get_usage();
echo memory_get_usage()."\n";
$c=range(1,100);
echo memory_get_usage()."\n";
โปรดจำไว้ว่าหากคุณต้องการเก็บผลลัพธ์ของmemory_get_usage()
ตัวแปรแรกตัวแปรนั้นจะต้องมีอยู่แล้วก่อนหน้านี้และmemory_get_usage()
จะต้องถูกเรียกอีกครั้งก่อนหน้านี้และทุกฟังก์ชันอื่น ๆ ด้วย
หากคุณต้องการสะท้อนเหมือนในตัวอย่างข้างต้นบัฟเฟอร์เอาต์พุตของคุณจะต้องเปิดอยู่แล้วเพื่อหลีกเลี่ยงหน่วยความจำบัญชีที่จำเป็นในการเปิดบัฟเฟอร์เอาต์พุต
- การคำนวณพื้นที่ที่ต้องการ
หากคุณต้องการใช้ฟังก์ชันในการคำนวณพื้นที่ที่ต้องการเพื่อจัดเก็บสำเนาของตัวแปรโค้ดต่อไปนี้จะดูแลการเพิ่มประสิทธิภาพที่แตกต่างกัน:
<?php
function getMemorySize($value) {
// existing variable with integer value so that the next line
// does not add memory consumption when initiating $start variable
$start=1;
$start=memory_get_usage();
// json functions return less bytes consumptions than serialize
$tmp=json_decode(json_encode($value));
return memory_get_usage() - $start;
}
// open the output buffer, and calls the function one first time
echo ".\n";
getMemorySize(NULL);
// test inside a function in order to not care about memory used
// by the addition of the variable name to the $_GLOBAL array
function test() {
// call the function name once
range(1,1);
// we will compare the two values (see comment above about initialization of $start)
$start=1;
$start=memory_get_usage();
$c=range(1,100);
echo memory_get_usage()-$start."\n";
echo getMemorySize($c)."\n";
}
test();
// same result, this works fine.
// 11044
// 11044
โปรดทราบว่าขนาดของชื่อตัวแปรมีความสำคัญในหน่วยความจำที่จัดสรร
- ตรวจสอบรหัสของคุณ !!
ตัวแปรมีขนาดพื้นฐานที่กำหนดโดยโครงสร้าง C ภายในที่ใช้ในซอร์สโค้ด PHP ขนาดนี้ไม่ผันผวนในกรณีของตัวเลข สำหรับสตริงนั้นจะเพิ่มความยาวของสตริง
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
หากเราไม่คำนึงถึงการเริ่มต้นของชื่อตัวแปรเราก็รู้แล้วว่าตัวแปรใช้จำนวนเท่าใด (ในกรณีของตัวเลขและสตริง):
44 ไบต์ในกรณีของตัวเลข
+ 24 ไบต์ในกรณีของสตริง
+ ความยาวของสตริง (รวมถึงอักขระ NUL สุดท้าย)
(ตัวเลขเหล่านี้สามารถเปลี่ยนแปลงได้ขึ้นอยู่กับเวอร์ชัน PHP)
คุณต้องปัดเศษขึ้นเป็น 4 ไบต์เนื่องจากการจัดตำแหน่งหน่วยความจำ หากตัวแปรอยู่ในพื้นที่ส่วนกลาง (ไม่อยู่ในฟังก์ชัน) ตัวแปรจะจัดสรรอีก 64 ไบต์ด้วย
ดังนั้นหากคุณต้องการใช้รหัสใดรหัสหนึ่งในหน้านี้คุณต้องตรวจสอบว่าผลลัพธ์โดยใช้กรณีทดสอบอย่างง่าย (สตริงหรือตัวเลข) ตรงกับข้อมูลเหล่านั้นโดยคำนึงถึงทุกข้อบ่งชี้ในโพสต์นี้ (อาร์เรย์ $ _GLOBAL, การเรียกใช้ฟังก์ชันครั้งแรกบัฟเฟอร์เอาต์พุต ... )