Trứng lòng đào và các vấn đề đồng hồ trong lập trình

Công Nghệ
Trứng lòng đào và các vấn đề đồng hồ trong lập trình
Bài viết được sự cho phép của tác giả Huỳnh Quán Cẩm Sáng nay tui luộc trứng. Bỏ trứng vào nồi, bật bếp rồi bỏ ra ngoài chơi game. Liếc nhìn đồng hồ trên lò vi sóng hiển thị 07:36 . Dự là sẽ canh đúng 6 phút để có trứng lòng đào hoàn hảo. 07:42 , tui vào tắt bếp và bóc trứng. Lòng đỏ nhão nhẹt . Nhìn kĩ mới để ý là đồng hồ trên lò chậm hơn đồng hồ trong game console gần 2 phút . "Bách khoa toàn thư" ngôn ngữ lập trình Perl "Trên tay" SwiftUI của một lập trình viên mobile Khi đồng hồ không đáng tin Đồng hồ pin mà chúng ta xài mỗi ngày sử dụng một bộ dao động Quartz , hoạt động bằng cách đo tần suất dao động của một viên pha lê thạch anh được cấp điện bởi một cục pin. Bạn nào yêu thích tìm hiểu đồng hồ chắc sẽ biết là bộ dao động Quartz, dù cho chính xác cao hơn nhiều so với bộ dao động cơ , vẫn có sai số từ ±10-20s/tháng trong điều kiện bình thường, ngoài ra còn phụ thuộc vào nhiều yếu tố khác như là nhiệt độ. Có nghĩa sau khi chạy được một khoảng thời gian nào đó, đồng hồ Quartz sẽ chạy lệch so với thời gian của vũ trụ . Hiện tượng này có thuật ngữ là clock drift (tạm dịch: trượt đồng hồ), clock drift có thể trượt về tương lai hoặc quá khứ tùy vào hứng của viên pha lê. Nó đồng nghĩa với việc thời gian trên cái đồng hồ đôi khi không đáng tin cậy . Vì vậy, đồng hồ cần phải được căn chỉnh đồng bộ thường xuyên. Giống như...

Bài viết được sự cho phép của tác giả Huỳnh Quán Cẩm

Sáng nay tui luộc trứng. Bỏ trứng vào nồi, bật bếp rồi bỏ ra ngoài chơi game. Liếc nhìn đồng hồ trên lò vi sóng hiển thị 07:36. Dự là sẽ canh đúng 6 phút để có trứng lòng đào hoàn hảo.

07:42, tui vào tắt bếp và bóc trứng. Lòng đỏ nhão nhẹt . Nhìn kĩ mới để ý là đồng hồ trên lò chậm hơn đồng hồ trong game console gần 2 phút .

Khi đồng hồ không đáng tin

Đồng hồ pin mà chúng ta xài mỗi ngày sử dụng một bộ dao động Quartz, hoạt động bằng cách đo tần suất dao động của một viên pha lê thạch anh được cấp điện bởi một cục pin.

Trứng lòng đào và các vấn đề đồng hồ trong lập trìnhTrứng lòng đào và các vấn đề đồng hồ trong lập trình

Bạn nào yêu thích tìm hiểu đồng hồ chắc sẽ biết là bộ dao động Quartz, dù cho chính xác cao hơn nhiều so với bộ dao động cơ, vẫn có sai số từ ±10-20s/tháng trong điều kiện bình thường, ngoài ra còn phụ thuộc vào nhiều yếu tố khác như là nhiệt độ.

Có nghĩa sau khi chạy được một khoảng thời gian nào đó, đồng hồ Quartz sẽ chạy lệch so với thời gian của vũ trụ . Hiện tượng này có thuật ngữ là clock drift (tạm dịch: trượt đồng hồ), clock drift có thể trượt về tương lai hoặc quá khứ tùy vào hứng của viên pha lê.

Nó đồng nghĩa với việc thời gian trên cái đồng hồ đôi khi không đáng tin cậy. Vì vậy, đồng hồ cần phải được căn chỉnh đồng bộ thường xuyên. Giống như khi đồng hồ treo trường hết pin hoặc sắp hết pin, nó sẽ không chạy chính xác nữa mà bạn “dòm” nhờ đồng hồ nhà hàng xóm để vặn lại cho đúng.

Nhưng rồi bạn sẽ đặt câu hỏi: “Tui có bao giờ chỉnh đồng hồ trên game console hay smart phone đâu mà nó vẫn chạy đúng thôi?”.

