ในงาน 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 ได้จากวิดีโอด้านล่าง