ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม : Static & Heap


      จากบทความที่แล้ว ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม ตอนที่ 1 เราพึ่งจะได้รู้จัก memory แต่ละชนิดของ controller กันไปเอง ถ้าถามหาความสำคัญก็ยังตอบไม่ได้ จริงมั้ย? เพราะที่ผ่านมาก็แค่บอกว่า memory ส่วนนี้ ๆ ทำอะไร แต่เอาเข้าจริงก็ยังไม่เห็นความสำคัญอยู่ดี บทความนี้เราก็เลยจะต่อกัน


      จริง ๆ เรายังมีส่วนที่ติดค้างกันอยู่จริงมั้ย เพราะในบทความที่แล้วเรายังไม่รู้เลยว่า Flash มันคือส่วนไหน SRAM มันคือส่วนไหน หรือแม้กระทั่ง EEPROM มันเขียนยังไง

      เจ้าของบล็อกขอเริ่มในส่วนของ Flash ก่อนเลยละกัน



      ตรงที่เป็นกรอบสีแดงนั่นแหละที่บอกว่ามีข้อมูลเก็บลง flash เท่าไหร่ จากตัวอย่างเจ้าของบล็อก flash โปรแกรมเปล่า ๆ ที่มีแต่  setup() กับ loop() แค่นั้น ใช้พื้นที่ flash ไป 444 byte หรือแค่ 1% จากพื้นที่ทั้งหมด 32k byte เห็นว่าเยอะอย่างงั้นแต่พอเขียนกับงานจริง ๆ พื้นที่ flash หมดไปง่ายมาก


Static data


      เราลองมาเล่นอะไรดูหน่อยแล้วกัน ยังจำข้อมูลในส่วนของ static data กันได้อยู่หรือเปล่าเอ่ย.. ข้อมูลจำพวก static data ก็คือพวกตัวแปร global variable กับ static variable นั่นเอง

      ถ้าหากว่าเจ้าของบล็อกเขียนโปรแกรมประมาณนี้แล้ว flash ลงไปในบอร์ด คิดว่าขนาด size ของโปรแกรมจะเป็นยังไง เพิ่มขึ้น ลดลง หรือ เท่าเดิม? ..



      นี่คือผลของโปรแกรม จากที่ถามไปถ้าเราเขียนเพิ่มตัวแปรลงไปในโค้ดมันคงไม่ลดลงหรอกเนอะ เพราะฉะนั้นตัดตรงนั้นทิ้งไปได้เลย เหลือแค่ เท่าเดิม กับ เพิ่มขึ้น แต่ผลที่ได้คือขนาด flash เท่าเดิมกับก่อนหน้าที่ไม่ใส่ตัวแปรเลย..

      ที่เป็นแบบนี้เพราะว่า เราประกาศตัวแปรขึ้นมา.. แล้วไงละ เราแค่ประกาศขึ้นมาแต่ไม่ได้ใช้อะไรเลย compiler ก็เลยมองว่าตัวแปรตัวนี้ก็เป็นแค่ค่าคงที่

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




      คราวนี้เราลองมาเล่นกันอีก ถ้าหากว่าเจ้าของบล็อกใส่ตัวแปรอาเรย์ขนาดเท่านี้ดู


      ผลลัพธ์ที่ได้ก็จะตามรูปข้างล่างนี้



      จะเห็นว่า memory ถูกใช้ไปแล้วตั้ง 29% อันนี้แค่ลองให้ดูเฉย ๆ นะ เพราะบางคนอาจจะบอกว่าคงไม่ได้เขียน array อะไรขนาดนี้หรอก แต่ก็อย่าลืมว่าบางงานเราก็ต้องใช้ library เหมือนกันซึ่งบางครั้งเราก็ไม่ได้เข้าไปดูหรอกว่า library เขาเขียนยังไง บางที memory ส่วนใหญ่ที่เสียไป อาจจะไม่ได้มาจากที่ผู้อ่านเอง แต่อาจจะมาจาก library ที่ผู้อ่านใช่อยู่ก็ได้




      จากที่ลองเขียนไปทั้งหมดอยู่ในส่วนของ static data ทั้งหมด ซึ่งจะสังเกตุว่า static data เป็นข้อมูลที่มีพื้นที่ตายตัว มีมากมีน้อยก็ขึ้นอยู่ที่เราสร้าง และเราสามารถรับรู้ได้ด้วยว่าพื้นที่ใช้ไปเท่าไหร่ และเหลือเท่าไหร่

      ทำไม static data ต้องเป็นตัวแปรประเภท global variable และ static variable?

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


Heap


      ถ้าแปลตามตัว heap ก็แปลว่า กอง เป็นข้อมูลที่ทับ ๆ กันสูงขึ้นไปเรื่อย ๆ อะไรประมาณนี้ จากที่เคยบอกไปในบทความที่แล้วว่าเราควรจะระวังการใช้งาน memory ในส่วนของ heap กัน เพราะว่าเราต้องเขียนจองพื้นที่เองและต้องคืนพื้นที่เอง

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


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




      ดูจาก Serial monitor แสดงให้เห็นว่า memory ถูกจองไปเรื่อย ๆ จนเหลือแค่ 136 byte เท่านั้น ซึ่งตรงนี้ไม่แน่ใจว่าทำไมถึงเหลือ 136 byte เพราะเจ้าของบล็อกก็กำลังจะดูอยู่เหมือนกันว่า ถ้ามันเหลือน้อยกว่านี้จะเป็นไง หรือว่าในส่วนของ heap มันใช้ได้แค่นี้



      แต่นี่ก็เป็นผลลัพธ์ของการลืมคืน memory นั่นแหละ และคราวนี้ลองใช้แล้วคืน memory ด้วย โดยเจ้าของบล็อกจะใส่ free เข้าไปแบบในโค้ด

      แล้วดูผลลัพธ์ข้างล่าง


      
      จะเห็นว่า memory ถูกคืนกลับไปทุกครั้ง และเจ้าของบล็อกก็ขอย้ำอีกว่าการจะใช้ heap ต้องใช้อย่างมีสติรู้ว่าตัวเองกำลังทำอะไร ซึ่งตัวอย่างของเจ้าของบล็อกแสดงแค่การใช้ malloc เท่านั้น แต่หลัก ๆ มันคือเรื่องของ pointer เพราะถ้าหากไม่ใช้ malloc ก็สามารถใช้ int *data = new int; แบบนี้ได้เหมือนกัน และบางทีอาจจะไปเจอกับ data structure ในแบบของ link list ก็ได้ แต่ยังไงสุดท้ายมันก็คือ pointer

      ในบทความนี้เจ้าของบล็อกขอพักไว้แค่นี้ก่อน บทความต่อไปจะต่อพวก stack แล้วก็วิธี solve ปัญหารวมทั้ง optimize ให้ดีขึ้นด้วย

อ่านต่อในบทความ ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม ตอนที่ 3 


reference : Memory of an arduino

ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

ว่าด้วยเรื่องหน่วยความจำ สิ่งที่หลายคนมองข้าม : รู้จักกับ Memory

คณิตศาสตร์กับโปรแกรมมิ่งมันเป็นยังไงนะ ตอนที่ 1 เกริ่นพีทาโกรัส

Pointer กับตัวแปร Array นะจ๊ะ.. [Back to basic แต่ไม่ basic]