Bei der Entwicklung von Strategien auf FMZ mit der JavaScript-Sprache, da die Strategie-Architektur befragt wird.exchange.Go
Funktion wird verwendet, um gleichzeitige Aufrufe an einige Schnittstellen zu tätigen, um die Anforderungen einiger gleichzeitiger Szenarien zu erfüllen.threading
Bibliothek, um gleichzeitig etwas zu entwerfen.
Aufgrund dieser Anforderung hat die FMZ-Plattform die untere Schicht des Systems aktualisiert.
Als Nächstes werde ich Sie dazu bringen, jede Funktion einzeln zu verstehen.
Die__Thread
Funktion kann einen Thread erstellen und eine Funktion gleichzeitig ausführen.func1
, was macht diefunc1
Wir können es von 0 bis 9 akkumulieren lassen. Um den schrittweisen Akkumulationsprozess zu sehen, verwenden wir die For-Schleife in der Funktion func1 um jedes Mal (die Sleep-Funktion wird für eine bestimmte Anzahl von Millisekunden zum Schlafen verwendet) für einen bestimmten Zeitraum zu pausieren.
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)
}
In praktischen Anwendungen können wir http-Anfragen gleichzeitig so machen:
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))
})
}
In dem obigen Beispiel haben wir die__threadJoin
Funktion in der Hauptfunktion endlich warten, bis die gleichzeitigen Threads zu beenden ausführen.ret
erhält den Rückgabewert der__threadJoin
Funktion, und wir drucken den Rückgabewert, können wir die spezifischen Ergebnisse der gleichzeitigen Thread-Ausführung beobachten.
// 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
}
Wir verwenden immer noch das Beispiel gerade jetzt, nachdem Sie einen Thread erstellt haben, können Sie die Ausführung des Threads nach einem Wartezeitraum von 1 Sekunde zwangsweise beenden.
Die Inter-Thread-Kommunikation nutzt hauptsächlich die__threadPostMessage
Funktion und__threadPeekMessage
Wir wollen uns das folgende einfache Beispiel ansehen:
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)
}
}
Die__threadPostMessage
Der erste Parameter ist die ID des spezifischen Threades, an den gesendet werden soll, und der zweite Parameter ist die zu versendende Nachricht, die eine Zeichenfolge, ein Wert, ein Array oder ein JSON-Objekt sein kann. Nachrichten können in gleichzeitigen Threadfunktionen an den Hauptthread gesendet werden, und die ID des Hauptthreads ist als 0 definiert.
Die__threadPeekMessage
Der erste Parameter ist die Überwachung der spezifischen ID des Threads. Der zweite Parameter kann die Timeout-Zeit (in Millisekunden) festlegen, oder er kann auf -1 gesetzt werden, was bedeutet, dass er blockiert wird, und er wird nicht zurückkehren, bis es eine Nachricht gibt. Wir können die Nachricht hören, die vom Hauptthread an den aktuellen Thread in der gleichzeitigen Thread-Funktion gesendet wird, und die ID des Hauptthreads ist als 0 definiert.
Natürlich, mit Ausnahme von gleichzeitigen Threads, die mit dem Hauptthread kommunizieren. Gleichzeitige Threads können auch direkt miteinander kommunizieren.
In dem obigen Beispielvar id = __threadId()
Die__threadId()
Funktion kann die ID des aktuellen Threads erhalten.
Zusätzlich zur Kommunikation zwischen Threads können geteilte Variablen auch für die Interaktion verwendet werden.
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
}
Das ist eine einfache Demonstration aller Funktionen. Schauen wir uns ein etwas komplizierteres Testbeispiel an.
Diese Teststrategie richtet sich an:https://www.fmz.com/strategy/401463
Auf den ersten Blick wissen Sie vielleicht nicht, was diese Teststrategie bewirkt.Es spielt keine Rolle, lassen Sie uns es erklären.Zuerst lernen wir, was WASM ist.
WebAssembly
istWASM
, WebAssembly
ist ein neues Codierungsformat und kann im Browser ausgeführt werden,WASM
kann mitJavaScript
und WASM ist eher wie eine Assembler-Sprache auf niedriger Ebene.
Dann ist die Teststrategie, die Ausführungsfähigkeit von wasm und javascript zu vergleichen, aber beim Vergleich können die beiden Ausführungsmethoden sukzessive ausgeführt werden, und der zeitaufwendige Wert jedes wird gezählt. Es ist auch möglich, die beiden Ausführungsmethoden gleichzeitig auszuführen, und die Statistiken sind zeitaufwändig. Jetzt, da die zugrunde liegende gleichzeitige Implementierung der JavaScript-Sprachstrategie unterstützt wurde, verwendet die Teststrategie eine gleichzeitige Methode, um die Ausführungsgeschwindigkeit desselben Algorithmus natürlich zu vergleichen und zu vergleichen.
// 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)
}
Es kann gesehen werden, dass die Logik der beiden Fib-Funktionsalgorithmen genau gleich ist.
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
})
}
Einfach ausgedrückt, WASM ist ein Programmcode mit höherer Ausführungsfähigkeit. Im Beispiel konvertieren wir den C-Sprachcode des
Wir können die Website verwenden, um zu konvertieren: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);
}
Die folgenden Befehle können verwendet werden:
python -c "print('data:hex,'+bytes.hex(open('program.wasm','rb').read()))"
Die verschlüsselte Hex-String istlet data = 'data:hex,0061736d0100000001868...
in den Code.
Dann analysieren Sie es in ein Wasm-Modell durch die Funktionwasm.parseModule()
integriert durch FMZ.
Erstellen Sie eine wasm-Modell-Instanz über die Funktionwasm.buildInstance()
integriert durch FMZ.
Dann rufen Sie diefib
Funktion in dieser wasm-Modell-Instanz, nämlich:ret = instance.callFunction('fib', input)
.
Diese Teststrategie kann nur für echte Bot-Tests verwendet werden. JavaScript Multi-Threading-Funktionen unterstützen bisher kein Backtesting.
wasm
undJavaScript
Vergleich der Ausführung, endgültige Ausführungsergebnisse:
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
Es scheint, dasswasm
dauert weniger Zeit und ist besser.