Skip to main content

เขียนโค้ดยาวขึ้น แต่ทำงานไวขึ้น? จริงไหม? เกิดจากอะไร?

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

ก่อนอื่นสำหรับคนที่ลืมว่า for-loop เขียนแบบไหน แล้วทำงานอย่างไรไปแล้ว หรือไม่คุ้นชินกับรูปแบบนี้ ก็มาหยุดพักชมตรงนี้สักครู่

ใน for-loop รูปแบบนี้ภายในจะแบ่งเป็น 3 ส่วนคั่นด้วย Semicolon ( ; ) เรียงตามลำดับดังนี้

  1. สิ่งที่ทำก่อนจะเริ่มต้นลูป ส่วนมากจะประกาศตัวแปรไว้นับรอบการทำงานของลูป
  2. เงื่อนไขในการทำงานของลูป ก่อนจะทำงานแต่ละรอบจะมาตรวจสอบตรงนี้ หากเป็น true ก็จะเริ่มรอบต่อไป แต่หากเป็น false จะเป็นการจบการทำงานของลูปนั้น
  3. จัดการการนับในตัวแปรที่ประกาศไว้ในขั้นที่ 1 ว่าจบแต่ละรอบให้เพิ่ม/ลดเท่าไร

มาลองเทียบดูกันชัด ๆ ว่าแบบที่บอกว่าเขียนยาวกว่าแต่ว่าทำงานได้ไวกว่ามาเป็นอย่างไร

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

เมื่อเห็นแบบนี้แล้วเลยก็กลายมาเป็นแบบที่สอง ถ้าไม่อยากให้มันนับซ้ำ ๆ ก็นับรอไว้ก่อนสิ ยาวขึ้นมาหนึ่งบรรทัด แต่ว่าไม่ต้องเข้าไปนับใหม่ทุกรอบให้เสียเวลา

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

แต่ตอนใช้งานจริง มันก็ต้องมีปัจจัยอื่นเข้ามาร่วมด้วยอยู่แล้ว อย่างเช่นในกรณีนี้ที่โค้ดเราเป็น JavaScript แล้วไปทำงานในเอนจิน V8 ที่ถูกใช้โดย Node.js หรือ Chromium-based Browser เช่น Google Chrome หรือ Microsoft Edge

ซึ่งหนึ่งในการทำงานของ V8 ก็คือทุกครั้งที่มีการยุ่งกับ Array เช่น push, pop เพื่อเพิ่ม/ลบข้อมูล จะทำการคำนวณขนาดไว้ให้ทุกครั้ง ดังนั้นการเรียก length แต่ละรอบก็จะไม่ได้เป็นการสั่งให้เข้าไปไล่นับจำนวนทุก ๆ รอบอย่างที่คิดกันไว้

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

อีกกรณีหนึ่งที่น่าสนใจก็คือหากเราเก็บข้อมูลไว้ใน ArrayList ของ Java หรือ Collection ของ C# หากไปแกะถึงในซอร์สโค้ดของทั้งสองตัวนี้จะเห็นได้ว่าเวลาดึงจำนวนออกมาไม่ได้เป็นการเข้าไปไล่นับแต่อย่างใด แต่ว่าแค่อ่านค่ามาให้เราเฉย ๆ เพราะมีการเก็บจำนวนไว้ภายในอยู่แล้ว จะเพิ่มลดก็ต่อเมื่อมีการเรียก Add หรือ Remove เท่านั้น

เป็นกรณีที่คล้ายกับ JavaScript ที่เจาะจงกับเอนจินที่นำโค้ดไปทำงาน แต่ว่ากรณีนี้เป็นที่ตัวภาษาเลย ซึ่งก็แปลว่าไม่ว่าจะนำไปทำงานที่ไหนก็จะได้ผลลัพธ์ที่คล้ายกันแน่นอน

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

“Premature-micro optimizations are the root of all evil”

“การพยายามเพิ่มประสิทธิภาพอย่างไม่ถูกที่ถูกเวลาจะเป็นต้นตอของปัญหาทั้งหมด”

การเพิ่มประสิทธิภาพไม่ใช้สิ่งที่ผิด แต่ก่อนจะทำลองมาตอบคำถามเหล่านี้ดูก่อนดีไหม?

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

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


อ่านเพิ่มเติม/อ้างอิง


เนื้อหานี้ถูกเผยแพร่ครั้งแรกในรูปแบบของโพสท์ Facebook เพื่อให้ง่ายต่อการสืบค้นจึงนำมาจัดเก็บในรูปแบบบทความด้วย