2015-06-07 24 views
6

Tôi đã xem xét cách tôi có thể nhúng ngôn ngữ (hãy sử dụng Lua làm ví dụ) trong Erlang. Điều này tất nhiên không phải là một ý tưởng mới và có rất nhiều thư viện ở đó có thể làm điều này. Tuy nhiên tôi đã tự hỏi nếu nó có thể bắt đầu một Genserver với nhà nước được sửa đổi bởi Lua. Điều này có nghĩa là một khi bạn khởi động Genserver, nó sẽ bắt đầu quá trình Lua (chạy dài) để thao túng trạng thái của Genserver. Tôi biết điều này là có thể là tốt, nhưng tôi đã tự hỏi nếu tôi có thể đẻ trứng 1.000 10.000 hoặc thậm chí 100.000 của các quá trình này.Erlang sinh ra số lượng lớn các quy trình C

Tôi không thực sự quen thuộc với chủ đề này nhưng tôi đã thực hiện một số nghiên cứu. (Vui lòng sửa tôi nếu tôi sai về bất kỳ tùy chọn nào trong số này).

TLDR; Chuyển đến đoạn cuối cùng.

Đầu tiên lựa chọn: NIFs:

này không có vẻ như là một lựa chọn vì nó sẽ chặn các Erlang Scheduler của quá trình hiện hành. Nếu tôi muốn sinh ra một lượng lớn trong số này, nó sẽ đóng băng toàn bộ thời gian chạy.

Thứ hai tùy chọn: Port Driver:

Nó giống như một NIF nhưng giao tiếp bằng cách gửi dữ liệu đến một cổng nhất định, mà cũng có thể gửi dữ liệu trở lại Erlang. Điều này là tốt đẹp mặc dù điều này cũng có vẻ để ngăn chặn các Scheduler. Tôi đã thử một thư viện mà không các plat nồi hơi cho bạn là tốt, nhưng điều đó dường như để ngăn chặn các scheduler sau khi sinh ra 10 quy trình. Tôi cũng đã nhìn vào ví dụ postgresql trên Tài liệu Erlang được cho là không đồng bộ nhưng tôi không thể lấy mã ví dụ để làm việc (R13?). Thậm chí có thể chạy nhiều quy trình Port Driver mà không chặn thời gian chạy không?

tùy chọn thứ ba: C Nodes:

Tôi nghĩ đây là rất thú vị và muốn thử nó ra, nhưng dường như các dự án "erlang-lua" đã thực hiện điều này. Thật tuyệt vì nó sẽ không làm hỏng máy ảo Erlang của bạn nếu xảy ra sự cố và các quy trình được phân lập. Nhưng để thực sự sinh ra một quá trình duy nhất, bạn cần phải sinh ra toàn bộ một nút. Tôi không biết nó đắt đến mức nào. Tôi cũng không chắc chắn giới hạn của việc kết nối các nút trong một cluster là gì, nhưng tôi không thấy bản thân mình sinh ra 100.000 nút C.

Thứ tư lựa chọn: cổng:

Lúc đầu, tôi nghĩ rằng đây là giống như một điều khiển Cảng nhưng nó thực sự khác nhau. Bạn sinh ra một quá trình thực hiện một ứng dụng và giao tiếp thông qua STDIN và STDOUT. Điều này sẽ làm việc tốt cho sinh sản một số lượng lớn các quá trình, và (tôi nghĩ?) Họ không phải là một mối đe dọa cho máy ảo Erlang. Nhưng nếu tôi sẽ giao tiếp thông qua STDIN/STDOUT, tại sao ngay cả bận tâm với một ngôn ngữ nhúng để bắt đầu? Cũng có thể sử dụng bất kỳ ngôn ngữ kịch bản nào khác.

