ผมหายไปเต็มๆ หนึ่งสัปดาห์ ผู้อ่าน Blog ใน GotoKnow คงสงสัยว่าหายไปไหน หรือทิ้งทุ่นทิ้งระบบแอบไปเที่ยวไหน หรือไปแอบเปิดเว็บใหม่นะ ไม่ใช่ครับ ไม่ใช่ทั้งหมดเลย และบทความนี้ล่ะที่ผมจะเฉลยให้ฟัง

GotoKnow เริ่มเป็นที่รู้จักและมีผู้ใช้ที่ใช้อย่างพร้อมๆ กัน (Concurrent User) มากขึ้นทำให้ระบบเริ่มทำงานช้าลง ทั้งนี้เป็นเพราะ MemeExpress ที่เราใช้ทำ GotoKnow เป็น CGI Application ซึ่งในการทำงานนั้นจะใช้ทรัพยากรระบบมาก ซ้ำร้ายเราใช้ SQLite ซึ่งทำงานช้ากว่า Server-based SQL engine เก็บข้อมูลอีกต่างหาก และอีกหลายข้อหลายประการที่ดูเป็นปัจจัยที่ทำให้ระบบช้า แต่การตัดสินใจเลือกเทคโนโลยีทุกอย่างก็มีเหตุผลและมีการแก้ปัญหาที่น่าสนใจที่จะเล่าให้ฟังครับ

“Optimization”

ในการพัฒนา MemeExpress นั้น เราเลือกเอาความเร็วในการทำให้ระบบใช้งานได้ก่อนเพื่อให้ทันกับความต้องการของ สคส ผู้สนับสนุนเราในการพัฒนานี้ อย่างไรก็ตามในการพัฒนานั้นเราเลือก “การออกแบบสถาปัตยกรรมระบบที่ดี” มาก่อน “ความเร็วในการทำงานของระบบ” ด้วยเหตุนี้เองเราจึงพัฒนาโดยเน้นการออกแบบสถาปัตยกรรมระบบและไม่ได้ให้ความสำคัญกับ code ว่าจะทำงานได้เร็วช้าเพียงไรขอให้ทำงานได้ตามสถาปัตยกรรมที่ออกแบบไว้ก็เพียงพอแล้ว การตัดสินใจแบบนี้เราเชื่อว่าน่าจะเป็น Best Practice สำหรับการพัฒนาระบบที่มีกำหนดส่งค่อนข้างกระชั้นเช่นนี้

หลังจากเราได้นำ MemeExpress มาใช้ทำ GotoKnow แล้ว เราก็ค่อยๆ optimize code ของ MemeExpress ในส่วน code ที่ทำงานช้าให้เร็วขึ้นอย่างค่อยเป็นค่อยไป การเลือกที่จะทำสถาปัตยกรรมให้ดีไว้ก่อนช่วยให้เรา optimize ได้อย่างไม่ลำบากนัก งานโดยส่วนใหญ่จึงเป็นการแก้ในส่วนเฉพาะเป็นจุดๆ ไปให้ทำงานได้เร็วขึ้นหรือถูกต้องมากขึ้น (refactoring) มากกว่าการแก้โครงสร้าง (rearchitecturing)

เรื่อง code optimization นี่เป็นศิลปะอย่างหนึ่งในการเขียนโปรแกรม เกิดขึ้นจากประสบการณ์และทักษะที่สั่งสมมาของนักพัฒนาโปรแกรม ผมทราบว่าในประเทศที่เน้นอุตสาหกรรม software นั้น นัก optimize code ที่มีฝีมือมีรายได้ไม่น้อยทีเดียว ดังนั้นทักษะนี้จึงเป็นสิ่งที่ผู้เรียนรู้ด้านนี้ควรฝึกฝนใส่ตัวเป็นอย่างยิ่ง โจทย์ในการฝึกฝนก็คือ “ทำอย่างไร code ที่เรากำลังเขียนอยู่นี้ทำงานเร็วที่สุด” ผมเองก็ไม่ใช่เป็นนัก optimize code ที่ดี แต่ก็เป็นทักษะที่พยายามฝึกฝนอยู่ครับ

นอกจากการพึ่งทักษะของ software engineer ในการ optimize code แล้ว เพื่อลดเวลาและต้นทุนในการ optimization เครื่องไม้เครื่องมือในการนี้ก็มีออกมาให้ใช้กันอย่างมากมาย ทั้งแบบ open-source และ commercial ซึ่งคุ้มค่าในการเรียนรู้สำหรับ software engineer ทุกคน

การ optimize code ซึ่งอยู่ในภาษา Python ของเรา ในตอนนี้เราใช้เครื่องมือได้แก่ PyLint ซึ่งเป็น software ที่ช่วยบอกถึง “ตัวริ้นไร” (Lint) หรือส่วนที่น่าสงสัยว่าจะสร้างปัญหาที่มีอยู่ใน code ของเรา PyLint ช่วยลดเวลาในการ optimization ของเราได้มาก อีกทั้งยังช่วยแนะนำให้เราแก้ code ให้สามารถอ่านได้ง่ายยิ่งขึ้นด้วย การใช้งาน PyLint ซึ่งเป็น command-line application ก็ไม่ยากนัก ผู้สนใจสามารถเรียนรู้ได้อย่างรวดเร็วและได้ผลลัพธ์คุ้มค่ากับเวลาที่เสียไป

