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.Go
function đượ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ụngthreading
thư 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.
Tiếp theo, tôi sẽ đưa bạn để hiểu từng chức năng một một.
Các__Thread
function 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 chofunc1
Chú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))
})
}
Trong ví dụ trên, chúng tôi đã sử dụng__threadJoin
chứ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.ret
nhận được giá trị trả về của__threadJoin
hà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}
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 chuỗi chủ yếu sử dụng__threadPostMessage
chức năng và__threadPeekMessage
Hã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__threadPostMessage
function đượ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__threadPeekMessage
function đượ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.
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.
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.
Đị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ì.
WebAssembly
làWASM
, WebAssembly
là một định dạng mã hóa mới và có thể chạy trong trình duyệt,WASM
có thể được sử dụng vớiJavaScript
tồ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.
// Recursive algorithm of Fibonacci Numbers in C Language
int fib(int f) {
if (f < 2) return f;
return fib(f - 1) + fib(f - 2);
}
// 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:
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);
}
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ã.
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.
Tạo một mẫu wasm instance thông qua hàmwasm.buildInstance()
được tích hợp bởi FMZ.
Vậy gọi chofib
chức năng trong trường hợp mô hình wasm này, cụ thể là:ret = instance.callFunction('fib', input)
.
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.
wasm
vàJavaScript
so 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ưwasm
mất ít thời gian hơn và tốt hơn.