Và vì vậy sau nhiều nghiên cứu trong một lĩnh vực, tôi không quen thuộc với việc tôi đã đến đây. Bạn có thể một Genserver như là một "thực thể", nơi AI được viết bằng Lua. Đó là lý do tại sao tôi muốn có một quy trình cho từng thực thể. Câu hỏi của tôi là làm thế nào để tôi đạt được nhiều Genservers mà giao tiếp với các quá trình Lua chạy dài? Điều này thậm chí có thể? Tôi có nên giải quyết vấn đề của mình một cách khác nhau không?

+0

Mã Lua có thực sự cần hoàn toàn vượt qua chuỗi hạt nhân cơ bản không? Hoặc nó có thể được thiết lập theo cách nó có thể đăng ký cho một cuộc gọi lại hoặc thông báo của một số loại để nó có thể mang lại các hạt nhân trở lại Erlang và sau đó được gọi trở lại khi sự kiện nó quan tâm xảy ra? –

+0

Trong trường hợp cụ thể của Lua bạn có thể muốn xem https://github.com/rvirding/luerl mà là một thực hiện của Lua trong Erlang. Bạn chỉ cần tải và thực thi mã Lua trong một quá trình erlang (vì vậy bạn có thể có nhiều bộ đánh giá đồng thời lua). – johlo

Trả lời

3

Nếu bạn có thể tạo mã Lua — hoặc chính xác hơn, mã gốc cơ bản — hợp tác với VM Erlang, bạn có một vài lựa chọn.

Hãy xem xét một trong những chức năng quan trọng nhất của máy ảo Erlang: quản lý việc thực thi một quy trình nhẹ của Erlang (có khả năng lớn) trên một tập hợp các chuỗi lịch trình tương đối nhỏ. Nó sử dụng một số kỹ thuật để biết khi một quá trình đã sử dụng hết thời gian của nó hoặc đang chờ đợi và vì vậy nên được lên kế hoạch để cung cấp cho một quá trình khác một cơ hội để chạy.

Có vẻ như bạn đang hỏi làm cách nào để chạy mã nguồn gốc trong máy ảo, nhưng như bạn đã gợi ý, lý do mã gốc có thể gây ra sự cố cho máy ảo. dừng mã nguồn gốc hoàn toàn lấy một chuỗi lịch trình và do đó ngăn chặn các quy trình Erlang thông thường thực hiện. Bởi vì điều này, mã nguồn gốc phải hợp tác mang lại luồng lịch trình cho VM.

Đối NIFs cũ, các lựa chọn cho sự hợp tác như vậy là:

  1. Giữ số lượng thời gian cuộc gọi NIF chạy trên một sợi lên lịch để 1ms hoặc ít hơn.
  2. Tạo một hoặc nhiều chuỗi riêng tư. Chuyển đổi từng cuộc gọi NIF chạy dài từ chuỗi lịch trình của nó sang một luồng riêng để thực thi, sau đó trả về chuỗi lịch trình cho máy ảo.

Vấn đề ở đây là không phải tất cả cuộc gọi đều có thể hoàn thành trong 1ms trở xuống và việc quản lý chuỗi riêng tư có thể bị lỗi. Để giải quyết vấn đề đầu tiên, một số nhà phát triển sẽ chia công việc thành nhiều phần và sử dụng hàm Erlang làm trình bao bọc để quản lý một chuỗi các cuộc gọi NIF ngắn, mỗi cuộc gọi đã hoàn thành một phần công việc. Đối với vấn đề thứ hai, tốt, đôi khi bạn chỉ không thể tránh nó, mặc dù khó khăn vốn có của nó.

Các NIF đang chạy trên Erlang 17.3 hoặc cao hơn cũng có thể tạo ra chuỗi chủ đề lập lịch hợp tác bằng cách sử dụng enif_schedule_nif function. Để sử dụng tính năng này, mã gốc phải có khả năng thực hiện công việc của nó theo từng phần sao cho mỗi đoạn có thể hoàn thành trong cửa sổ thực thi NIF 1ms thông thường, tương tự như cách tiếp cận được đề cập trước đó mà không cần phải trả về một trình bao bọc Erlang giả tạo. My bitwise example code cung cấp nhiều chi tiết về điều này.

