จะกำหนดขนาดหน่วยความจำ (ขนาด) ของตัวแปรได้อย่างไร?


102

มีฟังก์ชันใน PHP (หรือส่วนขยาย PHP) เพื่อค้นหาว่าตัวแปรที่กำหนดใช้หน่วยความจำเท่าใด sizeofเพียงแค่บอกจำนวนองค์ประกอบ / คุณสมบัติ

memory_get_usageช่วยให้ฉันได้ขนาดหน่วยความจำที่สคริปต์ทั้งหมดใช้ มีวิธีดำเนินการสำหรับตัวแปรเดียวหรือไม่?

โปรดทราบว่าสิ่งนี้อยู่ในเครื่องพัฒนาดังนั้นการโหลดส่วนขยายหรือเครื่องมือแก้ไขข้อบกพร่องจึงทำได้


แก้ไขแล้ว - 5 ปีต่อมาและปัญหาบางอย่างยังไม่สามารถแก้ไขได้ :(
Piskvor ออกจากอาคาร

คำตอบ:


46

คุณอาจต้องมี Memory Profiler ฉันได้รวบรวมข้อมูลมาแล้ว แต่ฉันได้คัดลอกสิ่งสำคัญบางอย่างซึ่งอาจช่วยคุณได้

อย่างที่คุณทราบ Xdebug ได้ลดการรองรับการทำโปรไฟล์หน่วยความจำตั้งแต่เวอร์ชัน 2. * โปรดค้นหาสตริง "ฟังก์ชันที่ถูกลบออก" ที่นี่: http://www.xdebug.org/updates.php

ฟังก์ชันที่ถูกลบออก

ลบการสนับสนุนสำหรับการทำโปรไฟล์หน่วยความจำเนื่องจากทำงานไม่ถูกต้อง

ตัวเลือก Profiler อื่น ๆ

php-memory-profiler

https://github.com/arnaud-lb/php-memory-profiler นี่คือสิ่งที่ฉันได้ทำบนเซิร์ฟเวอร์ Ubuntu เพื่อเปิดใช้งาน:

sudo apt-get install libjudy-dev libjudydebian1
sudo pecl install memprof
echo "extension=memprof.so" > /etc/php5/mods-available/memprof.ini
sudo php5enmod memprof
service apache2 restart

จากนั้นในรหัสของฉัน:

<?php
memprof_enable();
// do your stuff
memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w"));

ในที่สุดเปิดcallgrind.outไฟล์ด้วยKCachegrind

ใช้ Google gperftools (แนะนำ!)

ก่อนอื่นให้ติดตั้งGoogle gperftoolsโดยดาวน์โหลดแพ็คเกจล่าสุดที่นี่: https://code.google.com/p/gperftools/

จากนั้นเช่นเคย:

sudo apt-get update
sudo apt-get install libunwind-dev -y
./configure
make
make install

ตอนนี้อยู่ในรหัสของคุณ:

memprof_enable();

// do your magic

memprof_dump_pprof(fopen("/tmp/profile.heap", "w"));

จากนั้นเปิดเทอร์มินัลของคุณและเปิด:

pprof --web /tmp/profile.heap

pprofจะสร้างหน้าต่างใหม่ในเซสชันเบราว์เซอร์ที่มีอยู่ของคุณโดยมีสิ่งที่แสดงด้านล่าง:

การสร้างโปรไฟล์หน่วยความจำ PHP ด้วย memprof และ gperftools

Xhprof + Xhgui (ดีที่สุดในความคิดของฉันสำหรับโปรไฟล์ทั้ง cpu และหน่วยความจำ)

ด้วยXhprofและXhguiคุณสามารถกำหนดโปรไฟล์การใช้งาน cpu ได้เช่นกันหรือเพียงแค่การใช้หน่วยความจำหากนั่นเป็นปัญหาของคุณในขณะนี้ เป็นโซลูชันที่สมบูรณ์แบบมากช่วยให้คุณสามารถควบคุมได้เต็มรูปแบบและบันทึกสามารถเขียนได้ทั้งบน mongo หรือในระบบไฟล์

สำหรับรายละเอียดเพิ่มเติมดูที่นี่

แบล็คไฟร์

Blackfire เป็นผู้สร้างโปรไฟล์ PHP โดย SensioLabs ซึ่งเป็นพวก Symfony2 https://blackfire.io/

หากคุณใช้puphpetเพื่อตั้งค่าเครื่องเสมือนของคุณคุณยินดีที่จะรู้ว่ามันรองรับ ;-)

