ในงาน Google I/O 2014 กูเกิลประกาศว่าจะเปลี่ยนรันไทม์ของ Android จาก Dalvik เป็น ART อย่างเป็นทางการ
ART ไม่ใช่ของใหม่เพราะเริ่มทดลองใช้มาตั้งแต่ Android 4.4 KitKat (ข่าวเก่า) เพียงแต่มันจะถูกใช้งานจริงใน Android L เป็นต้นไป
ในภาพรวมแล้ว ART ดีกว่า Dalvik ในทุกด้าน แต่ดีกว่าอย่างไรและแค่ไหน กูเกิลอธิบายไว้ในเซสชันชื่อ The ART runtime ซึ่งบทความนี้สรุปประเด็นมาให้รู้จัก ART กันก่อนใช้งานจริงๆ
ก่อนอธิบายข้อดีของ ART ว่าเหนือกว่า Dalvik อย่างไรบ้าง เราต้องปูพื้นเรื่อง Dalvik กันสักหน่อยครับ
โครงการ Android ดัดแปลงสถาปัตยกรรมการคอมไพล์-รันโปรแกรมมาจาก Java ซึ่งคนที่เคยเขียนโปรแกรม Java หรือโปรแกรมที่ใช้แนวคิด virtual machine/managed code อื่นๆ มาก่อน คงทราบกันดีว่าต้องแปลงโค้ด 2 ครั้งคือ
กรณีของ Android ดัดแปลงกระบวนการข้างต้นเล็กน้อย โดยเพิ่มขั้นตอนการแปลง bytecode มาเป็นภาษาของ Dalvik (ไฟล์ .dex/.odex) จากนั้นค่อยนำไปรันบนอุปกรณ์พกพา โดยมี Dalvik ทำหน้าที่เป็น virtual machine แทน JVM
สถาปัตยกรรมของ JVM เทียบกับ Dalvik ดูได้จากภาพข้างล่าง (ภาพโดย Marko Gargenta จากหนังสือ Learning Android)
อย่างไรก็ตาม Dalvik ถูกออกแบบมาตั้งแต่ Android ยุคแรกเริ่มที่ประสิทธิภาพของฮาร์ดแวร์ยังจำกัดมาก ผมไปเจอกับสไลด์ของงาน Google I/O ปี 2008 ก็เขียนอธิบายเรื่องนี้ไว้ชัดเจนตามภาพ
กูเกิลเลือกไม่แก้ไขปรับปรุง Dalvik แต่เลือกเขียนใหม่เป็นโครงการ ART (Android Runtime) แทน
หลักการออกแบบ ART กำหนดว่านักพัฒนาไม่ต้องยุ่งเกี่ยวใดๆ กับการเปลี่ยนจาก Dalvik เป็น ART (รันแทนกันได้สมบูรณ์ ประสิทธิภาพดีกว่า) และรองรับการขยายตัวของการรันแอพในอนาคต
ของใหม่ใน ART ที่เหนือกว่า Dalvik แบ่งได้ 4 อย่างดังนี้
เนื่องจาก ART ถูกเขียนขึ้นใหม่ในยุคที่ประสิทธิภาพของฮาร์ดแวร์ดีขึ้นมาก กูเกิลจึงปรับแต่งตัวคอมไพเลอร์ในหลายแง่มุม ทั้งประสิทธิภาพ หน่วยความจำ และการใช้แบตเตอรี่ให้ดีกว่าเดิม
กราฟแสดงผลประสิทธิภาพที่ดีขึ้นของ ART เหนือ Dalvik
โลกของการคอมไพล์โปรแกรมแบบ virtual machine ยังมีเทคนิคแยกย่อยในขั้นตอนการรันบน VM อีก 2 แบบใหญ่ๆ คือการคอมไพล์แบบ Just-in-Time (JIT) และ Ahead-of-Time (AOT)
ภาพประกอบจาก IBM
Dalvik เป็นคอมไพเลอร์แบบ JIT ส่วน ART เป็นคอมไพเลอร์แบบ AOT ทำให้ประสิทธิภาพของการรันแอพดีกว่าเดิม
อย่างไรก็ตาม ใช่ว่า ART จะไม่มีจุดอ่อนเลย เพราะการคอมไพล์แบบ AOT ต้องใช้พื้นที่สำหรับเก็บโค้ดที่คอมไพล์ไว้แล้วเพิ่มขึ้น (Anwar Ghuloum ทีมงานของกูเกิลประเมินว่าประมาณ 20%)
ข้อด้อยอีกอย่างของ ART คือการคอมไพล์ "ครั้งแรก" ของ ART ต้องใช้เวลามากกว่า Dalvik นั่นหมายถึงการบูตมือถือครั้งแรกหลังเปิดใช้งาน หรือหลังการอัพเดตระบบผ่าน OTA (ที่เราเห็นข้อความว่า optimizing ตามด้วยชื่อแอพ) กระบวนการเบื้องหลังในช่วงนั้นคือการคอมไพล์แอพใหม่อีกรอบ (ahead-of-time compilation) นั่นเอง
ตัวเลขของกูเกิลประเมินว่าถ้ามีแอพ 300 ตัว จะใช้เวลาบูตประมาณ 15 นาที เพียงแต่การบูตเครื่องลักษณะนี้นานๆ ทำครั้ง เลยไม่ใช่ปัญหาสำหรับผู้ใช้มากนัก
garbage collector (ต่อไปจะเรียก GC) คือตัวจัดการหน่วยความจำที่ไม่ใช้แล้วหรือ garbage เพื่อให้มีหน่วยความจำว่างไปทำอย่างอื่น ถือเป็นฟังก์ชันพื้นฐานของการรันโปรแกรม managed code
ตัวอย่างการทำงานของ GC ดูได้จากแผนภาพด้านล่าง ในกล่องสี่เหลี่ยมคือหน่วยความจำ ก้อนสีเขียวคือหน่วยความจำที่ใช้อยู่ ก้อนสีแดงคือหน่วยความจำที่ไม่ใช้แล้วแต่ยังอยู่ในหน่วยความจำ และก้อนสีฟ้าคือข้อมูลชิ้นใหม่ที่จะจองที่ในหน่วยความจำ
รูปซ้ายสุด ก้อนสีฟ้าก้อนบนต้องการจองที่ในหน่วยความจำและมีพื้นที่ว่างอยู่ ในรูปถัดมาจึงเขียนลงหน่วยความจำได้อย่างไม่มีปัญหา แต่พอก้อนสีฟ้าก้อนล่างต้องการจองที่บ้าง กลับไม่มีที่ว่างเหลืออยู่
หน้าที่ของ GC คือการคืนหน่วยความจำที่ไม่ใช้แล้ว (ก้อนสีแดง) เพื่อให้ก้อนสีฟ้าสามารถเข้าไปแทนที่ได้
ปัญหาของ Dalvik GC คือมันถูกออกแบบมาไม่ดีนัก การคืนเนื้อที่ในหน่วยความจำทำให้ส่วนอื่นๆ ของระบบต้องหยุดทำงานชั่วขณะ (pause) เป็นเวลาประมาณ 60ms ผลคืออัตราการแสดงผล (frame rate) จะตกลงไป 4-5 เฟรม การหยุดพักนานขนาดนี้สามารถเห็นได้ด้วยตาเปล่า นี่จึงเป็นเหตุผลว่าทำไม Android "กระตุก" นั่นเองครับ
กูเกิลกลับไปทำการบ้านมาใหม่กับ ART GC ที่ทำงานได้เร็วขึ้น หยุดพักเพื่อคืนหน่วยความจำสั้นลงกว่าเดิม และปรับปรุงการเรียงพื้นที่ในหน่วยความจำใหม่ให้กระจายตัวน้อยลง (fragmentation ถ้านึกไม่ออกให้เปิดโปรแกรม Disk Defragment มาลองดู) หน่วยความจำจะว่างติดกันเป็นผืนใหญ่มากขึ้น โอกาสที่ต้องรัน GC เพื่อคืนหน่วยความจำจึงมีน้อยลง
ตัวอย่างกราฟแสดงประสิทธิภาพการจองหน่วยความจำ (allocation) ที่ดีขึ้นของ ART เทียบกับ Dalvik (กราฟสีแดงคือ ART รุ่นแรก, กราฟสีเขียวคือ ART รุ่นปัจจุบันหลังปรับแต่งแล้ว)
ฟีเจอร์การเรียงพื้นที่หน่วยความจำของ ART
เมื่อสถาปัตยกรรมซีพียูบนอุปกรณ์พกพาเริ่มวิ่งเข้าสู่ 64 บิต ก็ไม่ใช่เรื่องแปลกอะไรที่ ART จะรองรับ 64 บิตมาตั้งแต่ต้น ตอนนี้ ART จึงรองรับสถาปัตยกรรมซีพียูทั้งหมด 6 แบบคือ ARM, x86, MIPS (ทุกตัวมีทั้งแบบ 32/64 บิต)
ข้อดีของการเป็น 64 บิตก็มีตั้งแต่การรองรับหน่วยความจำใหญ่ขึ้น, ประสิทธิภาพที่ดีขึ้นจากชุดคำสั่งแบบ 64 บิต นอกจากนี้ก็มีประโยชน์จากเรื่องจำนวนคอร์ที่เพิ่มขึ้น (ไม่เกี่ยวกับ 64 บิตแต่มักจะมาด้วยกัน) อีกด้วย
กราฟแสดงประสิทธิภาพของการประมวลผลแบบ 32 บิตเทียบกับ 64 บิตทั้งสามสถาปัตยกรรม
ดังนั้นการรันแอพด้วย ART จึงมีประสิทธิภาพดีขึ้นทั้งจากตัว ART เอง และจากการเป็น 64 บิตแทน 32 บิต (ประโยชน์สองต่อ)
กราฟด้านล่างแสดงประสิทธิภาพของ ART เทียบ Dalvik (รูปซ้าย) และ 64 บิตเทียบ 32 บิต (รูปขวา) โดยรันบน Intel Atom Baytrail
สำหรับประเด็นเรื่องความเข้ากันได้ของแอพกับซีพียู 64 บิต กูเกิลบอกว่าถ้าเป็นแอพปกติทั่วไป เขียนด้วย Java อย่างเดียว (ไม่มี native code) ย่อมไม่มีปัญหาใดๆ รันได้เลย แอพกลุ่มนี้คิดเป็น 85% ของแอพใน Google Play Store
ส่วนแอพที่มีส่วนของ native code (NDK) ต้องคอมไพล์ใหม่ให้รองรับ 64 บิต ซึ่งจะเริ่มใช้ใน Android L
บทความ Introducing ART บน Android Developers (แต่ยังไม่อัพเดตรับ L มากนัก ข้อมูลยังเขียนสำหรับ 4.4)
สำหรับคนที่มีเวลา สามารถฟังบรรยายรายละเอียดของ ART ได้จากวิดีโอด้านล่าง
Comments
สุดยอดบทความเชิงลึก แจ่มมากก
อ่านแล้วยังไม่ค่อยแน่ใจ พวกที่ใช้ CPU Intel จะได้ประโยชน์จากการเปลี่ยน Dalvik มาเป็น ART มั้ยครับ? หรือยังขึ้นอยู่กับคนที่เขียนแอพที่มีโค้ด native อยู่ดี?
จริงๆ น่าจะตรงข้ามครับ ตามทฤษฎีแล้ว ใครก็ตามที่ใช้ non-native น่าจะได้ประโยชน์ทั้งหมดครับ เพราะตัวจาวารันไทม์มันเปลี่ยน
ที่นี้ก็เหลือแต่ว่า ART รันไทม์ตัวไหนบนแพลตฟอร์มต่างๆ ฉลาดกว่า รีดประสิทธิภาพได้ดีกัน จะว่าไปก็เหมือนให้โอกาส Intel เพราะเหมือนรีเซ็ตมาเริ่มใหม่กันเลย
อันที่จริงในจาวา การแต่งพวก GC นี่มีลูกเล่นเยอะเลยนะ ทั้ง parallel, concurrent, generational
น่าจะใด้ในระดับหนึ่งครับ เนื่องจากการ compile เกิดที่อุปกรณ์ optimization option น่าจะปรับตาม instruction ที่อุปกรณ์มี
samsung ใหญ่แค่ใหน ?
https://youtu.be/6Afpey7Eldo
Android ขี้ลอก น่าจะโดนฟ้องให้ล่มจมไปเลยนะแบบนี้ สงสารจาวา
สงสารยังไงครับ ตอนแรกจาว่าก็ opensource ไม่ใช่เหรอครับ
java เขา open ในระดับ language เลยนะครับ
ส่วน jvm ใครอยากทำก็ทำได้
สรุปได้ว่า
คำถามคือการ "เอาขยะออก" (GC) รันแค่ตอนที่ต้องการจองพื้นที่ในหน่วยความจำแล้วมันไม่มีที่ว่างเท่านั้นใช่ไหมครับ?
^
^
that's just my two cents.
เข้าใจถูกแล้วแต่เข้าใจคำว่า bytecode ผิดครับ คือ bytecode เป็นสิ่งที่เกิดมาก่อนตั้งแต่ตอนที่ pack ไฟล์ APK มาแล้วครับ แต่เวลาทำงานเราต้องมา compile bytecode ให้เป็นส่วนที่ทำงานได้ (native machine code) อีกที
เลยต้องบอกว่าอย่างนี้แทนครับ
อ่านความเห็นนี้แล้วกระจ่างเลยครับ
อ่าาา ขอบคุณครับ
^
^
that's just my two cents.
ผมยังสงสัยตรงที่ เรียงข้อมูลใหม่หลัง GC ทำงาน มันก็น่าจะกินเวลาพอสมควรเลย ยิ่งกว่าหาก้อนสีแดงเพื่อเอาออกอีก(ถ้าเป็นแบบในรูปเป้ะๆ)
ผมคิดว่า การเรียงข้อมูลใหม่ เป็นการจัดเรียงในช่วงที่ไม่มีอะไรมารอใช้แล้วหรือเปล่าครับ ถึงจะกินเวลา แต่เป็นเรื่องเบื้องหลัง ไม่ใช่ตอนที่มีอะไรมารอใช้งานอยู่แล้วไปนั่งจัดเรียง
แอปพลิเคชั่นส่วนใหญ่มักจะสร้าง object ที่มีช่วงชีวิตสั้นๆ คือพอมันเกิดปุ๊ปก็ตายปั๊บในไม่ช้า
object ที่อยู่ยืดยาวจริงๆมีน้อยซึ่ง compaction phase มันจะเกิดขึ้นตรง heap ส่วนที่เก็บ object ที่อยู่ยืดยาวอย่างนี้แหละซึ่งมันน่าจะมีไม่มากตามหลัก weak generational hypothesis ที่ Generational GC ใช้
ผมไปดูคลิปฉบับเต็มมา (แถวนาทีที่ 24) เข้าใจว่า ART แยกพื้นที่ heap ไว้ 2 ส่วนคือ primitive type กับ large object นะครับ พวก large object คงไม่ต้องไปจัดเรียงมันหรอกเพราะเกิดแล้วเดี๋ยวก็ตาย แต่ที่น่าสนใจคือพวก primitive type ที่มักโดน ref จาก large object บ่อยๆ อีกทีครับ พอเรียงข้อมูลพวกนี้แล้วทำให้ประสิทธิภาพโดยรวมดีขึ้น
คือ heap ที่ ART จัดการมีสองส่วนอย่างที่คุณว่ามาแหละคือ heap ธรรมดา กับ heap ที่แยกมาเฉพาะไว้เก็บ primitive เช่น บิตแม็ป
แต่ compaction ที่ผมพูดถึงคือ compaction ที่เกิดในส่วนที่เป็น heap ธรรมดาที่แบ่งย่อยออกเป็น region ย่อยอีกตามอายุของอ็อปเจ็ค คือ young, old , permanent ซึ่ง compaction จะเกิดใน old ซะส่วนใหญ่และบางทีจะเกิดขึ้นในส่วนที่เป็น permanent แต่ compaction จะไม่เกิดในส่วน young
compaction ในส่วน old นี้แหละที่ถ้าแอปนั้นๆไม่ได้มีพฤติกรรมตามหลัก weak generational hypothesis จะทำให้การ compaction ไม่มีประสิทธิภาพ แต่ตามธรรมชาติของแแอปโดยทั่วไปแล้วแอปส่วนมากมักจะมีพฤติกรรมตามหลักนี้เลยทำให้ compaction มันไม่เสียเวลามากของอ็อปเจ็คที่เก่่าๆแต่ยังมีชีวิตอยู่มันมีจำนวนน้อย
ปล ที่ผมเอาหลัก weak generational hypothesis มาอ้างเพราะว่าตามสไลด์ในวิดีโอ เค้าบอกว่า GC ตัวใหม่เป็น moving GC ซึ่งอีกชื่อนึงก็คือ generational GC
ส่วน heap ที่ ART แยกออกมาต่างหากสำหรับเก็บ primitive อย่างบิตแม็ป ผมว่าเค้าใช้ compaction อีกสกีมนึงเพราะว่า การ compaction ในส่วนนี้ไม่ซับซ้อนเหมือนในส่วนแรกเพราะ primitive type ไม่มี reference ไปหาอ็อปเจ็คอื่นดังนั้นจึงไม่ต้องอัพเดต reference เหมือนอ็อปเจ็คในส่วน old ใน heap ธรรมดา หรืออาจจะไมต้อง allocate เนื้อที่ด้วยซ้ำถ้าสามารถ reuse บิตแม็ปเดิมได้โดยการแค่ overwrite ทับบิตแม็ปเดิมที่ไม่ใช้แล้ว
อ่านจบแล้ว ผมว่าอนาคตคงบุกตลาด Desktop แซง Linux แน่นอน (รองรับทุก cpu เลย)
android เป็น linux ไม่ใช่
Android + Chrome OS ของ Google ก็พัฒนามาจาก Linux นิครับ หรือพูดง่ายๆว่าคือ Linux รุ่นใหม่นั่นล่ะ
ถ้าหมายถึงเฉพาะตัว kernel แล้ว android ก็คือ linux
แต่ถ้าหมายถึงสิ่งที่ linux distribution อื่นๆต้องมี android คงไม่ใช่ linux เพราะมันขาดองค์ประกอบเหล่านั้นไปเยอะมากๆ เช่น GNU C Library,X Window System
android เป็น linux ที่ฮิตที่สุดครับ ส่วน desktop ผมรอมานานละ อยู่ที่เขาจะทำยังไงกับ chrome os ล่าสุด รันแอปได้แล้ว ก็เท่ากับเป็น android ไปครึ่งตัวแล้ว แถมยังมี art อีก ที่เหลือก็แค่ อัด cpu แรง ๆ ให้ทั้ง chrome book chrome box ก็น่าจะกินตลาด desktop ได้ไม่ยาก
ถ้ามันใช้งานกับ desktop ที่มีอยู่แล้วผมว่ากินยากครับ
ในเวลาอีกไม่นาน Chrome อาจจะมี ART ติดมาด้วยก็ได้นะครับ :p
ผมว่ามีแน่ๆ แต่แค่ตอนไหนเท่านั้นแหละครับ (เพราะใช้เป็นแผนสำรองได้ในกรณีที่ Chrome OS มีแอพน้อยกว่าที่คิดไว้)
ปล. อยากจะแก้ความเห็นที่ผมพิมพ์ผิดเป็น "ถ้ามันใช้งานกับ desktop ที่มีอยู่แล้วไม่ได้หรือได้ไม่เต็มที่ ผมว่ากินยากครับ" แต่แก้ไม่ได้แล้ว
Desktop ไม่น่าจะต้องใช้ ART นะครับ.........
เพราะ ART ทำมาเพื่อ limited resource system คงไม่แรงดั่งใจเท่าของที่มีอยู่แล้วที่ไม่เน้นประหยัดทรัพยากร เน้นความแรงอย่างเดียว :D
ผมมองว่าเค้าใส่มาเพื่อเข้าไปเสริมข่าวข้างล่างนี่ครับ เพื่อดึงให้ผู้ใช้เข้าใจว่า "Windows มันเกินความจำเป็นสำหรับคุณ ไม่จำเป็นต้องจ่ายเงินเพื่อใช้มัน" ครับ
มาเนียน Chrome Metro บน Windows 8 ใส่อินเทอร์เฟซแบบ Chrome OS มาด้วย
Performance Boosting Thing™
แจ่ม!! แต่ผมก็ยังไม่ค่อยรู้เรื่อง รู้แค่มันดีกว่าแค่นั้นเอง
ขอบคุณมากครับ ได้ทวนและรับความรู้ด้านสถาปัตกรรมเยอะเลย ถ้าไม่ได้บทความนี้ความเข้าใจartจะตื้นเกินไปจริงๆ ;)
อ่านแล้วเข้าใจขึ้นเยอะเลยครับ
ใช้ S5 ลองเลือกเปลี่ยนเป็น ART ดูแล้วครับ แต่ลองเปิด App ดูแล้ว Crash บ่อยอยู่ เลยกลับไปใช้ Dalvik เหมือนเดิม - -" สงสัยต้องรออีกหน่อย
ART บน KitKat ไม่ค่อยเสถียรครับ แล้วก็ช้าด้วย 55
ขอบคุณสำหรับความรู้ครับ
ทุกทีที่อัพรอมใหม่ เห็นมีการ optimize ด้วย เพิ่งรู้ว่าใช้ ART อยู่ 555
คือ Dalvik ก็ optimize ครับเวลาอัพรอมใหม่
รอดูว่า เจ้าไหนจะปล่อยมาก่อน หมายถึงเครื่องนะไม่ใช่ Update
งั้นก็ไม่ต้องเก็บ byte code สิครับ
เก็บแค่ execution binary พอ
แล้วจะ compile ใหม่ก็โหลดมาใหม่ (ต้องมี version เก่าให้โหลดด้วยนะ)
ที่ต้องเก็บ dex ไฟล์ไว้น่าจะเป็นเพราะ ART จำเป็นต้องใช้ข้อมูลบางอย่างของ class ต่างๆทีแอปพลิเคชันเรียกใช้ระหว่างรันไทม์
เช่น GC จำเป็นต้องใช้ข้อมูลจาก dex ไฟล์ในการรีเคลม unreferenced object เพราะว่า dex ไฟล์เก็บ meta data เกี่ยวกับขนาดของคลาส ฟิลด์ เมธอดต่างๆมากมาย
ฯลฯ
แบบนี้ ถ้าเอา ART มาใช้กับรุ่นเก่าๆ มันจะดีขึ้นเยอะมั๊ยครับ
เช่น เครื่องพวกสมัยตอน galaxy s1 ทั้งหลาย
ที่มีแรมแค่ 512mb และ cpu 1ghz
ตามทฤษฎีน่าจะดีขึ้นครับ ทางปฏิบัติต้องลอง
มิน่าตอนเปลี่ยนจาก Dalvik -> Art ถึงใช้เวลาตั้ง 10 นาที เราก็ตกใจนึกว่าเครื่องแฮง :P
@ Virusfowl
I'm not a dev. not yet a user.