Theppitak's blog

My personal blog.

19 มิถุนายน 2561

libdatrie 0.2.12

libdatrie 0.2.12 ออกแล้ว ไล่หลัง 0.2.11 เพียง 2 เดือน หลังจากผ่านการทำความสะอาดโค้ดมาระยะหนึ่ง

เริ่มจากผมได้รับแพตช์จากคุณ Peter Moulder ทางเมลส่วนตัว ซึ่งเสนอปรับแก้ 3 รายการคือ:

  • แก้การประกาศฟังก์ชันที่ไม่รับพารามิเตอร์ด้วยรูปแบบ f(void) แทน f() เนื่องจากรูปแบบ f() เป็นเพียงการประกาศแบบ K&R ซึ่งไม่ระบุข้อมูลเกี่ยวกับพารามิเตอร์ ซึ่งในการ call จริงอาจใส่อาร์กิวเมนต์ใด ๆ มาก็ได้ ในขณะที่แบบ f(void) จะแสดงความชัดเจนว่าไม่รับพารามิเตอร์ใด ๆ
  • เปลี่ยนการกำหนดชนิด Bool ซึ่งเดิมกำหนดเป็น enum TRUE, FALSE ซึ่งจะไปชนกับค่าในซอร์สโค้ดอื่นได้ง่ายมาก จึงเปลี่ยนชื่อหลบแล้ว define TRUE, FALSE แบบมีเงื่อนไขเอา
  • ตัด typedef ชนิด byte, word, dword ที่ไม่มีการใช้งานใน libdatrie แต่มีโอกาสชื่อชนกับซอร์สอื่นที่ไปใช้ร่วมสูงมาก

นั่นนำไปสู่การตรวจสอบหาประเด็นอื่น ๆ ต่อ โดยใช้ CFLAGS="-ansi -pedantic -Wall" รวมถึงการใช้ CC=clang ด้วย ทำให้จับประเด็นเพิ่มได้อีกหลายรายการ หนึ่งในนั้นมีผลข้างเคียงเป็นการป้องกันการตัดท้ายชื่อพาธของพจนานุกรมที่ยาวมาก ๆ ด้วย

เหลือประเด็นที่ยังคงไว้ คือการใช้ "%ls" ใน printf() format string เพื่อพิมพ์ข้อความยูนิโค้ดที่อยู่ในรูป wide char string ซึ่งไม่มีใน C90 โค้ดนี้เป็นโค้ดที่อยู่ใน test ในส่วนแสดงข้อมูลการทำงานของ test เท่านั้น ไม่ได้อยู่ในโค้ดของ library และไม่ใช่ส่วนสำคัญที่ชี้ขาดผลการ test จึงปล่อยไว้อย่างนั้น เพราะหากพยายามทำให้ได้ตาม C90 จริง ๆ จะยุ่งยากเกินจำเป็น

ตามมาด้วย Debian upload ซึ่งเพิ่ม pkg-config เข้าใน dependency ของ libdatrie-dev เพื่อประกันว่า datrie-0.2.pc สามารถทำงานได้แม้ในระบบที่ติดตั้งแบบ minimal จริง ๆ

ป้ายกำกับ:

23 เมษายน 2561

libdatrie 0.2.11

libdatrie 0.2.11 ออกแล้ว หลังจากที่ไม่ได้ออกรุ่นมาเลยถึงสองปีครึ่ง และนับเป็น release แรกของ libdatrie ที่ออกจาก github หลังจากที่ปล่อยให้แพกเกจอื่น ๆ ทยอยออกรุ่นกันไปเยอะแล้ว

