Quantcast
Channel: cc :: somkiat
Viewing all articles
Browse latest Browse all 1997

มาลดเวลาการ build สำหรับ Android project กันเถอะ

$
0
0

Screen Shot 2559-01-09 at 5.37.01 PM

Screen Shot 2559-01-09 at 5.37.01 PM ปัญหาหนึ่งของการพัฒนา Android application ก็คือ เวลาในการ build project ด้วย gradle มันนานมาก ๆ ยิ่ง project มีขนาดใหญ่ขึ้น ยิ่ง project มี module จำนวนมาก ยิ่ง project ใช้ library จำนวนมาก คำถามคือ จะแก้ไข หรือ ปรับปรุงอย่างไรดี ? เพื่อทำให้เวลาการ build มันต่ำลงให้ได้มากที่สุด เรามาค้นหาวิธีการไปพร้อม ๆ กันเลย

นักพัฒนาอย่างเรา ต้องเริ่มต้นด้วยการค้นหาที่ Google สิ !!

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

แต่ก่อนอื่นแนะนำให้ดูสถานะปัจจุบันของการ build ของ project ก่อนนะ

โดย Environment ที่ผมใช้ในการทดสอบคือ
  • Macbook Pro, RAM 8GB แบบเหลือนิดเดียว, CPU 2.4 GHz
  • Android Studio 2.0 Preview 4
  • Grade 2.8
ขั้นแรกใช้ profile มาช่วยดูเวลาการ build ในปัจจุบัน $./gradlew clean assembleDevDebug --profile และ $./gradlew assembleDevDebug --profile ข้อสังเกต
  • การใช้ clean task นั้นเป็นการ build from scratch เป็นการ build ใหม่ทั้งหมด
  • แต่ถ้าไม่ใช้ clean จะเรียกว่า incremental build สำหรับการ run ซ้ำ จะทำให้ build เร็วขึ้น ซึ่งใช้งานบ่อยกว่าสำหรับการพัฒนา
ได้ผลการทำงานดังนี้ เป็นข้อมูลที่ทุกคนควรจดบันทึก และ จดจำไว้เลย มันเป็นข้อมูลตั้งต้น ก่อนทำการปรับปรุงส่วนอื่น ๆ ปล. ให้ทำการ run อย่างน้อย 3 ครั้งนะ เพื่อทำให้มั่นใจว่าผลที่ได้มันถูกต้อง และ ใกล้เคียงกันมากที่สุด
ได้เวลาการทำงานที่แย่ที่สุด คือประมาณ 2 นาที 30 นาที ส่วนของ incremental build ใช้เวลาประมาณ 1 นาที 30 วินาที
ผลจาก Build from scratchScreen Shot 2559-01-09 at 11.59.29 AM ผลจาก Incremental buildScreen Shot 2559-01-09 at 1.07.05 PM

จากรายงานที่ได้จาก profile พบว่าการ build ประกอบไปด้วย 3 ส่วน คือ

1. Configuration โดยปกติมันจะเร็วมาก ๆ จะช้าก็คือ build.gradle มีความซับซ้อนมาก ๆ 2. Dependency Resolution จะทำการตรวจสอบ และ download dependency ต่าง ๆ ที่ใช้งาน ปกติจะดึงข้อมูลจาก cached เครื่องก่อน ถ้าไม่มีจะทำการ download ผ่าน internet ซึ่งเวลาการทำงานโดยรวมจะน้อยมาก ๆ 3. Task Execution !! เป็นส่วนที่ใช้เวลาการทำงานสูงมาก ๆ เพราะว่าใน gradle จะมีงานย่อย ๆ เยอะมาก เช่น
  • Compiling
  • Dexing
  • Testing
จากเวลาการทำงาน หรือ build ของระบบงานตัวอย่าง พบว่า Task Execution มันสูงที่สุด นั่นคือ ปัญหา และ เป้าหมายที่ต้องการแก้ไขต่อไป !!!

มาเริ่มปรับปรุงเวลา build project กันเลย