Đó là bởi vì những thiết bị đó luôn tự chỉnh lại thời gian của chính nó, thông qua một giao thức có tên gọi là NTP (Network Time Protocol).

Việc giải thích cách giao thức NTP hoạt động nằm ngoài phạm vi bài viết này, nhưng cơ bản là máy của bạn join vào một mạng lưới bao gồm rất nhiều máy tính “hàng xóm”, nơi mà lâu lâu nó ngó vào đồng hồ của chúng và tự chỉnh sửa lại cho hợp lý dựa trên một công thức phức tạp. Thời gian của mạng lưới này có nguồn từ những atomic clock có độ chính xác gần như tuyệt đối, tính bằng giây/tỉ năm. NTP đảm bảo cho độ sai lệch ở mức vài chục millisecond.

Mặc dù vậy, không có gì đảm bảo đồng hồ trên máy của bạn luôn đúng mặc dù sử dụng NTP, bởi vì không chỉ thời gian, network cũng không đáng tin cậy. Máy tính có thể bị mất kết nối tới NTP server, mất kết nối Internet, hoặc chết đi sống lại sau một thời gian dài, lúc đấy không có gì đảm bảo thời gian của bạn là reliable cả.

Bài toán “trứng lòng đào”

Ta hãy thử mô tả lại bài toán trứng lòng đào dưới con mắt của một lập trình viên.

Ở đây ta có một distributed system, với 2 service (tạm gọi là Kitchen và GameConsole) chạy trên 2 máy tính riêng biệt và có kết nối mạng với nhau. Tui sẽ mô phỏng lại bằng đoạn code Ruby dưới đây, với các lớp giao tiếp networking đã được tối giản.

Kitchen có 2 thao tác boil_eggs và turn_stove_off. Khi bắt đầu nấu trứng, Kitchen sẽ gọi GameConsole nhắc nó tắt bếp sau 6 phút.

class Kitchen
  def boil_eggs()
    turn_stove_on()
    time = Time.now() # `07:36`
    due_time = time + 3_600 # 6 minutes
    GameConsole.remind(self, due_time)
  end

  def turn_stove_off()
    @turn_off = true
  end
end

Phương thức GameConsole.remind chỉ là một vòng lặp vô hạn kiểm tra khi nào thì báo bên kia tắt bếp.

class GameConsole
  def remind(sender, due_time)
    loop do
      if due_time >= Time.now()
        sender.turn_stove_off()
        break
      end
    end
  end
end

Ở đây, ta có một vấn đề “trứng lòng đào”. Nếu thời gian của chúng lệch nhau, như đã nói, bếp sẽ được tắt trước hạn nếu đồng hồ GameConsole chạy nhanh hơn Kitchen hoặc sau hạn nếu ngược lại. Sự đúng đắn của đoạn code này phụ thuộc vào độ đồng bộ thời gian của cả 2 máy tính.

Vậy ta sẽ sửa lại bài toán trên như thế nào? Đương nhiên bạn không thể cập nhật lại đồng hồ định kì bằng cơm, càng không thể cài NTP vào lò vi sóng. Cho dù bạn cài được NTP vào lò vi sóng đi chăng nữa, bạn vẫn không thể đảm bảo đồng hồ của lò luôn luôn chính xác. Bởi vì network là không đáng tin cậy như tui đã đề cập ở trên.

Cơ mà nếu ở ngoài đời thực, ta gần như lập tức nghĩ ra cách dùng đồng hồ bấm giờ.

Hầu hết mọi hệ điều hành đều cung cấp cho ta hai loại đồng hồ để thao tác với thời gian: real-time clock CLOCK_REALTIME và monotonic clock CLOCK_MONOTONIC. Hai loại đồng hồ này được thiết kế để dùng trong những trường hợp khác nhau.

  • real-time clock – còn lại là wall clock (đồng hồ treo tường), thể hiện dự đoán gần đúng nhất của máy tính về thời điểm thực hiện tại. Đồng hồ treo tường này luôn luôn cần được đồng bộ và có thể go backward.
  • monotonic clock – thể hiện thời gian đã trôi qua tính từ một thời điểm cố định bất kì nào đó trong quá khứ. Monotonic clock luôn tăng.

Ta có thể sử dụng monotonic clock cho bài toán trên.

Lúc này thay vì gửi một giá trị tuyệt đối là timestamp đáo hạn cho GameConsoleKitchen chỉ đơn thuần gửi gắm là nó muốn được đáo hạn sau một đơn vị thời gian.

class Kitchen
  def boil_eggs()
    turn_stove_on()
    GameConsole.remind(self, 3_600) # 6 minutes
  end
end

