2012-01-29 32 views
6

Tôi có nhiều chủ đề xử lý sự kiện. Tôi muốn gán dấu thời gian nano giây cho mỗi sự kiện. Nó phải là một id duy nhất, mặc dù. Vì vậy, trong trường hợp kỳ lạ mà hai sự kiện đến như vậy mà họ sẽ được chỉ định cùng một dấu thời gian, tôi muốn một trong số họ được tăng thêm một nano giây. Cho rằng độ chính xác thực sự không phải ở cấp độ nano giây, đó là ok như xa như bản chất tem thời gian của hệ thống.Id dấu thời gian duy nhất hiệu suất cao cho nhiều chủ đề trong Haskell

Trong một chuỗi, đây là một vấn đề nhỏ. Nhưng qua nhiều chủ đề, nó trở nên khó khăn hơn. Hiệu suất là cực kỳ quan trọng vì vậy ý ​​tưởng về sự đồng bộ ngây thơ trên một loại máy phát id tiêu biểu có vẻ như nó sẽ chặn quá nhiều.

Có cách tiếp cận nào giải quyết vấn đề này với khóa tối thiểu hoặc không khóa không?

Trả lời

1

Bạn có thể sử dụng atomicModifyIORef để triển khai bộ đếm nguyên tử. Với GHC, nó được thực hiện bằng cách sử dụng các hoạt động nguyên tử, không phải khóa.

import Data.IORef 
import System.IO.Unsafe 

counter :: IO Int 
counter = unsafePerformIO $ newIORef 0 

getUnique :: IO Int 
getUnique = atomicModifyIORef counter $ \x -> let y = x + 1 in (y, y) 
+0

@ehird: Vui lòng không thực hiện các thay đổi không quan trọng đối với bài đăng của tôi, thay vào đó hãy đăng nhận xét nếu bạn có nội dung cần thêm. –

+0

Xin lỗi, tôi cảm thấy sự thay đổi mà tôi đã thực hiện là đủ tầm thường nhưng sau đó lại thấy thêm hai lỗi nữa trước khi lưu. Hiện tại, 'getUnique' luôn trả về' ⊥' và 'counter' có thể được gạch chân thành các biểu thức khác, nhân đôi biến và phá vỡ mã.Ngoài ra, nếu cả hai điều này đã được cố định, thì 'getUnique' sẽ có một rò rỉ không gian do các khối xây dựng trên các lần thực thi liên tiếp. (BTW, mô-đun 'Data.Unique' chuẩn thực sự cung cấp API này.) – ehird

+0

@ehird: Đó chính xác là loại thông tin mà tôi muốn biết, cảm ơn. –

2

Tại sao không tách biệt các mối quan ngại về việc tạo dấu thời gian và tạo ID duy nhất? Ví dụ: có mô-đun chuẩn Data.Unique, cung cấp nguồn cung cấp toàn cầu các giá trị duy nhất trong IO và phải đủ nhanh cho hầu hết các mục đích. Hoặc, nếu bạn cần một cái gì đó huyền ảo, gói concurrent-supply cung cấp một nguồn cung cấp ID duy nhất, đồng thời hiệu suất cao với giao diện thuần túy.

Điều đó nói rằng, bạn có thể sử dụng POSIX monotonic clock cho mục đích này, sử dụng ví dụ: gói clock:

import Control.Monad 
import qualified System.Posix.Clock as Clock 

main :: IO() 
main = replicateM_ 100 $ do 
    time <- Clock.getTime Clock.Monotonic 
    print (Clock.sec time, Clock.nsec time) 
+0

Hiệu suất có đủ cao không? – augustss

+0

@augustss: Đồng hồ đơn điệu POSIX? Tôi không chắc. Nếu nó không đủ nhanh, đó là một lý do tốt khác để tách biến thời gian và tạo ID. – ehird

+0

@ehird sẽ là một ID duy nhất được tạo tại thời điểm b trong tất cả các trường hợp có giá trị cao hơn một ID duy nhất được tạo tại thời điểm (trước đó)? –

0

Trong ngôn ngữ C, chúng tôi thường thực hiện việc này bằng bộ đếm nguyên tử - không cần khóa. Nếu bạn muốn có một dấu thời gian quá, đó sẽ là một giá trị riêng biệt. Tôi không chắc chắn về Haskell vì tôi không viết với nó (như là thú vị như nó âm thanh).

0
+0

Chào mừng bạn đến Stack Overflow! Trong khi điều này về lý thuyết có thể trả lời câu hỏi, [nó sẽ là thích hợp hơn] (http://meta.stackexchange.com/q/8259) để bao gồm các phần thiết yếu của câu trả lời ở đây, và cung cấp liên kết để tham khảo. – oers

2

Bạn có thể sử dụng hai phần thông tin làm id duy nhất không? Nếu vậy, đặt cho mỗi luồng một id duy nhất và bản ghi cho mỗi sự kiện, dấu thời gian nano giây và id của chuỗi chỉ định dấu thời gian. Sau đó, vấn đề sẽ giảm xuống bất cứ điều gì bạn đã làm trong trường hợp có ren đơn để đảm bảo tính duy nhất của dấu thời gian. Và không có đồng bộ hóa ở tất cả sau khi khởi tạo.

Các vấn đề liên quan