Thực thi chiến lược đồng thời với hỗ trợ đa luồng JavaScript

Tác giả:Lydia., Tạo: 2023-03-07 15:12:04, Cập nhật: 2023-09-18 20:04:21

img

Hãy cho chương trình chiến lược được thực hiện đồng thời, và thêm hỗ trợ nhiều luồng ở phía dưới của hệ thống để chiến lược JavaScript

Khi phát triển các chiến lược trên FMZ sử dụng ngôn ngữ JavaScript, vì kiến trúc chiến lược được khảo sát.exchange.Gofunction được sử dụng để thực hiện các cuộc gọi đồng thời đến một số giao diện, để đáp ứng các yêu cầu của một số kịch bản đồng thời. Nhưng nếu bạn muốn tạo một luồng duy nhất để thực hiện một loạt các hoạt động, nó là không thể. Ví dụ như ngôn ngữ Python, sử dụngthreadingthư viện để làm một số thiết kế đồng thời.

Dựa trên yêu cầu này, nền tảng FMZ đã nâng cấp lớp dưới của hệ thống.

  • Tạo các chủ đề để thực hiện các chức năng tùy chỉnh đồng thời.
  • Giao tiếp giữa các chuỗi.
  • Các biến được lưu trữ giữa các chủ đề được chia sẻ.
  • Chờ cho chủ đề hoàn thành thực thi để lấy lại tài nguyên và trả lại kết quả thực thi.
  • Tấn công sức mạnh và lấy lại tài nguyên.
  • Nhận ID chủ đề hiện tại trong hàm thực thi chủ đề đồng thời.

Tiếp theo, tôi sẽ đưa bạn để hiểu từng chức năng một một.

Tạo các chủ đề để thực thi các hàm tùy chỉnh đồng thời

Các__Threadfunction có thể tạo một chủ đề và thực thi một hàm đồng thời. ví dụ, bạn cần tạo một hàm đồng thờifunc1, điều gì làm chofunc1Chúng ta có thể để nó tích lũy từ 0 đến 9. Để xem quá trình tích lũy dần dần, chúng ta sử dụng vòng lặp for trong hàm func1 để tạm dừng mỗi lần (chức năng Sleep được sử dụng để ngủ trong một số lượng nhất định của milliseconds) trong một khoảng thời gian nhất định.

function func1(sleepMilliseconds) {
    var sum = 0 
    for (var i = 0 ; i < 10 ; i++) {
        sum += i 
        Sleep(sleepMilliseconds)
        Log("sum:", sum)
    }
    
    return sum
}

function main() {
    // Use the __Thread function to create a thread concurrently, and the parameter 200 is the parameter of the func1 function,
    // If the func1 function has multiple parameters, here we pass the corresponding parameters.
    var thread1Id = __Thread(func1, 200)
    
    // Here we need to wait for the execution result of the thread whose thread Id is thread1Id, otherwise all threads will be released directly after the main function is executed.
    var ret = __threadJoin(thread1Id)
    Log("ret:", ret)
}

Trong các ứng dụng thực tế, chúng ta có thể thực hiện các yêu cầu http đồng thời như thế này:

function main() {
    let threads = [
        "https://www.baidu.com",
        "https://www.163.com"
    ].map(function(url) {
        return __Thread(function(url) {
            Log("GET", url)
            return HttpQuery(url)
        }, url)
    })
    threads.forEach(function(tid) {
        Log(__threadJoin(tid))
    })
}

Chờ cho kết thúc thực thi thread để lấy lại tài nguyên và trả về kết quả thực thi

Trong ví dụ trên, chúng tôi đã sử dụng__threadJoinchức năng trong chức năng chính cuối cùng để chờ cho các luồng đồng thời để hoàn thành thực thi.retnhận được giá trị trả về của__threadJoinhàm, và chúng tôi in giá trị trả về, chúng tôi có thể quan sát các kết quả cụ thể của việc thực hiện chuỗi đồng thời.

// id: thread ID, terminated: whether it was forced to stop, elapsed: time-consuming (nanoseconds), ret: the return value of the thread execution function
ret: {"id":1,"terminated":false,"elapsed":2004884301,"ret":45}

Kết thúc các thread bằng vũ lực và lấy lại tài nguyên

function func1(sleepMilliseconds) {
    var sum = 0 
    for (var i = 0 ; i < 10 ; i++) {
        sum += i 
        Sleep(sleepMilliseconds)
        Log("sum:", sum)
    }
    
    return sum
}

function main() {
    var thread1Id = __Thread(func1, 200)
    Sleep(1000)
    retThreadTerminate = __threadTerminate(thread1Id)
    Log(retThreadTerminate)   // true
}