Erlang 17 cũng mang tính năng thử nghiệm, theo mặc định, được gọi là bộ lập lịch bẩn. Đây là tập hợp các bộ lập lịch VM không có các ràng buộc thời gian thực thi mã gốc giống như các trình lập lịch biểu thông thường; công việc ở đó có thể chặn trong khoảng thời gian vô hạn mà không làm gián đoạn hoạt động VM bình thường.

Bộ lập lịch bẩn có hai hương vị: Bộ lập lịch CPU cho công việc liên kết CPU và bộ lập lịch I/O cho công việc I/O-bound. Trong một máy ảo được biên dịch để cho phép các trình lập lịch bị bẩn, theo mặc định có nhiều bộ lập lịch CPU bẩn vì có các bộ lập lịch thông thường và có 10 bộ lập lịch I/O. Những con số này có thể được thay đổi bằng cách sử dụng công tắc dòng lệnh, nhưng lưu ý rằng để cố gắng ngăn chặn sự lên lịch thường xuyên, bạn không bao giờ có nhiều lịch trình CPU bẩn hơn so với lịch trình thông thường. Các ứng dụng sử dụng cùng chức năng enif_schedule_nif được đề cập trước đó để thực thi NIF trên các bộ lập lịch bẩn. My bitwise example code cũng cung cấp nhiều chi tiết về điều này. Lịch trình bẩn sẽ vẫn là một tính năng thử nghiệm cho Erlang 18 là tốt.

mã gốc trong liên kết trong trình điều khiển cổng là tùy thuộc vào giống nhau trên-scheduler hạn chế thời gian thực hiện như NIFs, nhưng trình điều khiển có hai tính năng NIFs không:

  1. đang điều khiển có thể đăng ký mô tả tập tin vào Hệ thống con bỏ phiếu VM và được thông báo khi bất kỳ bộ mô tả tập tin nào trở thành I/O sẵn sàng.
  2. API trình điều khiển hỗ trợ truy cập vào nhóm chủ đề không đồng bộ hóa không lên lịch, kích thước trong đó có thể định cấu hình nhưng theo mặc định có 10 luồng.

Tính năng đầu tiên cho phép mã trình điều khiển gốc tránh chặn chuỗi cho I/O. Ví dụ, thay vì thực hiện lệnh chặn recv, mã trình điều khiển có thể đăng ký bộ mô tả tệp socket để máy ảo có thể thăm dò ý kiến ​​và gọi lại trình điều khiển khi bộ mô tả tệp có thể đọc được.

Tính năng thứ hai cung cấp một nhóm luồng riêng biệt hữu ích cho các tác vụ trình điều khiển không phù hợp với giới hạn thời gian thực thi mã gốc của chuỗi lịch trình. Bạn có thể đạt được như vậy trong một NIF nhưng bạn phải thiết lập hồ bơi thread của riêng bạn và viết mã riêng của bạn để quản lý và truy cập nó. Tuy nhiên, bất kể bạn sử dụng trình điều khiển không đồng bộ, nhóm chủ đề NIF của riêng bạn hay các trình lập lịch bẩn, hãy lưu ý rằng tất cả chúng đều là các luồng hệ điều hành thông thường, và vì vậy việc bắt đầu một số lượng lớn chúng đơn giản là không thực tế.

Mã trình điều khiển gốc chưa có quyền truy cập bộ lập lịch bẩn, nhưng công việc này đang diễn ra và có thể trở thành tính năng thử nghiệm trong bản phát hành 18x.

Nếu mã Lua của bạn có thể sử dụng một hoặc nhiều tính năng này để hợp tác với máy ảo Erlang, thì những gì bạn đang cố gắng có thể thực hiện được.

+0

Cảm ơn bạn đã giải thích sâu sắc. Điều này đã làm sáng tỏ rất nhiều cho tôi. Tôi sẽ nghiên cứu các tùy chọn này và xem liệu tôi có thể tìm ra giải pháp hay không. Cảm ơn một lần nữa! – Attic

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