อย่างแรกที่ให้ลองทำการปรับ ใน gradle ทำการแนะนำมาดังนี้
This build could be faster, please consider using the Gradle Daemon: https://docs.gradle.org/2.8/userguide/gradle_daemon.html
นั่นคือเรื่องของ Gradle Daemon พูดง่าย ๆ คือ มี background process หลาย ๆ ตัวมาช่วยทำงานนั่นเอง เชิงทฤษฎีน่าจะ build ได้เร็วขึ้นสิ แน่นอนว่าใช้ RAM เพิ่มขึ้นเช่นเดียวกัน !! มาดูกันเลย ทำการกำหนดค่าในไฟล์ gradle.properties org.gradle.daemon=true หรือใส่ใน command line ได้เลย $./gradlew clean assembleDevDebug —daemon --profile จากผลการทดสอบพบว่า
  • Build from scratch ใช้เวลาประมาณ 1 นาที 30 - 50 วินาที หรือลดลงไป 10-15%
  • Incremental build ใช้เวลาประมาณ 1 นาที 15 วินาที หรือลดลงไป 5% บางครั้งไม่ได้ช่วยอะไรเลย !!
แสดงผลการ Build from scratch ดังรูป Screen Shot 2559-01-09 at 12.22.52 PM และเรื่องอื่น ๆ ที่มักจะเขียน และ แนะนำมา เช่น
  • Parallel building สำหรับ multiple project
  • Configuration on demand สำหรับ multiple project
  • Offline mode
  • JVM arguments สำหรับ daemon
จากที่ทดสอบแล้วพบว่า เวลาการ build จะลดลงนิดเดียว ไม่คุ้มต่อการลงทุนเท่าไรนัก แต่ไม่ได้หมายความว่า คนอื่น ๆ เอาไปใช้จะได้ผลเหมือนผมนะ เชื่อเถอะว่า แตกต่างกันอย่างแน่นอน ดังนั้น จำเป็นต้องทดลองกันก่อนนะ

ข้อมูลเพิ่มเติม

ใน project มีการแยก code ออกเป็น module ย่อย ๆ แต่มันกลับทำให้การ build ช้าลงไป ซึ่งบางคนแก้ไขปัญหาด้วยการ build แบบ parallel แต่สำหรับผมจะแยกออกไปเป็น library แทนนะครับ ซึ่งลดเวลาการ build ไปได้เยอะกว่ามาก จากที่ทดสอบ และ ใช้งานจริงพบว่าลดเวลาการ build ไป 50% แต่ก็ยังทำงานช้าอยู่ดี เนื่องจากยังทำงานในระดับนาที !!

มาดู Task ใน gradle ที่ทำงานช้า ประกอบไปด้วย

  • transformClassesWithDex
  • compile
  • transformClassesWithMultidexlist
  • package
  • transformClassesWithJarMerging
จะลดเวลาการ build ของ task เหล่านี้อย่างไรกันดี ?

มาลองวิธีการต่อไปดีกว่า นั่นก็คือ เปลี่ยนค่า minSdkVersion เป็น 21

เป็นวิธีการเพิ่มประสิทธิภาพการ build ของ project ใหญ่ ๆ แน่นอนว่า ต้องการใช้งาน multidex แน่นอน และจะ build ช้ามาก ๆ ถ้าค่า minSdkVersion ต่ากว่า 21 เนื่องจากใน SDK 21 หรือ Lollipop ได้เปลี่ยนแปลง และ ปรับปรุงขั้นตอนการ build ใหม่ เพราะว่ามี runtime ตัวใหม่คือ ART (Android Runtime) มาแทน Dalvik ซึ่งมีผลให้การ dexing ดีขึ้น อ่านเพิ่มเติมเกี่ยวกับ multidex ได้ที่นี่ Android MultiDex  ถ้าไม่เชื่อก็ลองเปลี่ยนกันหน่อยสิ ดังนั้นลองเปลี่ยนค่า minSdkVersion เป็น 21 ก่อน เพื่อความสะดวกจะกำหนดใน productFlavor dev จากนั้นลอง build ดูใหม่ ได้ผลดังนี้
  • Build from scratch ใช้เวลาไม่ได้แตกต่างจากเดิมสักเท่าไร
  • Incremental build เป็นส่วนที่เวลาลดลงไปอย่างมาก เหลือไม่ถึง 30 วินาที หรือลดลงไป 50-70% กันเลย แต่ถ้ามี memory เหลือเยอะหน่อย จะใช้เวลา build 20 วินาที !!
