Thủ thuật cache UDP header để tăng performance trong Elixir
elixir
33
Erlang
14
White

Cẩm Huỳnh viết ngày 21/01/2018

Vài tháng trước tui có giúp phát triển chức năng hỗ trợ Unix domain socket cho Fluxter, cho phép Fluxter gửi metrics qua UDP đến Telegraf dùng Unix domain socket.

Cách thông thường để gửi một UDP packet trong Erlang/Elixir là dùng gen_udp. Ở ví dụ bên dưới ta mở một UDP socket ở passive mode và dùng hàm :gen_udp.send/4 để gửi packet đến một UDP socket ở địa chỉ 127.0.0.1 và port 27027.

{:ok, sock} = :gen_udp.open(0, [active: false])
{ok, addr} = :inet.getaddr('127.0.0.1', :inet)
packet = [my_data]
:gen_udp.send(sock, addr, 27027, packet)

Tuy nhiên lúc đọc code của Fluxter, tui phát hiện ra cách gửi UDP packet khá lạ.

{:ok, sock} = :gen_udp.open(0, [active: false])

{:ok, {n1, n2, n3, n4}} = :inet.getaddr('127.0.0.1', :inet)
port = 27027
header =
  [
    1, # inet address family for Erlang >= 19,
    band(bsr(port, 8), 0xFF),
    band(port, 0xFF),
    band(n1, 0xFF),
    band(n2, 0xFF),
    band(n3, 0xFF),
    band(n4, 0xFF)
  ]
packet = [header, my_data]

send(sock, {self(), {:command, packet}})

Với đoạn code trên, ta tính trước header chứa thông tin đích đến của packet. Rồi mỗi lần cần gửi data, ta chèn header đã tính vào đầu packet rồi gửi bằng Erlang port_command.

Lợi ích khi làm như vậy là giúp tăng tốc. Theo benchmark của tác giả thì tốc độ tăng gần 20% sau khi cache header.

Fluxter là một metrics writer với packet được gửi với số lượng lớn. :gen_udp.send/4 luôn build lại header mỗi khi được gọi trong khi đích đến của ta là không đổi. Đó là một cost không cần thiết và bằng cách cache lại header và dùng port_command để gửi packet, ta giảm được cost này.

Bài viết này sẽ giúp tui tăng lương như thế nào?

Bài viết này được viết sau khi tác giả đã được tăng lương mua quần mới. Còn bạn được tăng lương không tui đâu quan tâm. #ahihi

Cơ mà sau khi nói xong lợi phải nói đến răng, lộn hại. :trollface:

Tất nhiên việc tăng tốc không free, nó là một tradeoff (tạm dịch: sự đánh đổi). Cost chỉ chuyển hoá từ chỗ này sang chỗ khác, từ dạng này sang dạng khác.

Cost ở đây là việc phải maintain code mà đáng lẽ bạn đã không cần phải làm vậy nếu sử dụng abstraction. Với :gen_udp.send/4, bạn có thể yên tâm upgrade OTP version mà không phải lo gì cả (đã có người viết abstraction lo cho bạn). Còn khi tự build header, bạn sẽ phải tự kiểm tra, cập nhật CHANGELOG để tương thích app qua mỗi version OTP. Ví dụ OTP 19 và OTP 18 có cách build header khác nhau ở address family.

Tuy nhiên với cost là việc maintain thêm chừng 10 dòng code rất hiếm khi có breaking change để đổi lấy 20% giá trị performance, thương vụ này tui sẽ đầu tư. Còn shark Phú, không biết ông ấy nghĩ sao ta?


Quảng cáo trắng trợn: Bài viết đăng lại từ blog của mình.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Cẩm Huỳnh

40 bài viết.
340 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
39 9
(Ảnh) Vì sao lại là Bật Đèn? Ai từng đọc qua Tắt Đèn hẳn đã biết tác phẩm được kết thúc bằng tình huống: Buông tay, chị vội choàng dậy, mở cửa...
Cẩm Huỳnh viết 1 năm trước
39 9
White
37 6
Làm thế nào để chỉ với một đoạn text vài trăm ký tự, bạn có thể làm ngốn vài gigabyte bộ nhớ và từ chối dịch vụ của một hệ thống dùng XML? _____ ...
Cẩm Huỳnh viết 4 tháng trước
37 6
White
34 25
Vừa rồi mình vừa tiết kiệm được $5 mỗi tháng sau khi migrate cái (Link) từ Digital Ocean sang Heroku Free Dyno. (Ảnh) Kết quả thật mĩ mãn vì hầu ...
Cẩm Huỳnh viết 12 tháng trước
34 25
Bài viết liên quan
White
3 0
Chú thích: Bài này đăng lần đầu năm 2009 để chia sẻ kinh nghiệm, sau khi tác giả viết xong thư viện closed source để bán. Hiện tại năm 2016 đã có t...
Ngoc Dao viết hơn 2 năm trước
3 0
White
2 0
Trong xử lí song song, các đơn vị thực hiện nhiệm vụ xử lí thường gặp là: thread, process, core, CPU, node. Thường mỗi node ứng với một server vật ...
Ngoc Dao viết hơn 2 năm trước
2 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
40 bài viết.
340 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!