Với GameConsole, khi nhận được tin nhắn, ta sẽ ghi lại start là monotonic time hiện tại trên máy. Sau đó tính elapsed time (thời gian trôi qua) trong mỗi vòng lặp.

class GameConsole
  def remind(sender, due_after)
    start = Process.clock_gettime(Process::CLOCK_MONOTONIC)

    loop do
      elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start

      if elapsed >= due_after
        sender.turn_stove_off()
        break
      end
    end
  end
end

Vì sao không dùng Time.now()?

Time.now() trong Ruby dùng wall-clock.

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

Bài viết này không giúp bạn tăng lương, nhưng tui chắc chắn đọc xong, bạn sẽ biết nấu trứng lòng đào.

Bạn cũng biết rằng bạn KHÔNG nên dùng wall clock khi muốn tính elapsed time.

Bạn cũng nhớ rằng KHÔNG có gì đảm bảo một sự kiện xảy ra sau sẽ hiển thị sau ở hệ thống (causal effect), nếu dùng timestamp từ wall clock để order.

Bài viết gốc được đăng tải tại quan-cam.com

Có thể bạn quan tâm:

Xem thêm các việc làm Developer hấp dẫn tại Station D

Bài viết liên quan

Bộ cài đặt Laravel Installer đã hỗ trợ tích hợp Jetstream

Bộ cài đặt Laravel Installer đã hỗ trợ tích hợp Jetstream

Bài viết được sự cho phép của tác giả Chung Nguyễn Hôm nay, nhóm Laravel đã phát hành một phiên bản chính mới của “ laravel/installer ” bao gồm hỗ trợ khởi động nhanh các dự án Jetstream. Với phiên bản mới này khi bạn chạy laravel new project-name , bạn sẽ nhận được các tùy chọn Jetstream. Ví dụ: API Authentication trong Laravel-Vue SPA sử dụng Jwt-auth Cách sử dụng Laravel với Socket.IO laravel new foo --jet --dev Sau đó, nó sẽ hỏi bạn thích stack Jetstream nào hơn: Which Jetstream stack do you prefer? [0] Livewire [1] inertia > livewire Will your application use teams? (yes/no) [no]: ... Nếu bạn đã cài bộ Laravel Installer, để nâng cấp lên phiên bản mới bạn chạy lệnh: composer global update Một số trường hợp cập nhật bị thất bại, bạn hãy thử, gỡ đi và cài đặt lại nha composer global remove laravel/installer composer global require laravel/installer Bài viết gốc được đăng tải tại chungnguyen.xyz Có thể bạn quan tâm: Cài đặt Laravel Làm thế nào để chạy Sql Server Installation Center sau khi đã cài đặt xong Sql Server? Quản lý các Laravel route gọn hơn và dễ dàng hơn Xem thêm Tuyển dụng lập trình Laravel hấp dẫn trên Station D

By stationd
Principle thiết kế của các sản phẩm nổi tiếng

Principle thiết kế của các sản phẩm nổi tiếng

Tác giả: Lưu Bình An Phù hợp cho các bạn thiết kế nào ko muốn làm code dạo, design dạo nữa, bạn muốn cái gì đó cao hơn ở tầng khái niệm Nếu lập trình chúng ta có các nguyên tắc chung khi viết code như KISS , DRY , thì trong thiết kế cũng có những nguyên tắc chính khi làm việc. Những nguyên tắc này sẽ là kim chỉ nam, nếu có tranh cãi giữa các member trong team, thì cứ đè nguyên tắc này ra mà giải quyết (nghe hơi có mùi cứng nhắc, mình thì thích tùy cơ ứng biến hơn) Tìm các vị trí tuyển dụng designer lương cao cho bạn Nguyên tắc thiết kế của GOV.UK Đây là danh sách của trang GOV.UK Bắt đầu với thứ user cần Làm ít hơn Thiết kế với dữ liệu Làm mọi thứ thật dễ dàng Lặp. Rồi lặp lại lần nữa Dành cho tất cả mọi người Hiểu ngữ cảnh hiện tại Làm dịch vụ digital, không phải làm website Nhất quán, nhưng không hòa tan (phải có chất riêng với thằng khác) Cởi mở, mọi thứ tốt hơn Bao trừu tượng luôn các bạn, trang Gov.uk này cũng có câu tổng quát rất hay Thiết kế tốt là thiết kế có thể sử dụng. Phục vụ cho nhiều đối tượng sử dụng, dễ đọc nhất nhất có thể. Nếu phải từ bỏ đẹp tinh tế – thì cứ bỏ luôn . Chúng ta tạo sản phẩm cho nhu cầu sử dụng, không phải cho người hâm mộ . Chúng ta thiết kế để cả nước sử dụng, không phải những người đã từng sử dụng web. Những người cần dịch vụ của chúng ta nhất là những người đang cảm thấy khó sử dụng dịch...