Xdebug และการติดตามการใช้งานหน่วยความจำ

XDEBUG2เป็นส่วนขยายสำหรับ PHP Xdebug ช่วยให้คุณสามารถบันทึกการเรียกใช้ฟังก์ชันทั้งหมดรวมถึงพารามิเตอร์และส่งคืนค่าไปยังไฟล์ในรูปแบบที่แตกต่างกันรูปแบบเอาต์พุตมีสามรูปแบบ หนึ่งหมายถึงการติดตามที่มนุษย์อ่านได้อีกอันหนึ่งเหมาะสำหรับโปรแกรมคอมพิวเตอร์มากกว่าเนื่องจากแยกวิเคราะห์ได้ง่ายกว่าและอันสุดท้ายใช้ HTML ในการจัดรูปแบบการติดตาม คุณสามารถสลับระหว่างสองรูปแบบที่แตกต่างกันได้ด้วยการตั้งค่า ตัวอย่างจะอยู่ที่นี่

forp

forpง่ายไม่ล่วงล้ำเน้นการผลิตโปรไฟล์ PHP คุณสมบัติบางอย่าง ได้แก่ :

  • การวัดเวลาและจัดสรรหน่วยความจำสำหรับแต่ละฟังก์ชัน

  • การใช้งาน CPU

  • ไฟล์และหมายเลขบรรทัดของการเรียกใช้ฟังก์ชัน

  • ออกเป็นรูปแบบ Trace Event ของ Google

  • คำบรรยายของฟังก์ชัน

  • การจัดกลุ่มฟังก์ชัน

  • นามแฝงของฟังก์ชัน (มีประโยชน์สำหรับฟังก์ชันที่ไม่ระบุชื่อ)

DBG

DBGเป็นโปรแกรมแก้ไขจุดบกพร่อง php ที่มีคุณสมบัติครบถ้วนซึ่งเป็นเครื่องมือโต้ตอบที่ช่วยคุณในการดีบักสคริปต์ php ทำงานบนเว็บเซิร์ฟเวอร์ที่ใช้งานจริงและ / หรือการพัฒนาและช่วยให้คุณดีบักสคริปต์ของคุณในเครื่องหรือจากระยะไกลจาก IDE หรือคอนโซลและคุณสมบัติของมันคือ:

  • การดีบักระยะไกลและในเครื่อง

  • การเปิดใช้งานที่ชัดเจนและโดยปริยาย

  • Call stack รวมถึงการเรียกฟังก์ชันการเรียกเมธอดแบบไดนามิกและแบบคงที่พร้อมพารามิเตอร์

  • การนำทางผ่าน call stack ที่มีความสามารถในการประเมินตัวแปรในตำแหน่งที่ตรงกัน (ซ้อนกัน)

  • ก้าวเข้า / ก้าวออก / ก้าวข้าม / เรียกใช้ฟังก์ชันเคอร์เซอร์

  • จุดพักตามเงื่อนไข

  • จุดพักทั่วโลก

  • บันทึกข้อผิดพลาดและคำเตือน

  • หลายเซสชันพร้อมกันสำหรับการดีบักแบบขนาน

  • รองรับส่วนหน้า GUI และ CLI

  • รองรับเครือข่าย IPv6 และ IPv4

  • ข้อมูลทั้งหมดที่ถ่ายโอนโดยดีบักเกอร์สามารถเลือกป้องกันได้ด้วย SSL


2
นั่นคือว่าข้อมูลที่ผมกำลังมองหาขอขอบคุณ
Piskvor ออกจากอาคาร

93