Chúng tôi vẫn sử dụng ví dụ ngay bây giờ, sau khi tạo một chủ đề, bạn có thể buộc phải chấm dứt việc thực hiện chủ đề sau khi chờ đợi 1 giây.

Truyền thông giữa các chủ đề

Truyền thông giữa các chuỗi chủ yếu sử dụng__threadPostMessagechức năng và__threadPeekMessageHãy xem ví dụ đơn giản sau:

function func1() {
    var id = __threadId()
    while (true) {
        var postMsg = "Message from thread function func1" with "from id:" + id + 
        __threadPostMessage(0, postMsg)              // Send a message to the main thread
        var peekMsg = __threadPeekMessage(0)         // Receive messages from the main thread
        Log(peekMsg)
        Sleep(5000)
    }
}

function main() {
    var threadId = __Thread(func1)
    
    while (true) {
        var postMsg = "Messages from the main function of the main thread"
        __threadPostMessage(threadId, postMsg)
        var peekMsg = __threadPeekMessage(threadId)
        Log(peekMsg, "#FF0000")                     // #FF0000 , Set the log to red for distinction
        Sleep(5000)
    }
}

Các__threadPostMessagefunction được sử dụng để gửi tin nhắn đến một thread. Parameter đầu tiên là ID của thread cụ thể để gửi đến, và tham số thứ hai là tin nhắn để gửi, có thể là một chuỗi, một giá trị, một mảng, hoặc một đối tượng JSON và vân vân. Tin nhắn có thể được gửi đến chủ đề chủ đề trong các hàm chủ đề đồng thời, và ID của chủ đề chủ đề được định nghĩa là 0.

Các__threadPeekMessagefunction được sử dụng để theo dõi thông điệp được gửi bởi một chủ đề nhất định. Parameter đầu tiên là để theo dõi ID cụ thể của chủ đề. Parameter thứ hai có thể thiết lập thời gian hết thời gian (trong milliseconds), hoặc nó có thể được thiết lập thành -1, có nghĩa là chặn, và nó sẽ không trở lại cho đến khi có một thông điệp. Chúng ta có thể nghe thông điệp được gửi bởi chủ đề chính đến chủ đề hiện tại trong hàm chủ đề đồng thời, và ID của chủ đề chính được định nghĩa là 0.

Tất nhiên, ngoại trừ các luồng liên lạc đồng thời với luồng chính, luồng liên lạc đồng thời cũng có thể liên lạc trực tiếp với nhau.

Nhận ID chủ đề hiện tại trong hàm thực thi chủ đề đồng thời

Trong ví dụ trên,var id = __threadId()được sử dụng, và__threadId()hàm có thể nhận được ID của chủ đề hiện tại.

Các biến được lưu trữ giữa các luồng chia sẻ

Ngoài giao tiếp giữa các chủ đề, các biến được chia sẻ cũng có thể được sử dụng để tương tác.

function testFunc() {
    __threadSetData(0, "testFunc", 100)   // Stored in the current thread environment, key-value pair testFunc : 100
    Log("testFunc execution completed")
}

function main() {
    // threadId is 1, the created thread with threadId 1 will be executed first, as long as the thread resources are not reclaimed, the variables stored locally in the thread will be valid
    var testThread = __Thread(testFunc)
    
    Sleep(1000)

    // export in main, get testFunc: 100
    Log("in main, get testFunc:", __threadGetData(testThread, "testFunc"))   // Take out the value whose key name is testFunc
}

Điều trên là một minh chứng đơn giản của tất cả các hàm.

So sánh hiệu suất giữa JavaScript đa luồng gốc và WASM

Địa chỉ chiến lược thử nghiệm này:https://www.fmz.com/strategy/401463

Một cái nhìn, bạn có thể không biết chiến lược thử nghiệm này làm gì. Nó không quan trọng, hãy giải thích nó. Trước tiên, hãy tìm hiểu WASM là gì.

WebAssemblyWASM, WebAssemblylà một định dạng mã hóa mới và có thể chạy trong trình duyệt,WASMcó thể được sử dụng vớiJavaScripttồn tại cùng nhau, và WASM giống như một ngôn ngữ assembly cấp thấp.

Sau đó, chiến lược thử nghiệm là so sánh hiệu quả thực thi của wasm và javascript, nhưng khi so sánh, hai phương pháp thực thi có thể được thực hiện liên tiếp, và thời gian tiêu tốn của mỗi phương pháp được tính. Nó cũng có thể cho phép hai phương pháp thực thi thực hiện đồng thời, và thống kê tốn thời gian. Bây giờ khi thực hiện đồng thời cơ bản của chiến lược ngôn ngữ JavaScript đã được hỗ trợ, chiến lược thử nghiệm sử dụng phương pháp đồng thời để so sánh tự nhiên và so sánh tốc độ thực thi của cùng một thuật toán.

  • Algorithm của phiên bản ngôn ngữ C, hàm fib