By stationd
Hiểu về trình duyệt – How browsers work

Hiểu về trình duyệt – How browsers work

Bài viết được sự cho phép của vntesters.com Khi nhìn từ bên ngoài, trình duyệt web giống như một ứng dụng hiển thị những thông tin và tài nguyên từ server lên màn hình người sử dụng, nhưng để làm được công việc hiển thị đó đòi hỏi trình duyệt phải xử lý rất nhiều thông tin và nhiều tầng phía bên dưới. Việc chúng ta (Developers, Testers) tìm hiểu càng sâu tầng bên dưới để nắm được nguyên tắc hoạt động và xử lý của trình duyệt sẽ rất hữu ích trong công việc viết code, sử dụng các tài nguyên cũng như kiểm thử ứng dụng của mình. Cách để npm packages chạy trong browser Câu hỏi phỏng vấn mẹo về React: Component hay element được render trong browser? Khi hiểu được cách thức hoạt động của trình duyệt chúng ta có thể trả lời được rất nhiều câu hỏi như: Tại sao cùng một trang web lại hiển thị khác nhau trên hai trình duyệt? Tại sao chức năng này đang chạy tốt trên trình duyệt Firefox nhưng qua trình duyệt khác lại bị lỗi? Làm sao để trang web hiển thị nội dung nhanh và tối ưu hơn một chút?… Hy vọng sau bài này sẽ giúp các bạn có một cái nhìn rõ hơn cũng như giúp ích được trong công việc hiện tại. 1. Cấu trúc của một trình duyệt Trước tiên chúng ta đi qua cấu trúc, thành phần chung và cơ bản nhất của một trình duyệt web hiện đại, nó sẽ gồm các thành phần (tầng) như sau: Thành phần nằm phía trên là những thành phần gần với tương tác của người dùng, càng phía dưới thì càng sâu và nặng về xử lý dữ liệu hơn tương tác. Nhiệm...

By stationd
Thị trường EdTech Vietnam- Nhiều tiềm năng nhưng còn bị bỏ ngỏ tại Việt Nam

Thị trường EdTech Vietnam- Nhiều tiềm năng nhưng còn bị bỏ ngỏ tại Việt Nam

Lĩnh vực EdTech (ứng dụng công nghệ vào các sản phẩm giáo dục) trên toàn cầu hiện nay đã tương đối phong phú với nhiều tên tuổi lớn phân phối đều trên các hạng mục như Broad Online Learning Platforms (nền tảng cung cấp khóa học online đại chúng – tiêu biểu như Coursera, Udemy, KhanAcademy,…) Learning Management Systems (hệ thống quản lý lớp học – tiêu biểu như Schoology, Edmodo, ClassDojo,…) Next-Gen Study Tools (công cụ hỗ trợ học tập – tiểu biểu như Kahoot!, Lumosity, Curriculet,…) Tech Learning (đào tạo công nghệ – tiêu biểu như Udacity, Codecademy, PluralSight,…), Enterprise Learning (đào tạo trong doanh nghiệp – tiêu biểu như Edcast, ExecOnline, Grovo,..),… Hiện nay thị trường EdTech tại Việt Nam đã đón nhận khoảng đầu tư khoảng 55 triệu đô cho lĩnh vực này nhiều đơn vị nước ngoài đang quan tâm mạnh đến thị trường này ngày càng nhiều hơn. Là một trong những xu hướng phát triển tốt, và có doanh nghiệp đã hoạt động khá lâu trong ngành nêu tại infographic như Topica, nhưng EdTech vẫn chỉ đang trong giai đoạn sơ khai tại Việt Nam. Tại Việt Nam, hệ sinh thái EdTech trong nước vẫn còn rất non trẻ và thiếu vắng nhiều tên tuổi trong các hạng mục như Enterprise Learning (mới chỉ có MANA), School Administration (hệ thống quản lý trường học) hay Search (tìm kiếm, so sánh trường và khóa học),… Với chỉ dưới 5% số dân công sở có sử dụng một trong các dịch vụ giáo dục online, EdTech cho thấy vẫn còn một thị trường rộng lớn đang chờ được khai phá. *** Vừa qua Station D đã công bố Báo cáo Vietnam IT Landscape 2019 đem đến cái nhìn toàn cảnh về các ứng dụng công...

By stationd