How I/O schedulers contribute to disk performance in Linux (1)


Đối với nhiều người thì hẳn biết về vai trò của một số process scheduler (như O(1)) hơn là các I/O scheduler trong Linux. Về cơ bản thì mục đích của 2 dạng scheduler này cùng là lập lịch, điều phối truy cập, sử dụng các tài nguyên tính toán mà được dùng chung bởi nhiều chương trình. Với process scheduler thì đó là sắp xếp, quyết định xem một process được chạy trong vòng bao lâu, có nên để nó thực thi tiếp hay không và nếu không thì process nào sẽ được chọn để chạy kế tiếp. Vậy với các I/O scheduler thì có chức năng gì và chúng giúp tăng hiệu suất của một hệ thống như thế nào? Bài viết có tham khảo bài báo này [1] trên Linux Journal, tác giả Robert Love hiện là kỹ sư lập trình tại Google và đã viết cuốn sách Linux Kernel Development.

Ngay từ thuở ban đầu thì process scheduler đã là thành phần bắt buộc đối với các hệ điều hành hỗ trợ đa nhiệm dựa trên cơ chế chia sẻ thời gian được CPU thực thi giữa các chương trình nhưng I/O scheduler thì không cần thiết phải có. Để hiểu về vị thế của I/O scheduler khi một hệ thống sẽ hành xử như thế nào nếu không có nó thì trước hết cần điểm qua một số kiến thức nền tảng về cách truy xuất thông tin trên thiết bị lưu trữ hiện vẫn còn rất phổ biến và cũng là giới hạn trong bài này là: ổ đĩa cứng (hard disk drive – HDD). Chi tiết về cấu tạo và hoạt động của HDD nằm ngoài phạm vi bài này. Ở mức khái quát thì như được thể hiện trong hình vẽ sau.

Một HDD thường gồm nhiều platter xếp chồng lên nhau, mỗi platter bao gồm duy nhất một disk (đĩa), spindle (trục quay) và read/write head (đầu đọc/ghi). Trên mỗi disk được chia ra thành nhiều track được sắp xếp thành các hình tròn đồng tâm. Tập hợp các track có cùng bán kính trên mỗi disk tạo thành một cylinder. Cuối cùng, mỗi track bao gồm nhiều sector, và đây là đơn vị nhỏ nhất mà có thể được đánh địa chỉ trên HDD và thường có kích thước là 512 byte.

Một data lưu trên HDD được định vị dựa vào 3 thông tin là cylinder, head, sector. Cylinder sẽ cho biết track nào mà data nằm trên. Tiếp đến, head giúp nhận diện chính xác đầu đọc ghi sẽ được sử dụng để thao tác với data và vì vậy cũng cho biết data đang nằm trên disk/platter nào. Cuối cùng, giá trị sector cho chỉ ra chính xác sector trên track mà chứa data. Đó là kết thúc quá trình tìm kiếm data trên HDD và nhiệm vụ kế tiếp là head sẽ quay quanh trục để trỏ tới đúng sector để thực hiện đọc ghi dữ liệu theo yêu cầu từ process chuyển xuống cho hệ điều hành.

Việc máy tính phải truyền thông với HDD thông qua bộ 3 số cylinder, head, sector sẽ là phức tạp. May thay các HDD thời giờ đều có cơ chế ánh xạ bộ 3 đó với một số nhận dạng duy nhất gọi là block number. Khi đó hệ điều hành sẽ sử dụng khái niệm gọi là logical block addressing để đánh địa chỉ cho dữ liệu và HDD sẽ thực hiện chuyển đổi số block thành các giá trị cylinder, head, sector tương ứng. Điểm cần lưu ý là thứ tự số block cũng thể hiện thứ tự của chúng trên HDD, ví dụ, data ở block thứ n sẽ liền kề với data ở block thứ n+1.

Phần tiếp theo sẽ đi vào cụ thể hơn cách mà hệ thống UNIX làm việc với các I/O request và block như thế nào.

Thường thì sẽ có nhiều ứng dụng khác như database, email client, web server, text editor đưa ra đồng thời các yêu cầu I/O nhằm đọc ghi dữ liệu lên một block nào đó.  Khác với cách truy cập dữ liệu một cách tuần tự của một character device như bàn phím thì HDD là một dạng block device với đặc điểm là các mảnh dữ liệu có kích thước cố định được truy cập mà không theo thứ tự nào cả. Vì vậy, một khối dữ liệu, ví dụ như tập tin a.txt có kích thước 2MB do chương trình vim tạo ra có thể được chia nhỏ, nằm rải rác ở nhiều block và các block này không cần thiết phải liên tục nhau. Điều này dẫn đến sự phân mảnh dữ liệu mà ta thường biết đến với thuật ngữ fragment và khi đó chương trình nếu muốn hình thành đầy đủ data của một file thì phải tạo ra nhiều I/O request, mỗi request trỏ tới một block khác nhau. Nếu may mắn các block này liền kề nhau thì head sẽ không phải vất vả chạy tới lui trên disk để đọc/ghi như trong tình huống các block đó không có sự liền mạch.

Việc head di chuyển từ vị trí này tới vị trí khác trên disk gọi là seeking và đây là một trong các căn nguyên của vấn đề disk performance nói riêng và hiệu suất của máy tính nói chung bởi vì chúng thường là các thao tác tốn kém thời gian nhất (thường tính bằng mili giây) mà các process phải chờ xử lý. Đây cũng là lý do khiến việc sắp xếp lại các mảnh của dữ liệu sao cho chúng nằm trên các block liên tục nhau (gọi là data defragment) trở nên quan trọng.

Nhưng vẫn chưa được vui cho lắm khi công tác data defragment không mang nhiều ý nghĩa trong trường hợp đồng loạt nhiều ứng dụng tạo các I/O request tới nhiều file rải rác trên toàn bộ HDD. Có thể là email client muốn ghi một chút vào block xxx, webserver lại muốn ghi một chút vào block yyy, nhưng khoan, tự vì có thể text editor lại đang muốn đọc từ cả 2 block xxx và yyy thì sao? Lập lịch đáp ứng cho các request đó như thế nào để giảm thiểu số lần seeking và không tạo ra độ trễ quá lâu cho một số request nào đó. Đây là lúc mà I/O scheduler đóng vai trò quan trọng hơn cả…

[1]: http://www.linuxjournal.com/article/6931

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s