// Recursive algorithm of Fibonacci Numbers in C Language
int fib(int f) {
    if (f < 2) return f;
    return fib(f - 1) + fib(f - 2);
}
  • Phiên bản ngôn ngữ JavaScript của thuật toán, hàm fib
// A recursive algorithm for the same Fibonacci numbers, written in JavaScript
function fib(f) {
    if (f < 2) return f
    return fib(f - 1) + fib(f - 2)
}

Có thể thấy rằng logic của hai thuật toán hàm fib là chính xác như nhau.

function main() {
    // In order to make it easier to see the code, I write the comment on the following code directly:
    let cycle = 100    // The test executes the loop 100 times
    let input = 30     // The parameters that will be passed to the algorithm fib function
    let threads = [
        __Thread(function(cycle, input) {           // A thread is created concurrently to perform calculations using the JavaScript version of the fib function
            function fib(f) {                       // The specific algorithm used for testing, the fib function
                if (f < 2) return f
                return fib(f - 1) + fib(f - 2)
            }
            let ret = 0
            for (let i = 0; i < cycle; i++) {       // loop for 100 times 
                ret = fib(input);                   // Call the fib function of the JavaScript language 
                Log("javascript progress: ", i)
            }
            return 'javascript fib: ' + ret
        }, cycle, input),
        
        __Thread(function(cycle, input) {           // Run a thread concurrently to perform calculations using the wasm version of the fib function
            let data = 'data:hex,0061736d010000000186808080000160017f017f0382808080000100048480808000017000000583808080000100010681808080000007908080800002066d656d6f727902000366696200000aa480808000019e80808000000240200041024e0d0020000f0b2000417f6a10002000417e6a10006a0b'
            let m = wasm.parseModule(data)          // The data variable is the hex string of the wasm-encoded C language fib function, and the wasm model m is created using wasm.parseModule

            let instance = wasm.buildInstance(m, {  // Model instantiation, allocate a certain stack space
                stack_size: 65 * 1024 * 1024,
            })

            let ret = 0
            for (let i = 0; i < cycle; i++) {                // loop for 100 times 
                ret = instance.callFunction('fib', input)    // Calling the fib function code in the wasm instance is equivalent to calling the int fib(int f) function 
                Log("wasm progress: ", i)
            }

            return 'wasm fib: ' + ret
        }, cycle, input)
    ]
    
    // The elements in the threads array are the IDs returned by the __Thread function
    threads.forEach(function(tid) {
        let info = __threadJoin(tid)                         // Use the __threadJoin function to wait for two concurrent threads to execute and get the execution result
        Log('#'+tid, info.ret, 'elapsed:', info.elapsed / 1e6, "#ff0000")   // output execution result
    })
}

Nói một cách đơn giản, WASM là một mã chương trình có hiệu quả thực thi cao hơn. Trong ví dụ, chúng tôi chuyển đổi mã ngôn ngữ c của thuật toán tái diễn số Fibonacci thành WASM. Quá trình như thế này:

  1. Tóm lại một phần mã hàm ngôn ngữ C thành mã wasm.

Chúng ta có thể sử dụng trang web để chuyển đổi:https://wasdk.github.io/WasmFiddle/

// Recursive Algorithm of Fibonacci numbers in C Language
int fib(int f) {
    if (f < 2) return f;
    return fib(f - 1) + fib(f - 2);
}
  1. Tiếp tục mã hóa mã Wasm thành một chuỗi hex.

Các lệnh sau đây có thể được sử dụng:

python -c "print('data:hex,'+bytes.hex(open('program.wasm','rb').read()))"

Dòng mã hex được mã hóa làlet data = 'data:hex,0061736d0100000001868...trong mã.

  1. Sau đó phân tích nó thành một mô hình wasm thông qua các chức năngwasm.parseModule()được tích hợp bởi FMZ.

  2. Tạo một mẫu wasm instance thông qua hàmwasm.buildInstance()được tích hợp bởi FMZ.

  3. Vậy gọi chofibchức năng trong trường hợp mô hình wasm này, cụ thể là:ret = instance.callFunction('fib', input).

Tạo một bot thực sự để chạy thử nghiệm

Chiến lược thử nghiệm này chỉ có thể được sử dụng cho thử nghiệm bot thực sự. Các chức năng đa luồng JavaScript hiện không hỗ trợ backtesting.

wasmJavaScriptso sánh thực hiện, kết quả thực hiện cuối cùng:

2023-03-06 11:00:33		infomation	#2 wasm fib: 832040 elapsed: 13283.773019
2023-03-06 11:00:33		infomation	#1 javascript fib: 832040 elapsed: 21266.326974

Có vẻ nhưwasmmất ít thời gian hơn và tốt hơn.


Có liên quan

Thêm nữa