FMZ で戦略を開発する際に JavaScript 言語を使用する. 戦略アーキテクチャが調査されているため.exchange.Go
この関数は,いくつかのインタフェースに同時呼び出しを行うために使用され,いくつかの同時シナリオの要件を満たします. しかし,一連の操作を実行するために単一のスレッドを作成したい場合は,それは不可能です.例えば,Python言語のように,threading
図書室で並行設計をします
この要件に基づいて,FMZプラットフォームはシステムの底層をアップグレードした.JavaScript言語にも真のマルチスレッドサポートが追加された.詳細な機能には以下のものがある:
次に,各関数を"つずつ説明します.
について__Thread
例えば,同じ関数を作成する必要があります. この関数で,func1
どこにいるの?func1
0 から 9 まで蓄積させることができます. 漸進的な蓄積プロセスを確認するために, func1 関数の for ループを使用して,毎回一時停止します (Sleep 関数は一定の数ミリ秒間眠るために使用されます).
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)
}
HTTP リクエストを同時に こんな感じで作成できます
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))
})
}
この例では,__threadJoin
実行が完了するまで待つ. 変数ret
返回値が表示されます.__threadJoin
同時にスレッドを実行する特定の結果を観察できます. 実行するときに,
// 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
}
1秒間待った後 強制的にスレッドの実行を終了することができます. この例では,
スレッド間の通信は主に__threadPostMessage
機能と__threadPeekMessage
簡単な例を見てみましょう.
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)
}
}
について__threadPostMessage
function はスレッドにメッセージを送信するために使用される.最初のパラメータは送信する特定のスレッドのIDであり,第2パラメータは送信されるメッセージであり,文字列,値,配列,JSONオブジェクトなどである.メッセージは同時スレッド関数でメインスレッドに送信され,メインスレッドのIDは0と定義される.
について__threadPeekMessage
function は特定のスレッドが送信したメッセージを監視するために使用されます.最初のパラメータはスレッドの特定のIDを監視することです.第2パラメータはタイムアウト時間を (ミリ秒で) 設定したり,ブロックすることを意味する -1 に設定したりできます.メッセージが来るまで戻らないでしょう.メインスレッドが現在のスレッドに送信したメッセージを並行スレッド関数で聞くことができ,メインスレッドのIDは0と定義されます.
もちろん,メインスレッドと通信する並行スレッドを除いて.並行スレッドも互いに直接通信することができます.
この例では,var id = __threadId()
使用されている場合,__threadId()
この関数は,現在のスレッドのIDを取得できます.
スレッド間の通信に加えて,共有変数はインタラクションにも使用できます.
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
}
上記は,すべての関数の簡単な実証です. 少し複雑なテスト例を見てみましょう.
このテスト戦略のアドレス:https://www.fmz.com/strategy/401463
このテスト戦略が何をしているのか 一目でわからないかもしれません.どうでもいいです.説明しましょう.まず,WASMとは何かを知ろう.
WebAssembly
はWASM
, WebAssembly
新しい暗号化形式で ブラウザで実行できますWASM
と使用できます.JavaScript
WASMは低レベルのアセンブリ言語のようなものです
テスト戦略は, wasm と javascript の実行効率を比較することである.しかし,比較するとき,両実行方法が順に実行され,それぞれにかかる時間が計算される.また,両実行方法が同時に実行することを許可することも可能で,統計は時間がかかります.現在,JavaScript 言語戦略の基本的並行実装がサポートされているため,テスト戦略は自然に比較し,同じアルゴリズムの実行速度を比較するために並行方法を使用します.
// 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)
}
この2つのfib関数アルゴリズムの論理はまったく同じであることがわかります. 以下はテスト戦略のソースコードです.
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
})
}
簡単に言うと,WASMは実行効率が高いプログラムコードです.例では,Fibonacci数再帰アルゴリズムのc言語コードをWASMに変換します.プロセスは以下のようなものです:
ウェブサイトで変換できます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);
}
次のコマンドを使用できます:
python -c "print('data:hex,'+bytes.hex(open('program.wasm','rb').read()))"
暗号化された六角文字列はlet data = 'data:hex,0061736d0100000001868...
コードに書いてある
この関数を使って,その関数をワームモデルに解析しますwasm.parseModule()
FMZによって統合されています
関数で wasm モデルインスタンスを作成するwasm.buildInstance()
FMZによって統合されています
じゃあ電話してfib
この wasm モデルインスタンスの関数,すなわち:ret = instance.callFunction('fib', input)
.
このテスト戦略は,実際のボットテストにのみ使用できます.JavaScriptのマルチスレッド機能は,バックテストをサポートしていません.
wasm
そしてJavaScript
実行比較,最終的な実行結果:
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
明らかにwasm
時間がかかりやすく より良いのです