“mod_python

การพัฒนา MemeExpress นี้ เราต้องการให้ผู้ใช้นำไปใช้ได้อย่างง่ายที่สุด ดังนั้นการ “back to the basic” ด้วยการใช้ CGI (Common Gateway Interface) ในการติดต่อกับ Web Server ดูเหมือนจะเป็นทางเลือกที่ดีที่สุดในการเริ่มต้น เพื่อให้เหมาะสำหรับผู้ใช้ที่จะนำไปใช้ในองค์กรเล็กๆ แต่อย่างไรก็ตามในการออกแบบสถาปัตยกรรมนั้น เราเตรียมไว้เพื่อสามารถพัฒนาเพิ่มเติมเพื่อใช้รูปแบบการติดต่ออื่นซึ่งทำงานได้เร็วกว่าได้อีกสองรูปแบบคือ mod_python และ FastCGI ด้วย

ในตอนแรกนั้น เราคิดว่าคงให้ GotoKnow เป็นที่รู้จักอีกพักใหญ่ๆ กว่าต้องเราไปเพิ่มเติมในส่วนเพื่อให้ MemeExpress ใช้งานกับการติดต่อรูปแบบอื่นได้ แต่ปรากฎว่า GotoKnow ประสบความสำเร็จเร็วกว่าที่เราคาดไว้และระบบเริ่มช้าลง (ทั้งเป็นเพราะความเป็น CGI Application และปัจจัยอย่างอื่น) ดังนั้นเราจึงตัดสินใจพัฒนาเพิ่มเติมเพื่อให้ระบบทำงานได้กับ mod_python เพื่อรองรับจำนวนผู้ใช้ที่เพิ่มขึ้นนี้

Mod_python เป็น module ของ Apache โดยหน้าที่ของ mod_python คือการฝัง Python Interpreter เข้าไปใน Apache นั่นเอง ที่จริงแล้ว Apache Modules ที่ฝังตัวแปลภาษาเข้าไปในระบบนั้นมีหลายตัวด้วยกัน แต่ที่เป็นที่รู้จักอย่างแพร่หลายก็คงหนีไม่พ้น mod_php (ซึ่งฝังภาษา PHP) ส่วนอีกตัวที่ได้รับความนิยมน้อยลงกว่ามาหน่อยก็คือ mod_perl ซึ่งจะบอกว่าได้รับความนิยมน้อยก็ไม่เชิงนักเพราะ mod_perl นี่เองคือตัวที่ Amazon.com เลือกใช้

ด้วยการใช้ mod_python ทำให้ MemeExpress ทำงานเร็วขึ้นจากเดิมมาก อย่างไรก็ตามการแปลง CGI application ให้เป็น mod_python application นั้นไม่สามารถทำได้โดยตรง เพราะ interface ของ CGI และ mod_python นั้นไม่เหมือนกันเสียทีเดียว อีกทั้งธรรมชาติของการทำงานของ CGI application กับ mod_python application นั้นไม่เหมือนกัน กล่าวคือ CGI application ทำงานครั้งเดียวจบ เมื่อมีการเรียกใช้ครั้งใหม่ก็เริ่มการทำงานใหม่ (PHP application ก็ทำงานเหมือนกับ CGI application แม้จะทำงานผ่าน mod_php ก็ตาม) ส่วน mod_python application นั้นจะเสมือนว่าทำงานตลอดเวลาตั้งแต่การเรียกใช้งานครั้งแรก (Pseudo-State Retention)

ความแตกต่างในหลายประเด็นนั้นเป็นสิ่งที่ต้องจัดการเมื่อเราต้องการให้ MemeExpress ทำงานได้ทั้งกับ CGI และ mod_python และด้วยการออกแบบสถาปัตยกรรมของ MemeExpress แบบ object-oriented เราใช้วิธีการฝัง (encapsulate) งานที่เกี่ยวกับติดต่อกับ Web server ไว้ใน class hierarchy ดังนี้ ได้แก่ MeCtrler class เป็น base class โดยมี MeCgiCtrler class เป็น subclass เพื่อรองรับการใช้งานแบบ CGI และ MeModPythonCtrler class เป็น subclass เพื่อรองรับการใช้งานกับ mod_python ในอนาคตเราจะเขียน MeFastCgiCtrler class เป็นอีก subclass เพื่อรองรับ FastCGI ด้วย

“More to Do”

แม้ code optimization และการใช้ mod_python จะช่วยเพิ่มความเร็วในการทำงานอีกมาก แต่เรายังมีคอขวดที่การใช้ SQLite ซึ่งในส่วนนี้เราจะพัฒนาเพิ่มเติมต่อไปเพื่อให้ MemeExpress สามารถใช้งาน database engine อื่นที่มีความเร็วในการทำงานเพื่อรองรับ concurrent user จำนวนมากกว่าได้ด้วย ส่วน Source code ของ MemeExpress ในขณะนี้เข้าที่เข้าทางขึ้นมาก ตอนนี้เรากำลังใส่ License Agreement ต่างๆ ให้เรียบร้อยแล้วจะเปิดให้ download เพื่อไปทดลองดูกันในเวลาไม่ช้านี้ครับ