วันพุธ, กรกฎาคม 15, 2552

ทำเว็บแบบขยาย: เพิ่มความเร็วในการอ่านไฟล์

บริการบนเว็บส่วนมากอ่านไฟล์กันกระจุยกระจายอยู่แล้ว โดยเฉพาะที่บริษัทผมทำด้าน data-ware house เก็บไฟล์ multimedia แค่อ่าน thumbnail หน้านึงอย่างน้อยๆ ก็ 20 ไฟล์ แถมใน server มีไฟล์เป็นล้าน แค่หาไฟล์อย่างเดียวยังไม่ทันอ่าน server ก็เริ่มเหนื่อย

ก่อน ext3 บน kernel 2.6 เวลา server หาไฟล์ใน folder มันต้องไล่หาตั้งแต่ไฟล์แรกไปจนถึงไฟล์ที่ต้องการ ถ้าใน folder นั้นมีซัก 10,000 ไฟล์ server ก็ต้องทำ string match กัน 10,000 ครั้งก่อนจะเริ่มอ่านไฟล์ ถ้าในกรณีบริษัทผมต้องหาไฟล์ 20 ไฟล์ ก็ต้องทำ string match กัน 200,000 ครั้งต่อการเปิดเว็บ 1 หน้า

ตอนนี้ดีหน่อยเพราะเรามี ext3 บน kernel 2.6+ แถมมี ext4 อีกต่างหาก ตัวใหม่ๆ จะเก็บไฟล์เป็น hash เวลาเรียกไฟล์มันจะไปหาใน hash แล้ววิ่งตรงๆ ไปหาไฟล์เลยไม่ต้องเสียเวลาอ่านชื่อกันทีละไฟล์

ใครที่อยู่บนสถาปัตยกรรม เก่าๆ ก็ต้องลดจำนวนไฟล์ใน folder เอานะครับ

ธรรมชาติอีกหนึ่งอย่างที่น่าสนใจคือ เวลาที่ UNIX มันอ่านไฟล์มันไม่ได้อ่านอย่างเดียวครับ มันจะเขียนด้วย สิ่งที่เขียนคือ "เวลา" ที่เราไปยุ่งกันไฟล์ เพื่อบันทึกว่าแต่ละไฟล์ถูกอ่านหรือเขียนไปล่าสุดตอนไหน เราเรียก "เวลา" นี้ว่า "atime" หรือ access time

แน่นอนว่าการเขียนเปลืองพลังงานมากกว่าการอ่านหลายเท่าตัว ถ้าเป็นไฟล์ใหญ่ๆ ก็พอให้อภัยได้ แต่ถ้าเป็นไฟล์เล็กๆ การเขียนนิดเดียวบางทีใช้เวลามากกว่าการอ่าน ยิ่งเป็น web ด้วยเรามีไฟล์เล็กๆ จำนวนมากเช่น thumbnail, css, java script, favorite icon เป็นต้น ถ้า web server หรือ framework ทำงานไม่ดี ไฟล์พวกนี้ต้องอ่านกันทุกครั้งที่ผู้ใช้เปิด browser ทีเดียว

ทางแก้คือตอนที่เรา mount ไฟล์ให้เรา set noatime เอาไว้

noatime: Do not update inode access times on this file system (e.g, for faster access on the news spool to speed up news servers).

การจะ set notime ทำได้ 3 แบบครับ

1. แบบแรกคือทำกันตั้งแต่ตอน install



เลือกตรง mount option ที่ set เป็น default



เลือกที่ noatime ไว้ส่วน relatime จะเลือกไว้ก็ได้ครับ linus บอกไว้ว่า
The “relatime” thing that David mentioned might well be very useful, but it’s probably even less used than “noatime” is. And sadly, I don’t really see that changing (unless we were to actually change the defaults inside the kernel).
2. แบบที่สองคือใส่ตอนที่เราสั่ง mount ครับ
mount -o remount,noatime /
แบบนี้ก็ง่ายดีแต่ถ้า restart เครื่องก็ต้องสั่งกันใหม่ 3. แบบที่สามคือแก้ไฟล์ fstab แบบนี้น่าจะเหมาะกับ web server มากที่สุด ถ้าเรามี fstab แบบนี้
# /etc/fstab: static file system information.
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
/dev/sda1       /               ext2    errors=remount-ro 0       1
/dev/sda5       none            swap    sw              0       0
/dev/scd0       /media/cdrom0   udf,iso9660 user,noauto     0       0

ให้เราเติม noatime หรือ relatime ไว้ที่ column options ครับ จะใส่ทั้งสองตัวหรือแค่ตัวเดียวก็ได้

# /etc/fstab: static file system information.
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
/dev/sda1       /               ext2    noatime,relatime,errors=remount-ro 0       1
/dev/sda5       none            swap    sw              0       0
/dev/scd0       /media/cdrom0   udf,iso9660 user,noauto     0       0
เสร็จแล้ว restart เครื่องซักทีนึง แล้วลองสั่ง cat /proc/mounts เพื่อดูว่ามัน mount ให้เราถูกต้องหรือเปล่า
# cat /proc/mounts
rootfs / rootfs rw 0 0
none /sys sysfs rw,nosuid,nodev,noexec 0 0
none /proc proc rw,nosuid,nodev,noexec 0 0
udev /dev tmpfs rw,size=10240k,mode=755 0 0
/dev/sda1 / ext2 rw,noatime,relatime,errors=remount-ro 0 0
tmpfs /lib/init/rw tmpfs rw,nosuid,mode=755 0 0
usbfs /proc/bus/usb usbfs rw,nosuid,nodev,noexec 0 0
tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0
devpts /dev/pts devpts rw,nosuid,noexec,gid=5,mode=620 0 0

เท่านี้ server ก็ไม่ต้องเสียเวลาเขียนไฟล์แล้วครับ โดยเฉพาะเวลา mount ไปที่ Raid ยิ่งประหยัดได้หลายขุมเลย

ยกเว้นต้องการใช้ atime จริงๆ ก็ควรจะเปิดไว้นะครับ ยิ่งสำหรับเครื่องทั่วไปถ้าเราปิดโปรแกรม mail อาจใช้การไม่ได้เพราะมันมี function เทียบวันเวลาในการอ่านไฟล์เก็บไว้กับ atime เราอาจจะเลือกปิดเป็นบาง partition ตามการ mount ของเราก็ได้

อยากรู้เพิ่มเติมก็สั่ง man mount เอานะครับ
blog comments powered by Disqus