โดยทดลองทั้งแบบ daemon และ non-daemon ซึ่งผลต่างกันพอสมควร ซึ่งแนะนำให้ run แบบ daemon ไปเลย ปล. ต้องเตรียม RAM ให้เยอะ ๆ หน่อยนะครับ
มาดูผลการทำงาน ซึ่งได้ผลเป็นที่น่าพอใจเลยนะ Screen Shot 2559-01-09 at 4.02.50 PM สิ่งที่เห็นได้ชัดเจนก็คือ compileDevDebugJavaWithJavac นั่นคือการ compile code JAVA ด้วย Java Compiler นั่นเอง ขั้นตอนนี้ใช้เวลาที่สูงสุด ซึ่งน่าจะลดลงได้อีกนะ !!

ยังมีวิธีการการอื่น ๆ อีกนะ เช่น

  • ใช้ Jack และ Jill ซึ่ง Jack ใช้สำหรับการ compile code Java ไปยัง Dex format แต่ว่ามันไม่สนับสนุน Data Binding จึงไม่ได้ทำการทดสอบ
  • เพิ่ม Hardware เช่น RAM จะดีต่อการ build แน่นอน
  • แยก code ที่ไม่ค่อยเปลี่ยนแปลง ออกไปเป็น library หรือ dependency แทน จะได้ไม่ต้องเสียเวลามา build ใหม่ ดังนั้น Small is better นะครับ
  • ใช้ Buck สำหรับการ build แทนไปเลย

สุดท้าย ขอเน้นย้ำว่า

ก่อนจะทำการปรับปรุงอะไรก็ตาม ควรที่จะทำการเก็บข้อมูลเริ่มต้น และ ทำ profiling ก่อนเสมอ เพื่อทำให้เรารู้สถานะเริ่มต้นของระบบ กับทำให้เรารู้ถึงปัญหา เพื่อจะทำการแก้ไขได้ตรงจุด แต่ละปัญหา ย่อมใช้วิธีการแก้ไขที่ต่างกัน (No Silver Bullet)
ดังนั้น จงหาปัญหาของตัวเองให้เจอก่อนเสมอ มิเช่นนั้น คุณจะไม่สามารถแก้ไขปัญหาได้ หรือถ้าได้ก็ไม่ตรงจุด !!
จากปัญหาที่ผมพบเจอ สามารถลดเวลาการ build แบบ incremental จาก 1 นาที 30 วินาที มาจนเหลือเวลาไม่ถึง 30 วินาที ก็น่าจะทำให้เรามีกำลังใจในการ build มากขึ้น รวมทั้งเป็นสิ่งบ่งบอกว่า เราแก้ไขปัญหามาถูกทางแล้วนะ แต่ยังต้องลดเวลาลงไปอีก เป้าหมายต่อไปคือ ต่ำกว่า 10 วินาที !!
Fast Feedback มันคือหัวใจสำคัญของการพัฒนา software นะ ขอให้สนุกกับการพัฒนา Android application ครับ
Reference Websites http://blog.octo.com/en/reduce-android-build-duration/ https://medium.com/@erikhellman/boosting-the-performance-for-gradle-in-your-android-projects-6d5f9e4580b6#.me0d9b7bm http://kevinpelgrims.com/blog/2015/06/11/speeding-up-your-gradle-builds/ http://stackoverflow.com/questions/23367769/how-to-speed-up-android-studio-compilation-process http://android-developers.blogspot.nl/2015/11/android-studio-20-preview.html http://jimulabs.com/2014/10/speeding-gradle-builds/ https://www.timroes.de/2013/09/12/speed-up-gradle/ https://docs.gradle.org/2.8/userguide/gradle_daemon.html http://gradle.org/why/high-performance-builds/ http://tools.android.com/tech-docs/new-build-system/tips

Viewing all articles
Browse latest Browse all 1997

Trending Articles