ไม่มีวิธีโดยตรงในการใช้หน่วยความจำของตัวแปรเดียว แต่ตามที่ Gordon แนะนำคุณสามารถmemory_get_usageใช้ได้ ซึ่งจะส่งคืนจำนวนหน่วยความจำทั้งหมดที่จัดสรรดังนั้นคุณสามารถใช้วิธีแก้ปัญหาและวัดการใช้งานก่อนและหลังเพื่อรับการใช้งานตัวแปรเดียว นี่เป็นบิตที่แฮ็ก แต่ควรใช้งานได้

$start_memory = memory_get_usage();
$foo = "Some variable";
echo memory_get_usage() - $start_memory;

โปรดทราบว่านี่ไม่ใช่วิธีที่เชื่อถือได้คุณไม่สามารถแน่ใจได้ว่าไม่มีสิ่งอื่นใดสัมผัสกับหน่วยความจำในขณะที่กำหนดตัวแปรดังนั้นจึงควรใช้เป็นค่าประมาณเท่านั้น

คุณสามารถเปลี่ยนเป็นฟังก์ชันได้โดยการสร้างสำเนาของตัวแปรภายในฟังก์ชันและวัดหน่วยความจำที่ใช้ ยังไม่ได้ทดสอบ แต่โดยหลักการแล้วฉันไม่เห็นอะไรผิดปกติ:

function sizeofvar($var) {
    $start_memory = memory_get_usage();
    $tmp = unserialize(serialize($var));
    return memory_get_usage() - $start_memory;
}

14
$tmp = $varจะสร้างสำเนาตื้น สิ่งนี้จะไม่จัดสรรหน่วยความจำเพิ่มเติมจนกว่าจะมีการแก้ไข $ tmp
Gordon

@ กอร์ดอนคุณพูดถูกฉันมองข้ามจุดนั้นไป เนื่องจากฉันไม่สามารถหาวิธีแก้ไขตัวแปรได้อย่างเหมาะสมโดยไม่ต้องเปลี่ยนประเภทหรือขนาดฉันจะปล่อยให้เป็นเช่นนั้น บางทีอาจมีใครคิดออกมาก็ได้ :)
Tatu Ulmanen

7
เป็นไงบ้าง$tmp = unserialize(serialize($var)); สิ่งนี้จะรวมแนวทางของ Aistina ไว้ข้างต้น
Gordon

3
เนื่องจาก$varเป็นสำเนาตื้น ๆ หรือการอ้างอิงของสิ่งที่ส่งไปยังฟังก์ชันอยู่แล้วคุณจึงไม่จำเป็นต้องใช้$tmpแต่สามารถกำหนดให้ใหม่$varได้ นี้ช่วยประหยัดการอ้างอิงภายในจากการ$tmp $var
Gordon

ไม่ได้มีบางวิธีที่สง่างามมากขึ้นในการ dereference $tmpจาก$var?
Tomáš Zato - คืนสถานะ Monica

24

ไม่มีไม่มี แต่คุณสามารถserialize($var)ตรวจสอบstrlenผลลัพธ์โดยประมาณได้


นี่เป็นแนวทางที่ดีกว่ามากเนื่องจากหลีกเลี่ยงสิ่ง GC ทั้งหมด
Gleno

12
มันเป็นการประมาณที่แย่มาก ทุกรายการในอาร์เรย์ใน PHP มีขนาด ~ 80 ไบต์ แต่strlen(serialize(array(1,2,3)))เป็น 30
gsnedders

2
@Aistina, -1. คุณกำลังวัดสิ่งที่ผิด ตัวแปรและตัวแปรอนุกรมเป็นสองสิ่งที่แตกต่างกันโดยสิ้นเชิงและจะให้ผลลัพธ์ที่แตกต่างกันอย่างสิ้นเชิง
Pacerier

1
ไม่เพียงแค่นั้น แต่จะล้มเหลวอย่างสิ้นเชิงกับโครงสร้างข้อมูลที่ไม่ต่ออนุกรมได้เช่นการอ้างอิงแบบวงกลม
duskwuff

20

ในคำตอบของ Tatu Ulmanens คำตอบ:

ควรสังเกตว่า$start_memoryตัวมันเองจะใช้หน่วยความจำ ( PHP_INT_SIZE * 8)

ดังนั้นฟังก์ชันทั้งหมดควรกลายเป็น:

function sizeofvar($var) {
    $start_memory = memory_get_usage();
    $var = unserialize(serialize($var));
    return memory_get_usage() - $start_memory - PHP_INT_SIZE * 8;
}

ขออภัยที่ต้องเพิ่มสิ่งนี้เป็นคำตอบเพิ่มเติม แต่ฉันยังไม่สามารถแสดงความคิดเห็นเกี่ยวกับคำตอบได้

อัปเดต: * 8 ไม่เป็นที่แน่ชัด เห็นได้ชัดว่าขึ้นอยู่กับเวอร์ชัน php และอาจเป็น 64/32 บิต


4
คุณอธิบายได้* 8ไหมว่าทำไม? ขอบคุณ!
sierrasdetandil

@sierrasdetandil ดูเหมือนว่า $ start_memory ไม่ได้ใช้เฉพาะPHP_INT_SIZEไบต์ แต่PHP_INT_SIZE*8. คุณสามารถลองโดยเรียกใช้ฟังก์ชันนี้ซึ่งควรส่งคืนค่า 0:function sizeofvar() { $start_memory = memory_get_usage(); return memory_get_usage() - $start_memory - PHP_INT_SIZE*8; }
พารา

8ดูเหมือนจะไม่คงที่ ต่อไปนี้ฟังก์ชั่นความคิดเห็นของคุณในระบบ dev ของฉัน (PHP 5.6.19) -16ก็จะส่งกลับ นอกจากนี้ที่น่าสนใจคือจากการphp -aเรียกใช้สองบรรทัดของฟังก์ชันให้ค่าที่แตกต่างกัน
Paul DelRe

@PaulDelRe ใช่อาจจะขึ้นอยู่กับรุ่น / 64 บิตของสิ่งนี้
พารา

ตอนนี้ข้อผิดพลาดร้ายแรงเกิดขึ้นที่การโทร unserialize () นั่นช่วยไม่ได้! หากตัวแปรมีขนาดใหญ่จนหน่วยความจำหมดการเรียกใช้ฟังก์ชันในตัวแปรนั้นจะใช้หน่วยความจำมากขึ้น :(
john ktejik

4

ดู:

  • memory_get_usage() - ส่งคืนจำนวนหน่วยความจำที่จัดสรรให้กับ PHP
  • memory_get_peak_usage() - ส่งคืนค่าสูงสุดของหน่วยความจำที่จัดสรรโดย PHP

โปรดทราบว่าสิ่งนี้จะไม่ทำให้คุณใช้หน่วยความจำของตัวแปรเฉพาะ แต่คุณสามารถเรียกใช้ฟังก์ชันเหล่านี้ก่อนและหลังกำหนดตัวแปรแล้วเปรียบเทียบค่าได้ นั่นจะทำให้คุณได้ทราบถึงหน่วยความจำที่ใช้

นอกจากนี้คุณยังสามารถดูMemtrack ส่วนขยาย PECLได้แม้ว่าเอกสารประกอบจะขาดไปเล็กน้อย แต่ถ้าไม่บอกว่าแทบไม่มีอยู่จริง


ใช่. สามารถใช้ตอบคำถามทางอ้อมได้
Notinlist

3

คุณสามารถเลือกคำนวณความแตกต่างของหน่วยความจำสำหรับค่าการเรียกกลับ เป็นโซลูชันที่หรูหรากว่าใน PHP 5.3+

function calculateFootprint($callback) {
    $startMemory = memory_get_usage();
    $result = call_user_func($callback);
    return memory_get_usage() - $startMemory;
}

$memoryFootprint = calculateFootprint(
    function() {
        return range(1, 1000000);
    }
);

echo ($memoryFootprint / (1024 * 1024)) . ' MB' . PHP_EOL;

3

คุณไม่สามารถคำนวณรอยเท้าที่แน่นอนของตัวแปรย้อนหลังได้เนื่องจากสองตัวแปรสามารถใช้พื้นที่ที่จัดสรรเดียวกันในหน่วยความจำร่วมกันได้

ลองแชร์หน่วยความจำระหว่างอาร์เรย์สองอาร์เรย์ดูว่าการจัดสรรอาร์เรย์ที่สองมีค่าใช้จ่ายครึ่งหนึ่งของหน่วยความจำของอาร์เรย์แรก เมื่อเรายกเลิกการตั้งค่าหน่วยความจำแรกหน่วยความจำที่สองเกือบทั้งหมดยังคงใช้อยู่

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 ที่ละเอียดอ่อนได้

  1. การคำนวณพื้นที่ที่จัดสรรใหม่

หากคุณต้องการพื้นที่ที่จัดสรรใหม่หลังจากการมอบหมายงานคุณต้องใช้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()จะต้องถูกเรียกอีกครั้งก่อนหน้านี้และทุกฟังก์ชันอื่น ๆ ด้วย

หากคุณต้องการสะท้อนเหมือนในตัวอย่างข้างต้นบัฟเฟอร์เอาต์พุตของคุณจะต้องเปิดอยู่แล้วเพื่อหลีกเลี่ยงหน่วยความจำบัญชีที่จำเป็นในการเปิดบัฟเฟอร์เอาต์พุต

  1. การคำนวณพื้นที่ที่ต้องการ

หากคุณต้องการใช้ฟังก์ชันในการคำนวณพื้นที่ที่ต้องการเพื่อจัดเก็บสำเนาของตัวแปรโค้ดต่อไปนี้จะดูแลการเพิ่มประสิทธิภาพที่แตกต่างกัน:

<?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

โปรดทราบว่าขนาดของชื่อตัวแปรมีความสำคัญในหน่วยความจำที่จัดสรร

  1. ตรวจสอบรหัสของคุณ !!

ตัวแปรมีขนาดพื้นฐานที่กำหนดโดยโครงสร้าง 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, การเรียกใช้ฟังก์ชันครั้งแรกบัฟเฟอร์เอาต์พุต ... )


