LibThai Optimization
การปรับไปใช้ datrie 32 บิต ก็ทำให้ libthai สามารถเพิ่มคำในพจนานุกรมได้อีกเยอะ แต่ปรากฏว่า ราคาที่ต้องจ่ายไป นอกเหนือจากการใช้หน่วยความจำเพิ่มขึ้นอีกเท่าตัว (จาก 16 บิตเป็น 32 บิต) ก็คือ performance ที่ตกลงอีกราว 66% จากเวลาในการโหลดพจนานุกรมที่นานขึ้น และปริมาณการ access หน่วยความจำที่เพิ่มขึ้น
แต่การเพิ่มขนาดของ trie ก็เป็นเรื่องจำเป็นสำหรับการตัดคำไทย เพราะภาษาไทยมีจำนวนคำมากกว่าที่ trie 16 บิตจะรองรับได้ เพราะฉะนั้น ก็เลยต้องมาปรับปรุงเรื่องประสิทธิภาพ
เครื่องมือที่ใช้ช่วย ก็คือ valgrind โดยเขียนโปรแกรมง่าย ๆ ขึ้นมาลิงก์กับ libthai เพื่อทดสอบ
แต่ก่อนอื่น เนื่องจาก libthai มีการใช้งานอยู่ในระบบ ผมจึงเลี่ยงการกระทบกับระบบระหว่างทดสอบ ด้วยการติดตั้ง libthai และ datrie ฉบับ CVS ลงใน $HOME/libthai
โดยตั้งตัวแปรระบบดังนี้:
$ export PATH=$HOME/libthai/bin:$PATH $ export PKG_CONFIG_PATH=$HOME/libthai/lib/pkgconfig $ export LD_LIBRARY_PATH=$HOME/libthai/lib
แล้วใช้ configure option สำหรับ datrie และ libthai ดังนี้:
$ ../configure CFLAGS="-Wall -g -O0" --prefix ~/libthai
คอมไพล์ ติดตั้ง ตามปกติ จากนั้นก็มาเขียนโปรแกรมทดสอบแบบง่าย:
#include <string.h> #include <stdio.h> #include <thai/thbrk.h> int main () { char line [1024]; char bline [1024]; while (fgets (line, sizeof line, stdin)) { if (line [strlen (line) - 1] == '\n') line [strlen (line) - 1] = '\0'; th_brk_line (line, bline, 1024, "|"); printf ("%s\n", bline); } return 0; }
คอมไพล์โปรแกรมทดสอบ:
$ cc -o wbrk-test `pkg-config --cflags --libs libthai` wbrk-test.c
แล้วใช้ valgrind ตรวจสอบ โดยเริ่มจาก Memcheck:
$ cat testmsg | valgrind --leak-check=yes ./wbrk-test
เจอ memory leak จากการเปิดพจนานุกรมเป็น static data ซึ่งเป็นความจงใจ เพื่อให้โปรแกรมที่มาลิงก์กับ libthai ไม่จำเป็นต้องโหลดพจนานุกรมจนกว่าจะได้เรียกรูทีนตัดคำไทยจริง ๆ เป็นการโหลดเพียงครั้งเดียว แล้วใช้ในครั้งต่อ ๆ ไป แต่การทิ้ง memory leak ไว้ก็ไม่สวย โดยเฉพาะโปรแกรมที่โหลด libthai ด้วย dlopen()
จะทิ้งร่องรอยไว้หลังจาก dlclose()
ไปแล้ว ความจริงอยากแก้นานแล้ว ก็ถือโอกาสแก้เสียเลย (commit เข้า CVS ไปแล้ว)
หมดจากกรณีนี้ ก็ไม่มี memory leak เหลืออยู่อีกเลย ว้าว รอดตัวไป
จากนั้น ก็วัดประสิทธิภาพ หาจุดคอขวดด้วย Callgrind:
$ cat testmsg | valgrind --tool=callgrind ./wbrk-test
สำหรับผลลัพธ์ที่ Callgrind เขียนออกมานั้น คู่มือ เขาแนะนำให้เปิดดูด้วย KCachegrind แต่ทราบมาว่า Alleyoop หรือกระทั่ง Anjuta ก็ใช้เป็น frontend ได้เหมือนกัน แต่ผมมันพวกขี้เกียจ เพราะกว่าจะเซ็ตอะไร ๆ ให้พร้อมใช้ก็คงนาน อีกทั้งไม่แน่ใจว่าจะสามารถตั้ง environtment ต่าง ๆ ได้อย่างใจหรือเปล่า เลยเล่นง่าย ๆ ไปก่อน ด้วยการเปิดดูด้วย vim แล้วแกะข้อมูลตาม เอกสารทางเทคนิค ก็ทำให้เจอคอขวดได้เหมือนกัน
ที่ผ่านมา ก็ลดคอขวดไปได้สองแห่ง ลดเวลาลงได้ราว 15% ก็ต้องพยายามกำจัดจุดอ่อนต่อไป
การ optimize โดยใช้ Callgrind ช่วยในครั้งนี้ เป็นการ optimize โค้ดล้วน ๆ ด้วยการ implement ตรรกะเดิมให้เร็วขึ้น ยังไม่ใช่การทำ cut-off ในระดับตรรกะเหมือน รอบที่แล้ว ที่ทำหลังจากเปลี่ยนมาใช้พจนานุกรมภายนอก
ปล. พักหลัง ๆ นี้ ผมเขียน blog ด้วยการ "เล่าข่าวคราว" เท่านั้น ว่าทำอะไรคืบหน้าไปบ้าง โดยไม่ได้ลงรายละเอียดทางเทคนิค ก็หวังว่าการ blog โดยเพิ่มรายละเอียดด้วย จะเป็นประโยชน์กับผู้อ่านมากขึ้นบ้าง รวมทั้งกับตัวผมเองในอนาคตด้วย เป็นบันทึกกันลืม
ป้ายกำกับ: libthai