รุ่นนี้มีความเปลี่ยนแปลงที่สำคัญนอกเหนือจากการย้ายมา Github คือ:

  • ตรวจสอบ error จาก iconv() ได้ถูกต้องยิ่งขึ้น จากรายงานของ Daniel Macks ใน Issue #3
  • ปรับคำบรรยายแพกเกจใน README เนื่องจาก @flackbash ทักท้วงมาใน Issue #4 ว่า complexity ของการ search ของ trie เป็น O(m) เมื่อ m คือความยาวของคีย์ ไม่ใช่ O(1) เสียหน่อย ซึ่งอันที่จริง การอ้าง O(1) ก็เป็นเพียงการบอกว่า เวลาที่ใช้มันไม่ขึ้นกับขนาดของฐานข้อมูลเท่านั้น ในทำนองเดียวกับที่ hash table มักจะอ้าง compexity O(1) เหมือนกัน ทั้ง ๆ ที่เวลาที่ใช้ในการคำนวณค่า hash โดยปกติก็เป็น O(m) อย่างไรก็ดี ถูกทักท้วงมาเช่นนี้ก็แก้ไขตามนั้น แต่ยังคงเน้นว่ามันไม่ขึ้นกับขนาดของฐานข้อมูล
  • ปรับแก้การทำงานของ trie_state_get_data() ซึ่งเดิมทำงานไม่ถูกต้องในกรณีที่คีย์ที่ใช้ค้นนั้นเป็นส่วนต้นของคีย์อื่น (เช่น กา เป็นส่วนต้นของ การ) ซึ่งทำให้โครงการ pytries หันไปใช้วิธีเพิ่มฟังก์ชันใหม่ โดยส่งแพตช์มาให้ผมในเมลส่วนตัว ผมจึงแสดงความเห็นไปว่าน่าจะปรับแก้ฟังก์ชันเดิมให้ทำงานให้ถูกต้อง แทนที่จะเพิ่มฟังก์ชันใหม่ เรื่องเงียบไประยะหนึ่ง จนกระทั่งมีการผลักดันแพกเกจ python-datrie เข้า Debian (ITP) Andreas Tille จึงหันมากระทุ้งผมเรื่องนี้อีกครั้ง (Debian #894278) จนในที่สุดผมก็เลยแก้ปัญหานี้ (commit) และ Filip Pytloun ก็ได้ช่วยทดสอบให้ และปรับแก้ที่ pytries ให้
  • แก้ปัญหา segfault เมื่อใช้งานกับ alpha map แบบเต็มช่วง (0-255) โดย Xiao Wang รายงานใน Issue #6 ว่าเขาพบเมื่อใช้งานกับ PHP ซึ่งผมยังไม่มีเวลาไปตรวจสอบ จึงทิ้งช่วงมาจนกระทั่ง @nevermatch เข้ามาวิเคราะห์และชี้จุดผิดพลาดให้ ซึ่งผมก็ยังคง reproduce ไม่ได้อยู่ดี คือมันไม่ segfault แต่พบความผิดปกติตามที่เขาชี้จริง จึงถือว่ามีข้อมูลเพียงพอที่จะแก้ปัญหาได้แล้ว ซึ่งต้องขอขอบคุณทั้งสองท่านอย่างมากที่ช่วยตรวจสอบปัญหานี้ให้

ถือว่ารุ่นนี้ได้รับ contribution จากผู้ใช้ค่อนข้างหลากหลาย โดยเฉพาะการช่วยวิเคราะห์ปัญหาที่น่าประทับใจ และได้รู้เพิ่มเติมว่ามีการใช้งาน libdatrie กับ PHP ด้วย

และเช่นเคย upload 0.2.11-1 เข้า Debian เรียบร้อยแล้ว พร้อมความเปลี่ยนแปลงอื่น ๆ เพิ่มเติม เช่น การรองรับการ build ที่ไม่ต้องใช้ (fake)root

ป้ายกำกับ:

16 ตุลาคม 2558

LibThai Thread-safety

อันเนื่องมาจากการที่ Pango 1.38.0 ที่ออกมาพร้อมกับ GNOME 3.18 ได้ตัดระบบ dynamic module ทิ้ง แล้วใช้วิธีรวมเข้าในซอร์สโค้ดเลย (GNOME #733882) ทำให้ผู้ดูแลหลัก คือ Behdad Esfahbod ได้มีโอกาสรื้อมอดูลภาษาต่าง ๆ รวมถึงภาษาไทย และพบประเด็นของ libthai ที่รองรับการตัดคำของมอดูลภาษาไทยอยู่ จึงได้ติดต่อมาที่ผมเพื่อให้แก้ไข โดยประเด็นสำคัญคือเรื่อง thread-safety

โค้ดใน libthai มีส่วนหนึ่งที่ทำให้ไม่ปลอดภัยเมื่อเรียกใช้ผ่าน thread หลาย thread พร้อมกัน ซึ่งเป็นส่วนที่ผมใช้ลดปริมาณการเรียก malloc() โดยยังไม่ free() โหนดทางเลือกต่าง ๆ ของการตัดคำที่เลิกใช้แล้วในทันที แต่เอาไปฝากไว้ใน free list เพื่อนำกลับมาใช้ใหม่ และไอ้เจ้า free list ที่เป็นเสมือนโกดังเก็บของเก่ารอ reuse นี่แหละ ที่ implement แบบ static โดยไม่มีการจองก่อนเข้าใช้ ทำให้เมื่อมีหลาย thread เข้าใช้พร้อมกันจะเกิด race condition ขึ้นได้

ประเด็นนี้ pango รุ่นนี้แก้ปัญหาเฉพาะหน้าด้วยการ ล็อคก่อนเรียก th_brk() เพื่อให้ thread ต่าง ๆ เข้าใช้ฟังก์ชันนี้ทีละ thread ซึ่งอาจกลายเป็นคอขวดของระบบหลาย thread ได้ ทางที่ดีคือทำให้ libthai threadsafe เสีย

ทางเลือกที่เป็นไปได้จึงมี 3 ทาง

  1. ยกเลิก free list ไปเสีย (ซึ่ง Behdad สนับสนุน โดยให้เหตุผลว่า malloc() ใน libc รุ่นหลัง ๆ ทำงานเร็วขึ้นมากแล้ว และ CPU สมัยใหม่ก็ทำงานเร็วขึ้นมากแล้วด้วย จะไปนั่งออปติไมซ์ทำไมให้เมื่อยตุ้ม)
  2. ใช้ free list 1 ชุดต่อ 1 thread แทนที่จะใช้ร่วมกันหมด (แต่ละ thread เก็บโหนดที่เลิกใช้ไว้ในกระเป๋า recycle ของใครของมัน ไม่ต้องใช้ร่วมกัน)
  3. ใช้ free list กลางเหมือนเดิม แต่ให้มีระบบ lock (แต่ละ thread ต้องล็อคโกดังขณะเข้าใช้ thread อื่นต้องรอให้ thread ที่ใช้งานอยู่ใช้ให้เสร็จเสียก่อนจึงจะเข้าใช้ได้)

วิธียกเลิก free list อาจจะง่าย แต่ก่อนจะเชื่อก็ต้องวัดดูก่อน ซึ่งจากการทดลองของผมก็พบว่า th_brk() จะทำงานนานขึ้นถึง 18% ถ้าใช้ malloc() ตรง ๆ ทุกครั้ง หรือถ้าเทียบกลับ การใช้ free list สามารถประหยัดเวลาจากการใช้ malloc() ได้ถึง 15% ซึ่งผมถือว่ามีนัยสำคัญ ฉะนั้นจึงไม่เลือกวิธีนี้

จากนั้นจึงมาทดลองวิธีใช้ free list 1 ชุดต่อ 1 thread ซึ่งวิธีการก็ไม่ได้มีอะไรมาก เพียงแค่เปลี่ยนจากการใช้ตัวแปร static มาเป็นการสร้าง free list ใหม่ในการเรียก th_brk() แต่ละครั้งเท่านั้นเอง เนื่องจากตัว libthai เองไม่ได้สร้าง thread ใหม่อยู่แล้ว การสร้าง thread เกิดจากโค้ดผู้เรียกอย่าง pango หรือผู้ที่เรียก pango อีกทีทั้งสิ้น การสร้าง free list ต่อ 1 call ก็เท่ากับการสร้างต่อ 1 thread นั่นเอง

ผลการทดลองคือ free list แบบต่อ thread ก็ยังสามารถประหยัดเวลาได้ถึง 13% (2% ที่หายไปพบภายหลังว่าเกิดจากการสร้าง free list ผิดจากจุดเดิมในโค้ด ทำให้เกิดการสร้างและทำลาย free list เพิ่มขึ้น เมื่อแก้ให้ตรงกับจุดเดิมก็ปรากฏว่าประหยัดเวลาได้เท่าๆ ของเดิม) ซึ่งถือว่าน่าพอใจ

วิธีสุดท้ายที่ใช้ระบบล็อคนั้น จะทำให้ libthai ต้องมีการแทรกโค้ดการเรียก pthread เข้ามา ซึ่งทำให้โค้ดส่วนนี้ดูแปลกแยกไม่สวยงาม และในเมื่อวิธีที่ใช้ free list ต่อ thread ได้ผลเป็นที่น่าพอใจอยู่แล้ว ผมจึงไม่พิจารณาวิธีนี้อีก

จึงได้เป็น rev 577 (และแก้ไขเพิ่มเติมใน rev 583 หลังจากพบสาเหตุที่ทำให้การประหยัดเวลาลดลง 2%)

นอกจากนั้น ก็เป็นความพยายาม optimize การตัดคำของ libthai ต่อ ดังรายการต่อไปนี้:

  • optimize libdatrie ในส่วน AlphaMap (การแม็ปอักขระให้เป็นดัชนีสำหรับ trie transition ซึ่งจะเกิด ทุกครั้ง ที่มี transition) จากการคำนวณหาลำดับของอักขระจากช่วงต่าง ๆ ที่กำหนด มาเป็นการเปิดตารางที่สร้างไว้ล่วงหน้า ฟังดูอาจจะนึกว่ามันคงเร็วขึ้นอย่างมโหฬาร แต่สำหรับ libthai แล้วไม่ใช่ เนื่องจากเรากำหนดช่วงอักขระภาษาไทยเป็นช่วงต่อเนื่องเพียงช่วงเดียว การคำนวณลำดับอักขระจึงไม่ซับซ้อน เพียงแค่ลบด้วยอักขระแรกของช่วงแล้วบวกด้วย 1 ก็จบแล้ว การทำงานที่ประหยัดได้จากการเปิดตารางจึงเป็นเรื่องของโสหุ้ยของการวนลูปเล็ก ๆ น้อย ๆ เท่านั้น ซี่งปรากฏว่าทำให้ตัวฟังก์ชันใช้เวลาทำงานลดลง 14.6% และทำให้การตัดคำของ libthai ใช้เวลาลดลงโดยรวม 0.2% เท่านั้น (libdatrie rev 277) แต่สำหรับ use case ที่อักขระอินพุตมีหลายช่วงไม่ต่อเนื่อง การเปิดตารางนี้จะช่วยประหยัดเวลาได้มาก
  • optimize libthai ในส่วนของการยุบรวมกรณีตัดคำที่ตกตำแหน่งเดียวกัน (การตัดคำของ libthai ใช้วิธีลองตัดคำแบบต่าง ๆ เทียบกับพจนานุกรม แล้วเลือกเอาวิธีที่ได้จำนวนคำน้อยที่สุด โดยใช้การค้นแบบ best-first search ซึ่งคล้ายกับ breadth-first search แต่มีการคำนวณ heuristic ของกรณีต่าง ๆ และยุบรวมกรณีที่คืบหน้าเท่ากันเป็นระยะ ๆ) ซึ่งปรากฏว่าฟังก์ชัน brk_pool_match() ขึ้นชาร์ตฟังก์ชันที่กินเวลานานในรายงานของ Callgrind จึงพยายาม optimize ด้วยการทำให้ตัวฟังก์ชันเร็วขึ้นด้วยการแยกลูปเพื่อลด branching (rev 579 ตัวฟังก์ชันใช้เวลาลดลง 9.3%, runtime โดยรวมลดลง 0.067%) และด้วยการลดปริมาณงานของฟังก์ชันโดยค้นต่อจากจุดเดิมแทนการเริ่มที่ต้นลิสต์เสมอ (rev 582 ตัวฟังก์ชันใช้เวลาลดลง 8.85%, อันดับในชาร์ตเลื่อนลง 2 ขั้น, runtime โดยรวมลดลง 0.0388%) รวมแล้ว ตัวฟังก์ชันใช้เวลาลดลง 17.3% runtime โดยรวมลดลงประมาณ 0.1%

สรุปแล้ว การตัดตำของ libthai โดยรวมใช้เวลาลดลงประมาณ 0.28% (รวมเวลาโหลดพจนานุกรม) พร้อมกับปลอดภัยสำหรับการทำงานหลาย thread โดยไม่ต้องล็อคด้วย

ถ้าไม่มีไอเดียใหม่อีก ก็คงจะออกรุ่นใหม่เร็ว ๆ นี้ครับ

ในอีกด้านหนึ่ง ทีม debian-cd ได้กระทุ้งมาอีกครั้งว่าช่วยทำ udeb ของ libthai ให้หน่อย จะได้ใช้ในโปรแกรมติดตั้งของเดเบียน (Debian #800369) ก็ทยอยทำตั้งแต่ libdatrie1-udeb (0.2.9-3) รอจนผ่าน NEW queue แล้วก็ทำ libthai-data-udeb และ libthai0-udeb ต่อ (ขณะที่เขียน blog ยังรออยู่ใน NEW)

ป้ายกำกับ: ,

03 กันยายน 2558

Thanks

ขอขอบคุณย้อนหลัง สำหรับผู้สนับสนุนงานพัฒนาซอฟต์แวร์เสรีของผมในช่วงปลายเมษายน 2558 ถึงต้นกันยายน 2558 ที่ผ่านมาครับ คือ:

  • ปลายเดือนเมษายน 2558
    • ผู้ไม่แสดงตน 1 ท่าน
  • เดือนพฤษภาคม 2558
  • เดือนมิถุนายน 2558
    • คุณธนาธิป ศรีวิรุฬห์ชัย
    • ผู้ไม่แสดงตน 1 ท่าน
  • เดือนกรกฎาคม 2558
    • คุณธนาธิป ศรีวิรุฬห์ชัย
    • ผู้ไม่ประสงค์จะออกนาม
  • เดือนสิงหาคม 2558
  • ต้นเดือนกันยายน 2558

ขอให้ทุกท่านมีความเจริญก้าวหน้าในหน้าที่การงาน คิดสิ่งใดก็ขอให้สมปรารถนานะครับ

สี่เดือนที่ผ่านมา นับจาก บันทึกขอบคุณครั้งที่แล้ว งานพัฒนาที่ทำไปพอสรุปได้ดังนี้:

  • Optimize LibThai/LibDATrie เพิ่มเติม ตรวจสอบความเรียบร้อยทั่วไป และออกรุ่น libdatrie 0.2.9 และ libthai 0.1.22 พร้อมอัปโหลดเข้า Debian (libdatrie 0.2.9-1 และ libthai 0.1.22-1)
  • ตามแก้ปัญหาในแพกเกจ libdatrie-dev และ libthai-dev ที่อัปโหลดไว้ ดังที่มีผู้รายงานบั๊ก Debian #788163 และ Debian #788164
  • ออกรุ่น thaixfonts 1.2.7 ซึ่งได้เตรียมการแก้ปัญหาข้อมูล copyright ที่ขาดไว้ พร้อมทั้งเรื่อง reproducibility ที่ระบบของ Debian ตรวจพบ และแก้ปัญหาเล็ก ๆ น้อย ๆ ในตัว Debian package แล้วอัปโหลดเข้า Debian (thaixfonts 1.2.7-1)
  • ปรับแก้ฟอนต์ในชุด Fonts-TLWG ต่อ เพื่อรองรับภาษามลายูปาตานีเต็มรูปแบบ พร้อมกับเตรียม fallback โดยใช้ภาษาแต้จิ๋วเป็นโจทย์ ดังที่ได้ บันทีกไว้ ซึ่งขณะนี้ยังอยู่ระหว่างดำเนินการต่อ

  • อัปเดตแพกเกจ scim-thai ใน Debian เล็กน้อย เพื่อเป็นส่วนหนึ่งของการย้ายไป GCC5 ของ Debian

  • อัปเดตคำแปลชื่อภาษาใน ISO 639 และ ISO 639-3 ในแพกเกจ iso-codes (มีผลใน iso-codes 3.61)
  • ตรวจทานคำแปล GNOME ตามที่มีผู้ส่งเข้ามา

ขณะเดียวกัน ช่วงนี้งานที่ผมรับเพื่อ support ตัวเองเป็นงานสอน ซึ่งต้องใช้เวลาค่อนข้างมากในการเตรียมเนื้อหา จึงอาจเหลือเวลามาทำงานพัฒนาน้อยลง แต่ก็พยายามเจียดเวลาเท่าที่จะทำได้ครับ

ป้ายกำกับ: , , , ,

02 พฤษภาคม 2558

LibThai/LibDATrie Optimization Summary

นับจาก blog เรื่องการ micro-optimize libthai ซึ่งได้ทดลองใช้ LIKELY/UNLIKELY ในการลดการสะดุดของ pipeline ของ CPU ขณะทำ branching ซึ่งลดเวลาของการตัดคำของ libthai ลงได้เพียง 0.014% เท่านั้น แต่ปรากฏว่าเมื่อไปทำกับ libdatrie กลับให้ผลที่ดีกว่านั้น

โค้ดที่เป็นคอขวดจริง ๆ คือ da_get_base(), da_get_check() ซึ่งใช้อ่านช่องข้อมูล double array โดยมีการตรวจสอบขอบเขตของค่า index ของ array ด้วย เมื่อใส่ LIKELY() กำกับเงื่อนไขที่จะไม่ error แล้ว ปรากฏว่าเวลาที่ใช้ในการตัดคำลดลงอย่างมากเมื่อเทียบกับจุดอื่น ๆ โดยทั่วไป

แต่ก็อย่าคาดหวังอะไรมากกับ micro-optimization เพราะเวลาที่ลดลงได้จากการ micro-optimize libdatrie รวมแล้วคือ 1.94% แต่เมื่อเทียบกับ 0.014% ที่ได้ใน libthai ก็ถือว่าน่าตื่นตาตื่นใจไม่น้อย

อย่างไรก็ดี ในช่วงต่อมา ก็ได้มี คำแนะนำจากคุณ edgehogapp ว่าสามารถลดเวลาตัดคำของ libthai ลงได้ ถ้าแปลงรหัสข้อความจาก TIS-620 เป็น Unicode เพียงครั้งเดียวก่อนวิเคราะห์ แทนที่จะแปลงทุกครั้งที่วิเคราะห์แต่ละตัวอักษร ซึ่งเมื่อทดลองแล้วก็ปรากฏว่าสามารถลดเวลาลงได้อีกถึง 0.28%

ก่อนที่จะเตรียมออกรุ่น libdatrie และ libthai รุ่นใหม่ จึงมาวัดเวลาสรุปอีกครั้ง ว่าการออปติไมซ์ส่วนไหนให้ผลเท่าไร โดยใช้ test case เดียวกัน เวลาที่ callgrind วัดได้ในแต่ละกรณีคือ:

  • libthai เก่า + libdatrie เก่า: 39,000,827
  • libthai เก่า + libdatrie ใหม่: 38,242,294 (ลดลง 1.94%)
  • libthai ใหม่ + libdatrie เก่า: 38,851,449 (ลดลง 0.38%)
  • libthai ใหม่ + libdatrie ใหม่: 38,089,676 (ลดลง 2.34%)

เมื่อคิดเป็นอัตราเร็วที่เพิ่มขึ้น (1 / (1 - อัตราส่วนเวลาที่ลดลง) - 1):

  • libthai เก่า + libdatrie ใหม่: เร็วขึ้น 1.98%
  • libthai ใหม่ + libdatrie เก่า: เร็วขึ้น 0.38%
  • libthai ใหม่ + libdatrie ใหม่: เร็วขึ้น 2.39%

กล่าวคือ ความเร็วที่เพิ่มขึ้นส่วนใหญ่มาจากการออปติไมซ์ libdatrie และโดยรวมแล้วทำให้การตัดคำเร็วขึ้น 2.39%

ในการวัด ครั้งก่อน ผมได้แยกวัดเฉพาะเวลาที่ใช้ในการตัดคำจริง ไม่นับเวลาโหลดพจนานุกรม เพราะไม่ได้มีการเปลี่ยนแปลงใน libdatrie แต่ครั้งนี้ การออปติไมซ์ libdatrie จะมีผลทั้งสองส่วน ซึ่งเมื่อแยกวัดดูก็ได้ผลดังนี้:

เวลาที่ใช้ในการโหลดพจนานุกรม:

  • libthai ใหม่ + libdatrie เก่า: 663,463
  • libthai ใหม่ + libdatrie ใหม่: 633,318 (ลดลง 4.54%; เร็วขึ้น 4.76%)

เมื่อคิดเฉพาะเวลาที่ใช้ในการตัดคำ:

  • libthai ใหม่ + libdatrie เก่า: 38,851,449 - 663,463 = 38,187,986
  • libthai ใหม่ + libdatrie ใหม่: 38,089,676 - 633,318 = 37,456,358 (ลดลง 1.92%; เร็วขึ้น 1.95%)

กล่าวคือ การ micro-optimize libdatrie ส่งผลต่อการโหลดพจนานุกรมมากกว่าการตัดคำ และเฉพาะสำหรับการตัดคำ มีผลมากกว่าการ micro-optimize ตัว libthai เอง อย่างมาก (ลดเวลาลง 1.92% เมื่อเทียบกับ 0.014% จาก libthai)

นอกเหนือจากการ micro-optimize แล้ว libdatrie ยังมีรายการแก้บั๊กอีกรายการหนึ่ง ซึ่งคุณ Sergei Lebedev ได้รายงานเข้ามาทางอีเมลส่วนตัว โดยอ้างถึง บั๊กใน python wrapper ของ libdatrie เกี่ยวกับการ iterate trie ที่ว่างเปล่า

เตรียมออกรุ่นใหม่เร็ว ๆ นี้ละครับ ทั้ง libdatrie และ libthai

ป้ายกำกับ: ,

30 เมษายน 2558

Thanks

ขอขอบคุณย้อนหลัง สำหรับผู้สนับสนุนงานพัฒนาซอฟต์แวร์เสรีของผมในช่วงเดือนมกราคม 2558 ถึงเมษายน 2558 ที่ผ่านมาครับ คือ:

ขอให้ทุกท่านและครอบครัวมีความสุขความเจริญ สุขภาพแข็งแรงทั้งกายใจครับ

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

นอกจากการ optimize libthai/libdatrie ที่เคยเขียนไปแล้ว ก็มีงานจิปาถะอื่น ๆ อีก เช่น

  • งานแปล Xfce [ต้องล็อกอิน] ทั้งไล่กวดและไล่หลัง Xfce 4.12 ที่ออกไป จนขณะนี้อัตราการแปลของภาษาไทยอยู่ที่ 95% แล้ว
  • งานแปล GNOME ซึ่งผมเข้าสู่สถานะ review only (ไม่แปลเองอย่าง active) แล้ว ก็ได้ตรวจทานคำแปลที่มีนักแปลส่งเข้ามา
  • งาน Debian ในช่วงที่ Jessie freeze อยู่ ผมก็ได้แต่เตรียมปรับแก้ประเด็นเล็ก ๆ น้อย ๆ ที่ระบบ QA ต่าง ๆ ของ Debian ตรวจพบเพื่อรออัปโหลดในรอบ Stretch (Jessie + 1) ต่อไป เช่น:
    • lintian ส่วนใหญ่เป็นปัญหารูปแบบแฟ้ม debian/copyright ที่เครื่องแจงอ่านได้ และแฟ้มที่ขาดข้อมูลลิขสิทธิ์ ซึ่งบางส่วนต้องแก้ที่ต้นน้ำ ผมก็ทำเตรียมไว้
    • reproducible ตรวจพบการใช้ timestamp ขณะ build ซึ่งทำให้แพกเกจต่าง ๆ build หลายครั้งแล้วได้ checksum ไม่เท่ากัน ซึ่งทั้งหมดต้องแก้ที่ต้นน้ำ
    • Debian font review ซึ่งแสดงตัวอย่างฟอนต์จากแพกเกจฟอนต์ต่าง ๆ ใน Debian พร้อมผลลัพธ์จากโปรแกรม fontlint ที่ตรวจหาปัญหาต่าง ๆ ในฟอนต์ ทำให้ต้องมา validate ฟอนต์ที่ต้นน้ำทีละตัว ทำให้ได้แก้ปัญหาต่าง ๆ ในเส้นโค้งตัวอักษรของฟอนต์ เช่น การซ้อนทับกันของเส้น, การขาดจุด extrema, การระบุพิกัดของจุดแบบไม่ใช่จำนวนเต็ม, การใช้ชื่อ glyph ที่ไม่ตรงตามมาตรฐาน, ความผิดปกติของตาราง GPOS ฯลฯ แล้วก็เลยเถิดไปถึงการปรับเส้นอักษรแบบยกเครื่องในบางฟอนต์ ซึ่งส่งผลให้ได้เส้นที่คมชัดขึ้นเมื่อแสดงบนจอภาพ
    ประเด็นอื่นที่นอกเหนือจากที่ QA ตรวจพบ เช่น ปรับให้แพกเกจบางตัวที่สามารถใช้เอกสารใน /usr/share/doc ร่วมกันได้ทำเป็น symlink ถึงกัน ตาม Policy 12.3 วรรค 5 เพื่อลดขนาดติดตั้ง
  • งานปรับปรุงฟอนต์ในชุด fonts-tlwg ตามที่ได้รับข้อเสนอแนะจากคุณ Martin Hosken ซึ่งจะนำไปสู่การปรับปรุงการรองรับภาษาชาติพันธุ์ต่อไป
  • การแก้บั๊กใน libdatrie ตามที่มีผู้รายงานเข้ามาทางเมลลิงลิสต์

ขณะนี้ Jessie ก็ได้ออกไปแล้ว รอบการพัฒนาใหม่ของ Stretch ก็กำลังเริ่ม ก็คงใกล้ได้เวลาปล่อยของที่ทำสะสมไว้

ป้ายกำกับ: , , , , ,

11 กุมภาพันธ์ 2557

Thanks, and the November-January Diary

เร่งงานตามสัญญาโครงการอยู่หลายเดือน ไม่ได้เขียน blog จึงขอขอบคุณย้อนหลัง สำหรับผู้สนับสนุนงานพัฒนาของผมในเดือนพฤศจิกายน 2556 ถึงเดือนมกราคม 2557ที่ผ่านมาดังนี้ครับ:

ขออวยพรปีใหม่สากลและตรุษจีนย้อนหลังแด่ผู้สนับสนุนทุกท่าน ขอให้เจริญอายุ วรรณะ สุขะ พละ พร้อมทั้งมั่งมีศรีสุขครับ และที่สำคัญคือ 願源碼與你同在。[หงวงหง่วงแบ้อื่อลื่อตั่งต๋อ] May the Source be with you!

สามเดือนที่ผ่านมา นอกจากงานโครงการอักษรอีสานที่เป็นงานหลักแล้ว ก็มีงานพัฒนาอื่น ๆ เช่น

  • swath 0.5.2
    • แก้ปัญหา infinite loop ใน LaTeX filter ซึ่ง นิวตรอน รายงานมาทาง G+ (เป็น private share) พร้อมแพตช์แก้
    • แก้ปัญหาอักขระหายใน token ยาว ๆ ใน HTML filter ซึ่งคุณ Nicolas Brouard จากโครงการ ดีโมพีเดีย ได้พบขณะใช้ swath ช่วยเตรียมเอกสารฉบับพิมพ์ จากการใช้ base-64 encode รูปภาพในแท็ก <img src="data:image/png;base64,...> ซึ่งทำให้ token ยาวพอจะทำให้พบบั๊กได้ ถือเป็น use case ที่น่าสนใจมาก และทำให้รู้ว่ายังมีผู้ใช้ที่ใช้ HTML filter อยู่ ไม่ใช่แค่ LaTeX
    บั๊กทั้งสองนี้ เกิดจากความพยายามในการป้องกัน buffer overflow ใน swath 0.5.1 แต่แก้ไม่สมบูรณ์ (รุ่นก่อนหน้านั้นจะ segfault ในบั๊กหลังเลยทีเดียว ซึ่งเป็นช่องทางของ buffer overflow exploit ได้)
  • libdatrie 0.2.8
    • แก้ warning ใน test suite
    • แก้ปัญหาที่พบในการใช้ datrie เก็บคีย์ที่เป็นข้อมูล binary ซึ่งจะใช้ alphabet เต็มช่วงตั้งแต่ 1 ถึง 255 ทำให้พบปัญหาคีย์ซ้ำสำหรับอักขระ 255 อันเนื่องมาจากค่าสิ้นสุดการวนลูปที่ไม่ถูกต้อง รายงานโดยคุณ Naoki Youshinaga
    • แก้ให้ trie ล้มเหลวเมื่อเดินด้วยอักขระนอกช่วง alphabet แทนที่จะยอมให้อักขระดังกล่าวเดินได้ด้วยค่า 255 แล้วทำให้เกิดคีย์ปลอม ๆ ขึ้น แนะนำโดยคุณ Naoki Youshinaga เช่นกัน
    • เพิ่มเติมรายละเอียดในเอกสารประกอบ ตามที่ทักท้วงโดยคุณ Naoki Youshinaga
  • ปรับแพกเกจใน Debian โดยการเปลี่ยนแปลงที่น่าสนใจคือ
    • libdatrie-dev และ libthai-dev รองรับ multi-arch แล้ว หลังจากที่รองรับแค่ตัว lib package มาก่อนหน้านี้ ขณะนี้ dpkg รองรับการใช้แฟ้มร่วมกันระหว่างหลายแพกเกจแล้ว ทำให้สามารถใช้ header file ร่วมกันระหว่าง architecture ที่ต่างกันได้
    • รัน test suite ในการ build ทั้งใน libdatrie และ libthai ซึ่งทำให้พบ warning เพิ่มเติมใน libthai และแก้ที่ต้นน้ำแล้ว
  • ร่วมแปล VLC หลังจากพบคำสะกดผิดใน UI ก็ได้แปลเพิ่มเติมด้วยพอสมควร โดยเฉพาะชื่อภาษาต่าง ๆ ทำให้ได้ไปสอบทานกับคำแปล ISO 639 และ ISO 639-3 ในแพกเกจ iso-codes ควบคู่กันไปด้วย (ออกมาในรุ่น 3.50)
  • ตรวจทาน คำแปล GNOME ตามที่มีผู้ส่งคำแปลเข้ามา
  • งานแปล Xfce ขณะนี้แปลได้ 70% แล้ว

ป้ายกำกับ: , , , , , , ,

08 พฤศจิกายน 2556

Thanks, and the September-October Diary

ขอขอบคุณผู้สนับสนุนงานพัฒนาของผมในเดือนกันยายน-ตุลาคมที่ผ่านมาดังนี้ครับ:

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

งานในช่วงสองเดือนที่ผ่านมา แบ่งเป็นหมวด ๆ ดังนี้ครับ:

โครงการอักษรอีสาน

งานพัฒนาที่ LTN และ Debian

เป็นการปล่อยสิ่งที่พัฒนาสะสมมาตั้งแต่ระลอกที่แล้วเมื่อต้นปี โดยทยอยตรวจสอบความเรียบร้อยและออกรุ่นซอฟต์แวร์ต่าง ๆ ดังนี้:

  • libdatrie 0.2.7
    • แก้ไขประเด็นเรื่อง portability เกี่ยวกับ void pointer arithmatics ซึ่งจะมีปัญหากับคอมไพเลอร์ที่ไม่ใช่ GCC โดยได้รับรายงานจากคุณ Mikhail Korobov ว่าคุณ Gabi Daver ได้พบปัญหานี้ขณะคอมไพล์ด้วย Visual C++ พร้อมแพตช์แก้
    • ระหว่างแก้ ได้ทดลองคอมไพล์ด้วยตัวเลือก -Wall ทำให้เจอ warning เพิ่มเติม และแก้ไขจนหมด
    • เขียน test case เพื่อให้สามารถตรวจสอบความถูกต้องเวลาแก้โค้ดได้ในอนาคต ที่ผ่านมาจะทดสอบผ่าน libthai เป็นหลัก แต่เขียน test case เป็นเรื่องเป็นราวน่าจะสะดวกกว่า ซึ่งในระหว่างที่เขียน test case ก็ทำให้ได้อ่านเอกสารประกอบและแก้ไขที่ผิด พร้อมกับได้เพิ่ม API เพื่อความสะดวกในการใช้งานด้วย
    • ปรับ Doxyfile ที่ใช้สร้างเอกสาร เพื่อตัดสิ่งที่เลิกใช้แล้วใน doxygen 1.8.4
    • ออก libdatrie 0.2.7.1 ตามมา หลังจากพบว่าลืมปรับค่า library version เพื่อให้ SONAME สะท้อนการเพิ่ม API ที่เกิดขึ้น
    • อัปโหลด 0.2.7.1-1 เข้า Debian sid
  • thaixfonts 1.2.6
    • มีการปรับระบบ build ตาม autoconf รุ่นใหม่ และเปลี่ยนมาใช้ XZ tarball แทน GZ tarball ซึ่งเป็นสิ่งที่ทำไว้นานแล้ว ก็ออกรุ่นมาเพื่อปรับตามซอฟต์แวร์อื่นเท่านั้น ส่วนตัวเนื้อหาฟอนต์ไม่มีการเปลี่ยนแปลงอะไร
    • อัปโหลด 1:1.2.6-1 เข้า Debian sid
  • LibThai 0.1.20
    • ปรับข้อมูลพจนานุกรมตัดคำตามที่พบกรณีต่าง ๆ ในช่วงที่ผ่านมา [เกร็ด: รุ่นนี้รู้จักอำเภอขนอมที่ไม่ใช่ ขน-อม แล้ว ;-)]
    • แก้ compiler warning ที่พบใน test case ต่าง ๆ
    • อัปโหลด 0.1.20-1 เข้า Debian sid
  • TeX hyphenation patterns
    • sync ข้อมูลพจนานุกรมตัดคำจาก libthai เข้าไปที่ ThaiLaTeX SVN พร้อมกับปรับแก้ hyphenation patterns ตามข้อมูลใหม่
    • แจ้งไปที่โครงการ tex-hyphen ว่าขอปรับข้อมูล hyphenation patterns ภาษาไทย พร้อมกับรายงานปัญหาของสคริปต์บางตัวที่ใช้สร้างข้อมูลอัตโนมัติ คุณ Mojca Miklavec ก็ได้ช่วยแก้สคริปต์ให้ (rev 652, 653) และรับแพตช์ปรับข้อมูลภาษาไทยไปรวมให้ (rev 654)
    • สอบถามและขอ import source ของ hyphenation patterns ภาษาไทยเข้าใน tex-hyphen โดยตรง เพื่อที่ต่อไปจะได้ไปทำงานที่นั่นแทนที่จะต้องผ่าน ThaiLaTeX แบบนี้ ทั้งนี้เพื่อให้เป็นไปตามแผน ที่เคยคุยกันไว้ จนกระทั่งได้ import source ใน rev 655
    • ไม่มีการอัปโหลดอะไรใน Debian แค่รอ Debian อัปเดตแพกเกจ texlive-base เท่านั้น
    • request ขอลบ thailatex ออกจาก Debian unstable เพื่อไม่ให้มีซอร์สตกค้างอยู่ (ลบแล้ว)
  • swath 0.5.1
    • แก้รหัสตัดคำของ Lambda จาก U+200C (ZWNJ) เป็น U+200B (ZWSP) ...ว่าแต่มีใครใช้ฟีเจอร์นี้ไหมเนี่ย?
    • sync ข้อมูลพจนานุกรมตัดคำจาก ThaiLaTeX/hyph-utf8 (ซึ่ง sync มาจาก LibThai อีกที) เพื่อให้ตัวตัดคำ LaTeX ทำงานสอดคล้องกับ hyphenation patterns
    • ก่อนออกก็ปรับซอร์สโค้ดของ swath เพื่อให้แต่ละรุ่นมีการปรับปรุงด้านความปลอดภัยไปทีละน้อย โดยในรุ่นนี้ได้ป้องกัน buffer overflow ใน file filter ต่าง ๆ (ยังมีให้แก้อีกเยอะในรุ่นถัด ๆ ไป :-P )
    • อัปโหลด 0.5.1-1 เข้า Debian sid
  • IBus-LibThai 0.1.2
    • แก้ปัญหาการกด shortcut (เช่น Ctrl-C) ใน IBus 1.5 อันเนื่องมาจากการเชื่อมรวมกับ XKB ของ IBus รุ่นนี้ ทำให้ผังแป้นพิมพ์ที่ระบุใน metadata ของ IBus-LibThai ว่าเป็น th ทำให้กด Ctrl-C ได้เป็น Ctrl-แ เสมอ แก้ไขโดยปรับผังแป้นพิมพ์เป็น us เท่านั้น
    • อย่างไรก็ดี การแก้ปัญหาในรายการที่แล้วทำให้เกิดปัญหาใหม่ คือทำให้กด accelerator ใน GUI ที่แปลเป็นไทย (เช่น Alt-ฟ เพื่อเรียกเมนู แฟ้ม) ไม่ได้ วิธีแก้ที่เหมาะสมจึงควรให้ IBus-LibThai พยายามแปลง key event ที่มีการกดปุ่มประกอบให้เป็นภาษาไทย แต่ปรากฏว่าไม่สามารถส่ง event ที่แปลงแล้วกลับไปหา event queue ได้ เนื่องจากฟังก์ชัน ibus_engine_forward_key_event() ไม่ทำงานอย่างที่คาด งมอยู่นานก็ไม่สามารถแก้ได้ เวลามีจำกัดจึงใช้วิธีกำหนดผังแป้นพิมพ์เป็น us,th เพื่อให้ GTK+ กับ XKB ไปคุยกันเอง ซึ่งก็ได้ผล แต่ปัญหาคือ มันจะแปลงอักขระตามผังเกษมณีเท่านั้น ใครใช้ผังปัตตะโชติใน IBus-LibThai ก็จะงง ไว้หาวิธีแก้ต่อไปในรุ่นหน้า
    • เพิ่มการรองรับการป้อนเลขไทยด้วยแป้นตัวเลข โดยอาศัยการกด CapsLock ล็อคไว้ หรือใช้การยกแคร่ระดับ 3 (Alt ขวา) อนึ่ง ตามที่เคยได้ ออกแบบไว้ เมื่อสองปีก่อนนั้น จะใช้ ScrollLock ไม่ใช่ CapsLock เนื่องจาก CapsLock จะไปเพิ่มขั้นตอนขณะสลับภาษาไปเป็นภาษาอังกฤษที่จะต้องปลด CapsLock อีกขั้นหนึ่งด้วย แต่ในครั้งนี้ได้ตัดสินใจเปลี่ยนเป็น CapsLock ด้วยเหตุผลสองประการ ประการแรกคือการตรวจสอบสถานะของ ScrollLock ด้วย API ของ IBus เป็นไปได้ยาก เพราะไม่มีการเตรียมการรองรับไว้ ประการที่สองคือในแป้นพิมพ์ย่อส่วน เช่นแป้นพิมพ์โน้ตบุ๊ก หลายรุ่นได้ตัดปุ่ม ScrollLock ออกไปแล้ว ตามที่ วิกิพีเดียว่าไว้ (โน้ตบุ๊กผมก็ไม่มี)
    • อัปโหลด 0.1.2-1 เข้า Debian sid

งานแปล

  • ตรวจทาน คำแปล GNOME ตามที่มีผู้ส่งคำแปลเข้ามา โดยที่ผมไม่ได้แอคทีฟตามแปลเองอีกต่อไปแล้ว
  • แปล Xfce เป็นไทย เพิ่มเติม โดยล่าสุด ได้แปล core package ต่าง ๆ ครบแล้ว พร้อมกับปรับคำแปลทั้งหมดจาก master กลับไปที่ branch xfce-4.10 ด้วย และแปลปลั๊กอินที่ผมใช้อีกนิดหน่อยเพิ่มเติม ทำให้ขณะนี้อัตราการแปลของภาษาไทยอยู่ที่ 54% แล้ว

blog นี้ก็เลยยาวหน่อย ขอขอบคุณทุกท่านที่ติดตามครับ

ป้ายกำกับ: , , , , , , , , , ,

24 มกราคม 2556

libdatrie 0.2.6

ออก libdatrie 0.2.6 ไปแล้วเมื่อวานนี้ โดยเป็นรุ่นแรกและเป็น tarball แรกของ LTN ที่ ใช้การบีบอัดแบบ XZ ตามที่ได้ ซาวเสียง ในกลุ่มเมล

การเปลี่ยนแปลงหลัก ๆ ของรุ่นนี้ เป็นเรื่องการลิสต์รายการคำใน trie โดยได้รับความช่วยเหลือจาก Mikhail Korobov จากรัสเซีย ตามที่เคย blog ไปเมื่อเกือบ 6 เดือนที่แล้ว ถือว่าดองไว้นานมากเหมือนกัน เนื่องจากติดภารกิจต่าง ๆ

อัปโหลด 0.2.6-1 เข้าที่ Debian experimental แล้วครับ ไว้รอย้ายเข้า Sid หลังจากที่ Wheezy ออกแล้ว

ป้ายกำกับ:

07 สิงหาคม 2555

Libdatrie Python Binding and Improvements

ในบรรดาโครงการต้นน้ำที่ผมทำ libdatrie น่าจะนับได้ว่าเป็นโครงการที่ได้รับความช่วยเหลือจากผู้ใช้มากที่สุดแล้ว ซึ่งเกือบทั้งหมดเป็นชาวต่างประเทศ (ดูหลักฐานได้ใน blog ก่อน ๆ) เช่นในครั้งนี้มาจากคุณ Mikhail Korobov จากรัสเซีย

Mikhail ได้ทำ Python binding สำหรับ libdatrie (และได้เล่าถึง Ruby binding ของ Tyler McMullen นักพัฒนาอีกคนหนึ่งด้วย) ทำให้พบประเด็นต่าง ๆ ที่ต้องการปรับปรุงที่ต้นน้ำ จึงได้ติดต่อมาที่ผม จากการพูดคุยแลกแพตช์กันทางอีเมล ก็ทำให้ libdatrie ใน SVN ได้รับการปรับปรุงหลายรายการ ที่ผ่านมาก็มีดังนี้:

  • แก้ปัญหาการคอมไพล์ด้วย MSVC ไม่ผ่าน
  • แก้ที่ผิดในเอกสารประกอบฟังก์ชัน
  • แก้บั๊กของบางฟังก์ชันที่พบระหว่างพูดคุยถึงอาการต่าง ๆ ที่เขาพบ
  • เพิ่ม API ใหม่สำหรับลิสต์รายการคำใน trie เพื่อใช้ใน Python binding เนื่องจาก API เดิมที่ใช้ callback function ไม่ยืดหยุ่นพอ จึงได้เพิ่มคลาส TrieIterator เพื่อให้โค้ดผู้เรียกสามารถควบคุม control flow เองได้มากขึ้น
  • optimize การลิสต์รายการคำ โดย Mikhail ได้เสนอให้คำนวณคีย์แบบ incremental และลดปริมาณการ malloc ซึ่งปรากฏว่าวิธีใหม่นี้ทำงานได้เร็วขึ้นกว่าเดิมประมาณ 10% และเมื่อปรับฟังก์ชันแบบที่เรียก callback แบบเดิมมาใช้ TrieIterator แทนการเรียกตัวเอง ยังทำให้ลดการใช้สแต็กลงไปได้อีกมาก
  • ปรับปรุงการคำนวณช่วงอักขระในคลาส AlphaMap ที่ใช้แปลงไปมาระหว่างอักขระภายนอกกับรหัส 8 บิตที่ใช้เดินไปใน trie ทำให้ได้ map ที่กระชับและประหยัดเวลาในการ map มากขึ้นในกรณีที่ผู้เรียกเพิ่มช่วงอักขระเล็ก ๆ หลายช่วง หรือแม้แต่เพิ่มอักขระทีละตัว

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

distro ทั่วไปที่มอง libdatrie ผ่าน application อย่าง libthai หรือ swath อาจจะเห็นเป็นแค่ไลบรารีเล็ก ๆ ที่ไม่มีความสำคัญ แต่สำหรับคนทำงานเรื่อง information retrieval หรือ NLP แล้ว libdatrie ได้พิสูจน์ตัวเองในระดับหนึ่งว่ามีประโยชน์พอสมควร จนกลายเป็นโครงการที่ให้ประสบการณ์แบบโอเพนซอร์สกับผมมากที่สุดในบรรดาโครงการทั้งหลายที่ทำมา

นอกจากแหล่งอย่าง Debian หรือ Ubuntu แล้ว คงต้องยกเครดิตให้กับ Wikipedia ที่ทำให้โครงการนี้เป็นที่รู้จัก

สำหรับฟีเจอร์ต่าง ๆ ที่ว่าไป รอพบได้ใน libdatrie รุ่นหน้าครับ ซึ่งยังไม่มีกำหนดออกรุ่นแน่นอน และหลังจากออกแล้ว ก็คงยังไม่ได้เข้า Debian Wheezy เนื่องจาก freeze ไปแล้ว ถ้าจะเข้า Debian ก็คงไปพักไว้ที่ experimental ก่อน

ป้ายกำกับ:

25 กันยายน 2553

Double-Array Trie Has Got Java Implementation

ไม่ใช่ผมทำเองหรอกครับ แต่ได้รับแจ้งจากคุณ Chris Gioran นักพัฒนาชาวกรีก ว่าได้พัฒนา double-array trie ในฉบับ Java แล้ว โดยโฮสต์ไว้ที่ github โดยอาศัยหลักการจากหน้าเว็บที่ผมเขียนไว้ สัญญาอนุญาตที่ใช้ เป็น LGPL เหมือน libdatrie ครับ

รายละเอียด มีบันทึกไว้ใน blog ของเขา

ภูมิใจจังที่ได้เขียนเอกสารฉบับนี้ไว้ และได้รู้ว่ามันมีประโยชน์ในที่ต่าง ๆ ตามที่ได้เคยบอกกล่าวมาบ้างแล้ว ว่าผู้ใช้ประโยชน์ต่อยอดส่วนใหญ่เป็นชาวต่างประเทศ มีบางครั้งได้พบชาวต่างประเทศแล้วเขาบอกว่าจำชื่อผมได้จากเว็บ double-array trie ก็รู้สึกอิ่มอกอิ่มใจ ว่างานเล็ก ๆ จากประเทศเล็ก ๆ ชิ้นนี้ก็มีประโยชน์กับเขาบ้างเหมือนกัน

ป้ายกำกับ: ,

30 มิถุนายน 2553

libdatrie 0.2.4

ออก libdatrie 0.2.4 ไปแล้วเมื่อกลางวัน รุ่นนี้มีการเพิ่ม API ใหม่เข้ามา ตามคำแนะนำของผู้ใช้

ก็ตามปกติครับ ดูเหมือนผู้ใช้ส่วนใหญ่ของ libdatrie จะเป็นนักพัฒนาชาวต่างประเทศ ความคิดเห็นส่วนใหญ่ที่ผ่านมาจะได้จากชาวต่างประเทศมากกว่าคนไทย สำหรับรุ่นนี้ ความเปลี่ยนแปลงคือ:

  • แก้บั๊กลืมปิดแฟ้มในฟังก์ชัน trie_save() รายงานโดย Xu Jiandong (แซ่เดียวกับผมนะนี่)
  • เพิ่ม API trie_store_if_absent() ซึ่งจะเก็บค่าลงใน trie เฉพาะเมื่อไม่มีคำเดิมอยู่ใน trie เท่านั้น ถ้ามีอยู่แล้วก็จะคืนสถานะล้มเหลวกลับมา ซึ่งจะมีประโยชน์สำหรับโปรแกรมแบบหลายเธรด เพราะถ้าเขียนทับจะเกิด race condition ได้ เรื่องนี้เสนอแนะโดย Dan Searle จากสหราชอาณาจักร
  • เพิ่ม API trie_fread() และ trie_fwrite() สำหรับอ่าน/เขียนข้อมูล trie จากแฟ้มที่เปิดไว้ โดยไม่ปิดแฟ้มหลังทำเสร็จ ตรงนี้จะมีประโยชน์สำหรับโปรแกรมที่ต้องการเก็บข้อมูล trie รวมอยู่ในแฟ้มเดียวกับข้อมูลส่วนอื่น โดยทำให้อ่าน/เขียนข้อมูลเฉพาะส่วน trie แล้วย้อนกลับไปให้โปรแกรมอ่าน/เขียนข้อมูลส่วนอื่นต่อได้ ซึ่งก็ดูจะเป็นอีกขั้นของการรวมข้อมูล หลังจากที่ผมจับข้อมูล double-array กับ tail มารวมเข้าในแฟ้มเดียวไปแล้วตั้งแต่ 0.2.0 เสนอแนะโดย NIIBE Yutaka ซึ่งเป็น DD จากญี่ปุ่น

อัปโหลดแพกเกจเข้า Debian เรียบร้อยแล้วครับ

อีกแพกเกจหนึ่งใน Debian ที่มีการเปลี่ยนแปลงคือ scim-thai โดยแก้ปัญหา FTBFS อันเนื่องมาจากรุ่นของ gettext ที่ใช้ตอนออกรุ่นต้นน้ำนั้นเก่ากว่ารุ่นของแมโครที่ aclocal เตรียมให้ขณะ build (Debian #584394)

ป้ายกำกับ: ,

28 กุมภาพันธ์ 2553

Hardening LibThai

หลังจากผ่าน security update มาแล้ว ก็มีรายการแก้ไขเพิ่มเติมอีกนิดหน่อยจาก การตรวจสอบของทีม RedHat ซึ่งละเอียดน่าประทับใจมาก ก็เป็นการอุดช่องเล็ก ๆ น้อย ๆ เพิ่มเติม พร้อมกับพบ บั๊กใน glib เพิ่มเติมด้วย

แต่อีกประเด็นหนึ่งที่ได้แก้เพิ่ม คืออาการพังที่เคยได้รับรายงานมาหลายครั้งแล้ว แต่ทำซ้ำใหม่ไม่ได้สักที จนกระทั่งมาเจอกรณีที่น่าจะใกล้เคียงที่สุด คือ Debian #569996 ซึ่งพบว่า iceweasel, gedit จะพังถ้าแสดงภาษาไทยโดยแฟ้มพจนานุกรมตัดคำของ libthai เสียหายอยู่

ในบั๊กนั้น ได้ให้ผู้ใช้แก้ปัญหาไปแล้วด้วยการ reinstall libthai-data แต่หลังจากปิดบั๊กไปก็รู้สึกว่าควรจะให้ libthai ยืดหยุ่นกว่านี้ ถ้าพจนานุกรมเสียหายก็ไม่ควรจะพังไปเลย แต่ควรจะแค่ไม่ตัดคำให้เท่านั้น ว่าแล้วก็เข้าไปปรับปรุงส่วน error handling ใน libdatrie และ libthai ตามนั้น

อีกส่วนหนึ่ง ได้รับแจ้งจาก Behdad จาก RedHat ว่าซอร์สโค้ด libthai ไม่ได้แปะสัญญาอนุญาตไว้ที่แฟ้มซอร์สแต่ละแฟ้ม ซึ่งเป็นวิธีที่ชัดเจนที่สุดในการใช้ LGPL ก็เลยแก้เพิ่มด้วยทั้งใน libdatrie และ libthai โดยได้ถือโอกาสจัดแต่งซอร์สโค้ดไปในตัวด้วย

ผลก็คือ libdatrie 0.2.3 และ libthai 0.1.14 ที่ออกไปเมื่อวานและวันนี้ตามลำดับครับ พบได้ใน Debian mirror ใกล้บ้านท่าน

ป้ายกำกับ: , , , , , , , ,

18 เมษายน 2552

Songkran Updates

ความคืบหน้าต่าง ๆ ในช่วงสงกรานต์ที่ผ่านมา:

  • แพตช์สำหรับ Xlib ที่เคยเขียนถึงใน blog เก่า ได้ check-in หมดแล้วที่ upstream ด้วยความช่วยเหลือของ Julien Cristau ผู้ดูแลแพกเกจ libx11 ของ Debian ตามที่เคย blog ไว้ ว่าเขาเสนอจะผลักดันเข้า upstream ให้ เป็นอีกครั้งหนึ่งที่ทำให้ชอบในสไตล์การทำงานของ Debian ที่พยายามทำงานร่วมกับ upstream ให้มากที่สุด สไตล์นี้มีให้พบเห็นที่ Ubuntu บ้าง แต่น้อยครั้ง ส่วนใหญ่จะรับแพตช์เร็ว แต่ไม่ค่อยช่วยผลักดันเข้า upstream แต่ก็ถือว่าเป็นประโยชน์ในแง่ที่ทำให้ผู้ใช้ได้ช่วยทดสอบเร็วขึ้น
  • ในระหว่างนั้น พบว่า xchat-gnome พัง เรียกไม่ขึ้น โดยมีสาเหตุมาจากคำแปลไทย ก็เลยแก้และ commit เข้า SVN พร้อมได้รายงาน Debian #523739 เอาไว้ด้วย ใครเจอปัญหานี้ก็ไปดูได้ครับ หรือรอรุ่น 0.26.1 ซึ่งรวมรายการแก้นี้แล้วก็ได้
  • ตาม แผนการ migrate libthai ใน Debian ตอนนี้ค่อนข้างเสร็จสมบูรณ์แล้วใน unstable รวมทั้ง binNMU ต่าง ๆ ที่ทำให้ตอนนี้ libdatrie0 ไม่มี reverse dependency เหลืออยู่อีกแล้ว ที่เหลือก็รอให้ผ่านเข้า testing ก่อนที่จะปรับแก้ระบบ build ของ libdatrie ต่อไป
  • swath 0.4.0 ก็เข้าสู่ unstable แล้วเช่นกัน
  • จากที่ได้รับรายงานเรื่องปัญหาการ build libdatrie ในระบบต่าง ๆ เช่น Mac, MinGW หรือแม้แต่ Linux distro ด้วยกันที่ไม่ใช่ Debian อย่าง Fedora ก็ได้ทยอยแก้ไปทีละเรื่อง โดยได้รับข้อมูลเบื้องต้นเกี่ยวกับ Mac จากคุณ bact' ผ่าน twitter และได้รับความช่วยเหลือจากคุณ cwt เกี่ยวกับ Fedora และ Mac ทางห้อง #tlwg, คุณ kengggg เกี่ยวกับ Mac ผ่านเมลลิงลิสต์ thai-linux-foss-devel, คุณ Beamer User และคุณ Sudchai เกี่ยวกับ cygwin และ MinGW ผ่านความเห็นใน blog ตอนนี้น่าจะถือได้ว่าตัว libdatrie เองผ่านในทุกระบบแล้ว ต่อไปก็เหลือตรวจสอบการ build แพกเกจที่ใช้ libdatrie คือ libthai และ swath ในแพลตฟอร์มต่าง ๆ ว่ายังมีปัญหาต้องแก้อีกไหม ก่อนที่จะออก libdatrie ตัวใหม่ต่อไป

นอกจากความคืบหน้าดังกล่าว ก็ปรากฏว่าพบปัญหาเล็กน้อยเกี่ยวกับการ migrate libthai ใน Debian โดยแม้จะมีการ upload libthai ที่ตัด link flag รอไว้แล้วใน unstable ตามที่อธิบายไว้ใน blog ก่อน ก็ปรากฏว่า pango ยังคงลิงก์ตรงกับ libdatrie0 อยู่ดี

ตรงนี้ตัวการยังคงอยู่ที่ libthai.la เจ้าปัญหาตัวเดิม คือแม้ผมจะไปแก้ libthai.pc ให้ประกาศ require datrie แบบ private แล้ว และเมื่อสั่ง 'pkg-config --libs libthai' ดูก็ไม่พบ -ldatrie ในผลลัพธ์แล้วก็ตาม แต่สุดท้าย pango ที่ build ออกมาก็ยังคงลิงก์ตรงกับ libdatrie0 อยู่ดี ทั้งนี้เพราะการติดตั้ง libthai.la ทำให้ระบบ build ของ pango ซึ่งใช้ libtool มันไปเจอไฟล์นี้ แล้วก็ไปลากเอา -ldatrie ตามที่ระบุในไฟล์นี้มาให้อยู่ดี..

แม้อยากจะตัดไฟล์นี้ออกเสียก็ยังทำไม่ได้ในตอนนี้ ในเมื่อ kdelibs 3 ยังคงอยู่ใน Debian ก็เลยต้อง hack ด้วยการแอบลบข้อมูล dependency_libs ออก ซึ่งก็ทำให้ -ldatrie ถูกตัดออกไปจากการ build ของ pango ได้ โดยคาดว่าคงไม่กระทบกับการทำงานของ kdelibs 3

ปัญหานี้ไม่ซีเรียสกับผู้ใช้ เพราะ symbol versioning ได้ช่วยป้องกันการพังเพราะ symbol ชนกันไปแล้ว แต่ปรากฏว่ามีเรื่องที่คาดไม่ถึง คือได้สร้างปัญหาให้กับระบบ buildd ของ Debian อยู่ระยะหนึ่ง เพราะการที่ pango ยังคงลิงก์ตรงกับ libdatrie0 ในระหว่างที่ผมได้ update libdatrie เป็น libdatrie1 ซึ่งทำให้ libdatrie0 หายไปจาก archive นั้น การ build ที่ buildd ที่เกี่ยวข้องกับ pango มีอันเจ๊งไปหมด เพราะ buildd chroot ทั้งหลายไม่สามารถดาวน์โหลด pango มาติดตั้งได้เนื่องจากขาด dependency คือ libdatrie0 ไป ตรงนี้ผมไม่รู้ตัวจนกระทั่งได้ไปติดต่อขอ binNMU กับ release team เขาถึงได้เล่าให้ฟัง..

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

และอีกเรื่องหนึ่งคือ.. รอให้ KDE 3 obsolete ใน Debian เร็ว ๆ จะได้ปลดเปลื้องภาระความปวดหัวกับ libthai.la นี่เสียที

ป้ายกำกับ: , , ,

09 เมษายน 2552

swath 0.4.0 in experimental

ต่อจาก blog ที่แล้ว ตอนนี้ swath 0.4.0 ก็เข้าไปอยู่ใน Debian experimental เรียบร้อยแล้วเช่นกัน

swath รุ่นนี้ นอกจากการเปลี่ยนมาใช้ libdatrie 0.2 ก็มีการเปลี่ยนแปลงย่อย ๆ ตามปกติ โดยคราวนี้ได้ทรมาน swath ด้วย valgrind คล้ายกับที่ เคยทำกับ libthai เพียงแต่ไม่ได้ล้วงลึกลงไปแก้อะไรมากนัก เนื่องจาก swath ไม่ใช่โค้ดของผมเอง (แต่เป็นของ คุณไพศาล ทำไว้) ยังไม่มั่นใจพอที่จะแก้อะไรใหญ่โต

แต่ก็โชคดีที่สิ่งผิดปกติที่ valgrind ตรวจพบ ไม่ได้แก้ยากเกินไป โดยที่ได้แก้ไปก็ได้แก่:

  • หน่วยความจำรั่ว 1 จุด
  • การใช้ new[] กับ delete[] ที่ไม่เข้าคู่กัน
  • การใช้ strcpy() กับสตริงที่ซ้อนทับกัน
  • การ branch โดยอาศัยค่าที่ไม่ได้กำหนดค่าเริ่มต้นไว้

มีรายการสุดท้ายที่ผมยังไม่มั่นใจพอที่จะแก้หนึ่งรายการ เนื่องจากทำให้ผลลัพธ์การตัดคำเปลี่ยนไป เลยทิ้งไว้ก่อน เป็นเรื่องของการ branch โดยอาศัยค่าที่ไม่ได้กำหนดค่าเริ่มต้นไว้

เป็นอันว่า เราได้ swath ที่สามารถปรับพจนานุกรมได้ละ ไว้เดี๋ยวรอย้าย libdatrie1 จาก experimental เข้า unstable ก่อน แล้วจึงย้าย swath ตามมา ระหว่างนี้ ใครสนใจทดสอบก็ลองได้จาก experimental ครับผม

ป้ายกำกับ: ,

07 เมษายน 2552

libthai 0.1.11 ready in experimental

ตาม แผนการ migrate libthai ที่ได้วางไว้ ตอนนี้มีความคืบหน้าเล็กน้อย

หลังจากที่ได้เตรียม libdatrie 0.1.4 ใน debian unstable ไว้แล้ว ก็ออก libdatrie 0.2.1 และ libthai 0.1.11 ตามมา พร้อมกับ upload แพกเกจทั้งสองเข้าใน debian experimental เรียบร้อย โดยการ upload ทั้งหมด ก็เป็นการเพิ่ม symbol versioning ทั้งใน libdatrie0 และ libdatrie1 ก็เป็นอันว่าสามารถปรับรุ่น libthai จาก unstable เป็นรุ่นใน experimental ได้โดยไม่มีปัญหาโปรแกรมพังอีกต่อไป

ต่อไปก็รอ libdatrie 0.1.4 ย้ายเข้า testing (เพื่อเตรียมการปรับรุ่นสำหรับผู้ใช้ testing ด้วย) ซึ่งเหลือเวลาอีก 4 วันสำหรับรอรายงานบั๊กใน unstable ถ้าไม่มีอะไรผิดพลาดก็คงได้เข้า testing ในวันที่ 11-12 เม.ย. จากนั้นจึงเริ่มย้ายแพกเกจใน experimental เข้า unstable ได้

ก่อนหน้านี้ ผมได้ upload scim-thai และ gtk-im-libthai ซึ่ง build กับ libthai-dev 0.1.9-5 ใน unstable ไปแล้ว ซึ่งเป็นการตัดการลิงก์ตรงกับ libdatrie0 ออก โดยพร้อมกันนี้ก็ถือโอกาสตัดการลิงก์ตรงกับไลบรารีอื่นที่ไม่จำเป็นที่ GTK+ ไปดึงมาให้ด้วย เช่น libatk, libfreetype, libcairo ฯลฯ ทำให้ dependency ลดลงไปเยอะ แต่การตัดการลิงก์ตรงกับ libdatrie0 ก็เป็นการลดความเสี่ยงต่อการพังลงทางหนึ่ง แต่ทั้งนี้ทั้งนั้น pango language engine ภาษาไทย รวมทั้ง libm17n-0 ยังคงลิงก์ตรงกับ libdatrie0 อยู่ ดังนั้น libdatrie0 0.1.4 ที่มาช่วยแยกรุ่นของ symbol ก็ยังคงจำเป็น

ในระหว่างนี้ ถ้าใครอยากช่วยทดสอบ libthai ใน experimental ก็สามารถเริ่มทำได้นะครับ ตอนนี้ไม่ทำโปรแกรมพังแล้ว ผมเองก็กำลังใช้อยู่ เพื่อทดสอบการใช้งาน หรือจะรอใช้ใน unstable หรือ testing เพื่อความปลอดภัย ก็ไม่มีปัญหาครับ ส่วนผู้ใช้ Ubuntu ก็คงรอใช้ใน karmic ได้หลังจากนั้น

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

อีกโปรแกรมหนึ่งที่กำลังจะได้อานิสงส์จาก libdatrie ตัวใหม่ ก็คือ swath ซึ่งใน SVN ได้ปรับมาใช้ libdatrie ตัวใหม่แล้ว ทำให้สามารถปรับพจนานุกรมสำหรับตัดคำได้ ตอนนี้กำลังอยู่ระหว่างเก็บกวาดโค้ดเพื่อเตรียมออกรุ่นใหม่

ป้ายกำกับ: , , ,

01 เมษายน 2552

libthai/libdatrie Migration in Debian

ระหว่างนี้ยังคงอยู่ในช่วงเคลียร์ TODO list ต่อไป โดยหลังจาก file bug เกี่ยวกับ X locale และ Pango ไปแล้ว ก็มาที่เรื่องของ libthai ซึ่งต้องทำหลายขั้นตอน ระหว่างที่ต้องหยุดรอกระบวนการ ก็สลับไปหยิบเรื่องการ update แพกเกจภาษาไทยใน Debian มาทำไปพลาง ๆ แล้วก็แวะมาที่เรื่อง ฟอนต์ นิดหน่อย ส่วนเรื่องบั๊กความกว้างของตัวเลขอารบิกในฟอนต์ที่ว่าจะทำนั้น ดูแล้ว เป็นปัญหาเกี่ยวกับ hinting ซึ่งจะกินเวลานานเกินไป เลยข้ามไปก่อน เมื่อรายการที่รอผ่านแล้ว ก็เลยกลับมาดูเรื่อง libthai ต่อ

เรื่องของ libthai ก็เริ่มจากการ ออก libdatrie 0.2.0 ที่ ทำค้างไว้ และก่อนที่จะออก libthai ตามมา ก็ upload libdatrie เข้า Debian experimental ก่อน เพื่อทดสอบความเรียบร้อยให้แน่ใจ แต่เนื่องจากรุ่นนี้มีการเปลี่ยน SONAME ของไลบรารี จาก libdatrie.so.0 เป็น libdatrie.so.1 ทำให้มีแพกเกจไบนารีตัวใหม่ คือ libdatrie1 และอื่น ๆ ก็เลยต้องไปผ่านการตรวจสอบใน NEW queue ของ Debian ก่อน เลยเป็นช่วงให้หยุดรอไปทำอย่างอื่นไปพลางอย่างที่ว่าไป

เมื่อผ่านแล้ว ก็มา ออก libthai 0.1.10 ที่ใช้ libdatrie ตัวใหม่ แล้วอัปโหลดเข้า Debian experimental ตามเข้าไป ซึ่งปรากฏว่าเจอตอเข้าให้ เกี่ยวกับเรื่องการ upgrade ไลบรารีข้ามรุ่น SONAME ใครที่เคยอ่านพบใน Debian New Maintainer's Guide แล้วไม่เข้าใจ ว่าทำไมเขาแนะนำ new maintainer ว่าไม่ควรเริ่มจากแพกเกจที่เป็นไลบรารี ก็ขอให้เชื่อเถอะ ว่าเป็นคำแนะนำที่ควรแก่การรับฟังอย่างยิ่ง

ถ้าผมสาธยายรายละเอียดปลีกย่อยเกี่ยวกับไลบรารีที่พบมาทั้งหมด blog ก็คงจะยาวจนไม่ได้เขียนบันทึกที่ตั้งใจจะเขียน ก็ขอข้ามมาที่ปัญหาที่พบในครั้งนี้เลยละกัน

ปัญหาที่พบในครั้งนี้ พอสรุปได้ 2 ประเด็นใหญ่ ๆ

  1. ปัญหาการจัดการการเปลี่ยนแปลง ABI ที่ไม่เข้ากับของเดิม
  2. ปัญหาของ transitive dependency

อาการเป็นดังนี้:

  • client ที่ลิงก์กับ libthai (เช่น Thai language engine ใน Pango) ไปลิงก์กับ libdatrie ไว้ด้วย ผ่านค่า "-lthai -ldatrie" ใน pkg-config ดังนั้น language engine นั้นจึงลิงก์กับ libdatrie 2 ชุด ลิงก์โดยตรงขณะคอมไพล์ชุดหนึ่ง และลิงก์ผ่าน libthai อีกชุดหนึ่ง
  • เมื่อ libthai มีการปรับรุ่น โดยรุ่นใหม่ไปลิงก์กับ libdatrie1 ในขณะที่ client ยังคงลิงก์กับ libdatrie0 อยู่ เมื่อโหลดขึ้นมาทำงาน จึงกลายเป็นโหลด libdatrie ขึ้นมา 2 รุ่นพร้อมกัน คือ libdatrie0 และ libdatrie1
  • เนื่องจากมีการเปลี่ยนแปลง ABI ที่ไม่เข้ากับของเดิม โดยที่ไม่ได้จัดการเรื่อง symbol ให้ดี ไลบรารีทั้งสองชุดจึงมี symbol ซ้ำกัน แต่ทำงานไม่เหมือนกัน จะเรียกได้ตัวเก่าหรือตัวใหม่ก็สุดแท้แต่ linker จะบังเอิญไปหยิบตัวไหนมาให้
  • ผลคือ โปรแกรมทำงานเพี้ยน หรือบางครั้งก็ segfault ไปเลย

ปัญหานี้ ถ้าสามารถโละทุกอย่างที่เกี่ยวข้องทิ้งแล้วคอมไพล์ใหม่หมดจาก libdatrie ตัวใหม่ ก็จะแก้ปัญหาได้ แต่คุณก็รู้ ว่ามันเป็นไปได้ยากสำหรับ distro ขนาดใหญ่อย่าง Debian โดยเฉพาะเมื่อการเปลี่ยนแปลงมาจากแพกเกจเล็ก ๆ ที่มีผลแค่กับภาษาไทยภาษาเดียว (หรือแม้แต่ถ้าคุณคอมไพล์ทุกอย่างจากซอร์สเอง การคอมไพล์ระบบใหม่หมดก็ไม่ใช่เรื่องสนุก) ดังนั้น การจัดการการปรับรุ่นของไลบรารีจึงมีความละเอียดอ่อนค่อนข้างมาก

ได้สรุปไปแล้วข้างต้น ว่าปัญหามีสองประเด็นหลัก ขอเล่าประเด็นหลังก่อน

Transitive Dependency เป็นปัญหาที่ไม่น่าจะเกิด สำหรับโปรแกรมที่ลิงก์กับ shared library ไม่ใช่ลิงก์แบบ static กล่าวคือ ถ้า client ของ libthai ไม่ได้เรียกใช้อะไรใน libdatrie เลย ก็ไม่ควรต้องลิงก์กับ libdatrie โดยตรง ปล่อยให้ libthai ลิงก์ไปคนเดียวก็พอแล้ว จากนั้น เมื่อมีการปรับรุ่น libthai ก็จะไม่กระทบกับ libdatrie อีก

เรื่องนี้เป็นความบกพร่องของผมเองที่ไม่ระวังเรื่อง link flag ของ libthai โดยแม้จะพยายามหลีกเลี่ยง libtool มาใช้ pkg-config แล้ว ก็ยังคงติดแฟล็ก '-ldatrie' มาในแฟ้ม pkg-config ของ libthai อยู่ กล่าวคือ ถ้าเป็นลิงก์โปรแกรมผ่าน *.la ที่สร้างโดย libtool นั้น มันจะไปดึงเอา dependency ของไลบรารีมาลิงก์ตรงหมด (เป็นสาเหตุหนึ่งที่ Debian และดิสโทรอื่นบางดิสโทรพยายามจะกำจัดแฟ้ม *.la ออกจากระบบให้หมด แต่ของ libthai ยังต้องคงไว้ เพื่อให้ kdelibs 3.x ใช้โดยเฉพาะ แต่ก็ไม่ได้มีผลอะไรกับระบบการลิงก์ เพราะ libthai ใช้ pkg-config เป็นหลัก) ในขณะที่การใช้ pkg-config จะสามารถแยก dependency ที่เป็น private ออกจาก public ได้ แต่พอมาใช้ pkg-config แล้ว ผมก็ยังเข้าใจผิดว่าการลิงก์นั้นยังต้องใช้ link flag เหมือน libtool ซึ่งไม่จำเป็นเลย

ดังนั้น ถ้าก่อนหน้านี้ ผมประกาศให้ libdatrie เป็นรายการ requires แบบ private ในแฟ้ม libthai.pc ก็จะไม่เกิดการลิงก์ client กับ libdatrie โดยตรงเป็นจุดที่สอง นอกเหนือจากผ่าน libthai และปัญหา ABI นี้ก็จะไม่เกิดขึ้นเลย

ปัญหานี้ Loic Minier ซึ่งเคยเป็น sponsor ให้กับแพกเกจ libthai ของผมได้ชี้ให้เห็น เขาไม่ได้พูดละเอียดขนาดนี้หรอก ผมเรียบเรียงและอธิบายเพิ่มเติมเพื่อให้เข้าใจง่ายเข้าน่ะ

แต่ผมกลับไปแก้ไขอดีตไม่ได้ ได้แต่กำจัด flag นั้นเพื่อลดรายการ dependency และการโหลดไลบรารีลงในอนาคต แล้วก็มาแก้ปัญหา ABI ที่พบอยู่ตรงหน้านี้

Incompatible ABI Change จาก libdatrie0 เป็น libdatrie1 มีการเปลี่ยนแปลง API โดยมีชื่อฟังก์ชันซ้ำกับของเดิมบางส่วน ดังนั้น เมื่อถูกโหลดขึ้นมาพร้อมกันโดยไม่มีการจัดการแยกแยะ symbol แบบนี้ loader จึง resolve symbol มั่ว แต่ปัญหานี้สามารถเลี่ยงได้ ด้วยการทำ symbol versioning ซึ่งพูดง่าย ๆ ก็เป็นเหมือนการใส่ namespace ให้กับแต่ละ symbol นั่นเอง โดยแยกแยะ ABI เป็นรุ่น ๆ ทับซ้อนกันได้ วิธีนี้มีข้อแม้ว่าไลบรารีจะต้องลิงก์ตรงกับ client เท่านั้น จะไม่มีผลต่อการโหลดผ่าน dlopen เพราะข้อมูล version ในการเรียก จะรู้ได้ในขณะลิงก์เท่านั้น ส่วนถ้าผ่าน dlopen การเรียกก็จะไม่มีการระบุ version

แต่กรณีของเรา libthai ก็ลิงก์ตรงกับ libdatrie อยู่แล้ว สามารถนำมาใช้แก้ปัญหาได้ โดยผมต้องกลับไปใส่ symbol version ใน libdatrie ตัวเก่า แล้ว ออก libdatrie 0.1.4 เพื่อ upload เข้า unstable รอไว้ก่อน พร้อมกันนั้นก็ใส่ symbol version ให้กับ libdatrie ใน experimental ไว้ด้วย เมื่อ libthai ตัวใหม่ย้ายจาก experimental เข้า unstable จึงจะไม่เกิดปัญหาชื่อชนกัน ซึ่งกว่าผมจะย้ายมาได้ ก็ต้องรอให้ libdatrie 0.1.4 ย้ายเข้าไปถึง testing เสียก่อน (ใช้เวลาประมาณ 10 วัน) เพื่อให้ผู้ใช้ testing สามารถ upgrade ได้โดยไม่สะดุดเหมือนกัน

เรื่องการทำ symbol versioning นี้ Josselin Mouette เป็นคนชี้ให้เห็น แต่ความรู้พื้นฐานเกี่ยวกับ symbol versioning ที่ทำให้เข้าใจในสิ่งที่เขาบอก ก็ต้องขอบคุณ Martin Wuertele ซึ่งเป็น Application Manager ในกระบวนการสมัครเป็น Debian Developer ของผม เพราะข้อสอบภาคทฤษฎีของเขา ทำให้ผมไปค้นคว้าจนได้ความรู้ประดับสมองรอไว้ ตอนนี้ก็ได้เวลางัดออกมาใช้ในภาคสนามละ

จากเงื่อนไขต่าง ๆ ที่เล่ามา แผนการโดยสรุปของผมจึงเป็นขั้น ๆ ดังนี้:

  1. update libthai ใน unstable (0.1.9-5) เพื่อตัด link flag '-ldatrie' ออก รอไว้ ในระหว่างนี้ ถ้าแพกเกจไหนที่ลิงก์กับ libthai มีการ build เกิดขึ้น ก็จะตัดลิงก์ตรงกับ libdatrie0 ออกไป เลี่ยงปัญหาการพังไปโสดหนึ่ง หรืออย่างน้อยก็ตัดการโหลดไลบรารีที่ไม่จำเป็นออกไปหนึ่งรายการ แต่ถ้ายังมีใครไม่ build ก็ไม่เป็นไร ยังมีก๊อกสอง
  2. update libdatrie0 ใน unstable (0.1.4-1) ซึ่งเพิ่ม symbol version รอไว้ เพื่อที่เมื่อ libthai ตัวใหม่ย้ายเข้า unstable แล้ว จะไม่เกิดการชนของ symbol และต้องรอให้แพกเกจนี้ย้ายเข้าไปถึง testing เสียก่อนด้วย จึงจะดำเนินการขั้นต่อไปได้
  3. ออก libdatrie1 ตัวใหม่ที่มี symbol version และ upload เข้า experimental
  4. update libthai ใน experimental อีกครั้ง โดยลิงก์กับ libdatrie1 ที่มี symbol version พร้อมกับตัด link flag เหมือนที่ทำใน unstable ด้วย นอกจากนี้ จากที่ Josselin ได้ท้วงว่าอาจมีปัญหากับการ upgrade เพียงบางส่วนจาก lenny ที่ยังใช้ libdatrie0 ตัวเก่า จึงควรเพิ่ม versioned conflict กับ libdatrie0 (<< 0.1.4) ด้วย
  5. เมื่อถึงเวลาอันควร (ซึ่ง Josselin บอกว่า น่าจะเป็นหลัง GNOME 2.26 migration ล็อตใหญ่ที่กำลังจะเริ่ม) ก็ติดต่อกับ release team เพื่อย้าย libthai เข้า unstable โดยขอ binNMU สำหรับทุกแพกเกจที่ลิงก์กับ libthai ซึ่งน่าจะทำให้ libdatrie0 รุ่นเก่าถูกปลดระวางไปอย่างสมบูรณ์

สำหรับ swath ตัวใหม่ที่ลิงก์กับ libdatrie1 แล้วนั้น คงจะออกเมื่อ libdatrie1 ตัวใหม่อยู่ตัวแล้ว อาจจะระหว่างอยู่ใน experimental หรือหลังจากย้ายเข้า unstable ก็แล้วแต่ความเหมาะสม

ป้ายกำกับ: , , ,

16 มีนาคม 2552

My (Partial) TODO List

ชักยาวเป็นหางว่าวแล้ว TODO list ของผม.. แค่ช่วงที่ติดงานแปล GNOME 2.26 นี่เท่านั้น จดไว้กันลืมเสียหน่อย 2.26 ออกเมื่อไรต้องรีบทยอยเคลียร์..

  • ออก libdatrie, libthai, swath รุ่นใหม่ที่ได้ ทำค้างเอาไว้
  • จัดการเรื่องปัญหา extended cluster ของ pango ซึ่งมีผลกับการเลื่อนเคอร์เซอร์ข้าม cluster ในรูป "เก" และ "กะ" (รวมทั้ง "เกะ") -- สิ่งที่เกี่ยวข้อง: Mozilla #474068, Unicode UAX #29
  • ออกแบบเรื่อง UI การใช้ภาษาอังกฤษในโลแคลไทย เพื่อแก้ปัญหา ผู้ใช้ไม่ยอมใช้โลแคลไทย จนไปกระทบ feature ภาษาไทยของระบบ และหาที่เสนอแนวคิด
  • แก้ปัญหาเรื่องความกว้างของตัวเลข ตามที่ Davide Viti ได้ ตรวจสอบ เอาไว้ แพกเกจที่กระทบคือ ttf-thai-arundina และ ttf-thai-tlwg
  • update Debian package ภาษาไทย โดย update ข้อมูล VCS ของแพกเกจที่ host ที่ LTN จาก CVS เป็น SVN, update ตาม Debian policy 3.8.1, update debhelper เป็น level 7
  • ผลักดัน Thai Fonts Siampradesh (non-free) เข้าใน Debian

มีรายการอื่นอีก ที่คงไม่สะดวกที่จะเขียนลง blog เนื่องจากเป็นการติดต่อเป็นการส่วนตัวกับคนอื่น

วันนี้เป็นวันสุดท้ายก่อน tarballs due ของ GNOME 2.26 แล้ว คงจะพยายามแปล user guide ให้ได้มากที่สุด จากนั้นก็เป็นคิวของ release notes ที่ควรจะเสร็จภายในวันพุธ (18 มี.ค.) แล้วหลังจากนั้นถึงจะเป็นอิสระจากงานแปล ไปเคลียร์ TODO list ได้..

ป้ายกำกับ: , , , , , , , , , ,

03 ธันวาคม 2551

32-bit datrie

จากที่เคย เกริ่น ไว้นานแล้ว ถึงปัญหาเรื่อง dict ใน swath ที่เพิ่ม-ลบคำไม่ได้ จำเป็นต้องแทนที่โค้ด trie ด้วย datrie ตัวใหม่ แต่มีปัญหาว่า datrie นั้นใช้ node index ขนาด 16 บิต ซึ่งทำให้จำนวนโหนดไม่เพียงพอกับรายการคำของ swath ประกอบกับปัญหา dict ตัดคำของ libthai ก็มาชนลิมิตนี้เหมือนกัน รวมทั้งมีผู้รายงานเข้ามาบ่อย ว่าต้องการเพิ่มคำให้ได้มากกว่านี้ ก็สรุปว่าต้องแก้ datrie ให้รองรับ node index ขนาดใหญ่ขึ้น

ก็ได้ ประกาศแผน ใน thai-linux-foss-devel mailing list ว่าจะตัดสินใจ break ABI โดยล้มเลิกความคิดเรื่อง backward compatibility กับ trie 16 บิต หรือการใช้ index 24 บิต แต่จะใช้ index 32 บิตอย่างเดียวไปเลย เพื่อความเรียบง่ายของโค้ด พร้อมกันนี้ก็ถือโอกาสปรับ API ให้รองรับการใช้งานที่กว้างขึ้นด้วย สรุปแผนคือ:

  • แตก branch r_0_1_x-branch สำหรับ maintain datrie 0.1.x แล้วพัฒนารุ่นใหม่ใน HEAD ซึ่งจะมุ่งสู่รุ่น 0.2.0 ต่อไป
  • break ABI โดยเปลี่ยน SONAME ของไลบรารีเป็น libdatrie.so.1
  • เปลี่ยนขนาดของ node index จาก 16 บิต เป็น 32 บิต
  • ปรับฟอร์แมตของแฟ้ม จากเดิมที่แยกเป็น *.br และ *.tl ให้รวมอยู่ในแฟ้มเดียว
  • ปรับ API จากที่ต้องอ่าน-เขียนกับแฟ้มเสมอ ให้กลายเป็นแค่ทางเลือกหนึ่งในการ load/save เท่านั้น และให้ใช้ trie ใน memory ล้วน ๆ ได้ด้วย

ตอนนี้ใน CVS ได้ใช้ node index ขนาด 32 บิตแล้ว รวมทั้งปรับโค้ดเรื่องการจัดการ overflow นิดหน่อย ขั้นต่อไปคือทำเรื่อง API และฟอร์แมตของแฟ้ม

ป้ายกำกับ: , ,

hacker emblem