Ao desenvolver estratégias no FMZ usando a linguagem JavaScript, uma vez que a arquitetura da estratégia é pesquisada.exchange.Go
A função é usada para fazer chamadas simultâneas para algumas interfaces, de modo a atender aos requisitos de alguns cenários simultâneos. Mas se você quiser criar um único thread para realizar uma série de operações, é impossível.threading
biblioteca para fazer algum design simultâneo.
Com base neste requisito, a plataforma FMZ atualizou a camada inferior do sistema.
Em seguida, vou levá-lo a entender cada função uma por uma.
O__Thread
Por exemplo, você precisa criar uma função simultâneafunc1
, o que faz ofunc1
Para ver o processo de acumulação gradual, usamos o loop for na função func1 para pausar cada vez (a função Sleep é usada para dormir por um certo número de milissegundos) por um determinado período de tempo.
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)
}
Em aplicações práticas, podemos fazer solicitações http simultaneamente assim:
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))
})
}
No exemplo acima, usamos o__threadJoin
função na função principal finalmente para esperar que os tópicos concorrentes para terminar de executar.ret
recebe o valor de retorno do__threadJoin
função, e imprimimos o valor de retorno, podemos observar os resultados específicos da execução simultânea do thread.
// 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
}
Ainda usamos o exemplo agora, depois de criar um thread, você pode forçar a encerrar a execução do thread depois de esperar por 1 segundo.
A comunicação inter-thread utiliza principalmente o__threadPostMessage
Função e__threadPeekMessage
Vejamos o seguinte exemplo simples:
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)
}
}
O__threadPostMessage
O primeiro parâmetro é o ID do thread específico para enviar, e o segundo parâmetro é a mensagem a ser enviada, que pode ser uma cadeia, um valor, uma matriz ou um objeto JSON e assim por diante. As mensagens podem ser enviadas para o thread principal em funções de thread simultâneas, e o ID do thread principal é definido como 0.
O__threadPeekMessage
A função é usada para monitorar a mensagem enviada por um determinado thread. O primeiro parâmetro é monitorar o ID específico do thread. O segundo parâmetro pode definir o tempo de tempo (em milissegundos), ou pode ser definido como -1, o que significa bloqueio, e não retornará até que haja uma mensagem. Podemos ouvir a mensagem enviada pelo thread principal para o thread atual na função de thread concorrente, e o ID do thread principal é definido como 0.
Claro, exceto para threads simultâneos que se comunicam com o thread principal.
No exemplo acima,var id = __threadId()
A utilização de__threadId()
função pode obter a ID do tópico atual.
Além da comunicação entre threads, variáveis compartilhadas também podem ser usadas para interação.
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
}
O exemplo acima é uma demonstração simples de todas as funções.
Este endereço da estratégia de ensaio:https://www.fmz.com/strategy/401463
Em primeiro lugar, vamos aprender o que é o WASM.
Then the test strategy is to compare the execution efficiency of wasm and javascript, but when comparing, the two execution methods can be executed successively, and the time-consuming of each is counted. It is also possible to allow the two execution methods to execute concurrently, and the statistics are time-consuming. Now that the underlying concurrency implementation of the JavaScript language strategy has been supported, the test strategy uses a concurrent method to compare naturally and compare the execution speed of the same algorithm.
- Algorithm of C language version, fib function
// Algoritmo recursivo de números de Fibonacci em linguagem C int fib ((int f) { se (f < 2) retornar f; Retorno fib ((f - 1) + fib ((f - 2); - Não.
- JavaScript language version of the algorithm, fib function
// Um algoritmo recursivo para os mesmos números de Fibonacci, escrito em JavaScript Função fib ((f) { se (f < 2) retornar f Retorno fib ((f - 1) + fib ((f - 2) - Não.
It can be seen that the logic of the two fib function algorithms is exactly the same. The following is the source code of the test strategy:
função principal (() {
// A fim de tornar mais fácil ver o código, escrevo o comentário sobre o seguinte código diretamente:
deixe ciclo = 100 // O teste executa o loop 100 vezes
deixe entrada = 30 // Os parâmetros que serão passados para o algoritmo fib função
deixe os fios = [
__Thread(function(cycle, input) { // Um thread é criado simultaneamente para executar cálculos usando a versão JavaScript da função fib
Função fib ((f) { // O algoritmo específico utilizado para testes, a função fib
se (f < 2) retornar f
Retorno fib ((f - 1) + fib ((f - 2)
- Não.
Let ret = 0
para (i = 0; i < ciclo; i++) { // ciclo por 100 vezes
ret = fib(input); // Chamar a função fib da linguagem JavaScript
Log ((
__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
})
}
Simply put, WASM is a program code with higher execution efficiency. In the example, we convert the c language code of "Fibonacci number recursive algorithm" into WASM. The process is like this:
1. Compile a piece of C language function code into wasm code.
We can use the website to convert: https://wasdk.github.io/WasmFiddle/
// Algoritmo recursivo de números de Fibonacci em linguagem C int fib ((int f) { se (f < 2) retornar f; Retorno fib ((f - 1) + fib ((f - 2); - Não.
2. Further encode the wasm code into a hex string.
The following commands can be used:
python -c
The encoded hex string is ```let data = 'data:hex,0061736d0100000001868...``` in the code.
3. Then parse it into a wasm model through the function ```wasm.parseModule()``` integrated by FMZ.
4. Create a wasm model instance through the function ```wasm.buildInstance()``` integrated by FMZ.
5. Then call the ```fib``` function in this wasm model instance, namely: ```ret = instance.callFunction('fib', input)```.
## Create a real bot to run the test
This test strategy can only be used for real bot testing. JavaScript multi-threading functions do not support backtesting so far.
```wasm``` and ```JavaScript``` execution comparison, the final execution results:
2023-03-06 11:00:33 Informação # 2 foi fib: 832040 expirado: 13283.773019
2023-03-06 11:00:33 infomation #1 javascript fib: 832040 expired: 21266.326974
It seems that
O "wasm" leva menos tempo e é melhor.