1
... และที่ว่าแม้กระทั่งก่อนที่เราจะเข้าไปใน internals ของzvalue, is_refและคัดลอกบนเขียน ขอบคุณ.
Piskvor ออกจากอาคาร

1
ขอบคุณคุณฉันพลาดหน้านั้นในคู่มือ PHP ฉันเพิ่มลิงก์เพื่อตอบคำตอบให้สมบูรณ์ (แต่ฉันเดาว่าคุณได้อ่านแล้ว)
อดัม

2

ฉันมีปัญหาที่คล้ายกันและวิธีแก้ปัญหาที่ฉันใช้คือเขียนตัวแปรลงในไฟล์จากนั้นเรียกใช้ filesize () บนมัน ประมาณนี้ (รหัสที่ยังไม่ทดลอง):

function getVariableSize ( $foo ) 
{
    $tmpfile = "temp-" . microtime(true) . ".txt";
    file_put_contents($tmpfile, $foo);
    $size = filesize($tmpfile);
    unlink($tmpfile);
    return $size;
}

โซลูชันนี้ไม่เร็วมากเพราะเกี่ยวข้องกับดิสก์ IO แต่ควรให้บางสิ่งที่แน่นอนมากกว่าเทคนิค memory_get_usage มันขึ้นอยู่กับความแม่นยำที่คุณต้องการ


ควรสังเกตว่าโซลูชันนี้ใช้ได้กับสตริงและอาร์เรย์แบบมิติเดียวของสตริงเท่านั้นและการใช้strlenจะง่ายกว่า
อดัม


1
function mesure($var){
    $start = memory_get_usage();
    if(is_string($var)){
        $newValue = $var . '';
    }elseif(is_numeric($var)){
        $newValue = $var + 0;
    }elseif(is_object($var)){
        $newValue = clone $var;
    }elseif(is_array($var)){
        $newValue = array_flip($var, []);
    }
    return memory_get_usage() - $start;
}

1

สคริปต์ต่อไปนี้แสดงการใช้หน่วยความจำทั้งหมดของตัวแปรเดียว

function getVariableUsage($var) {
  $total_memory = memory_get_usage();
  $tmp = unserialize(serialize($var));
  return memory_get_usage() - $total_memory; 
}

$var = "Hey, what's you doing?";
echo getVariableUsage($var);

ลองดู

http://www.phpzag.com/how-much-memory-do-php-variables-use/

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.