При разработке стратегий на FMZ с использованием языка JavaScript, поскольку архитектура стратегии опрошена.exchange.Go
функция используется для одновременных вызовов на некоторые интерфейсы, чтобы удовлетворить требования некоторых одновременных сценариев. Но если вы хотите создать одну нить для выполнения серии операций, это невозможно. Например, как язык Python, используйтеthreading
Библиотека для одновременного проектирования.
Основываясь на этом требовании, платформа FMZ обновила нижний слой системы.
Далее я приведу вас к пониманию каждой функции одну за другой.
В__Thread
функция может создавать нить и выполнять функцию одновременно.func1
, что делаетfunc1
Чтобы увидеть процесс постепенного накопления, мы используем петлю for в функции func1 для паузы каждый раз (функция 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 используется для отправки сообщения в нить. Первый параметр - это идентификатор конкретной нитки для отправки, а второй параметр - это сообщение, которое должно быть отправлено, которое может быть строкой, значением, массивом или объектом JSON и так далее. Сообщения могут быть отправлены в основную нить в одновременных функциях нитки, а идентификатор основной нитки определяется как 0.
В__threadPeekMessage
function используется для мониторинга сообщения, отправленного определенной нитью. Первый параметр - это мониторинг конкретного ID нитки. Второй параметр может устанавливать время выхода (в миллисекундах), или он может быть установлен на -1, что означает блокировку, и он не вернется, пока не будет сообщения. Мы можем слушать сообщение, отправленное главной нитью текущей нитке в функции параллельной нитки, и ID главной нитки определяется как 0.
Конечно, за исключением параллельных потоков, которые общаются с основной нитью.
В примере выше,var id = __threadId()
используется, и__threadId()
Функция может получить идентификатор текущей нитки.
В дополнение к коммуникации между потоками, общие переменные также могут использоваться для взаимодействия.
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.
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
// Рекурсивный алгоритм чисел Фибоначчи на языке C Инт фиб ((инт ф) { если (f < 2) возвращает f; возвращается fib ((f - 1) + fib ((f - 2)); Я не знаю.
- JavaScript language version of the algorithm, fib function
// рекурсивный алгоритм для тех же чисел Фибоначчи, написанный в JavaScript функция fib ((f) { если (f < 2) возвращает f возвращение fib ((f - 1) + fib ((f - 2) Я не знаю.
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:
функция main() {
// Для того, чтобы сделать его проще увидеть код, я пишу комментарий на следующий код напрямую:
пусть цикл = 100 // Тест выполняет петлю 100 раз
пусть вход = 30 // Параметры, которые будут переданы в алгоритм функции fib
пусть нитки = [
__Thread(function(cycle, input) { // Завод создается одновременно для выполнения вычислений с использованием версии JavaScript функции fib
функция fib ((f) { // Специфический алгоритм, используемый для тестирования, функция fib
если (f < 2) возвращает f
возвращение fib ((f - 1) + fib ((f - 2)
Я не знаю.
пусть ret = 0
для (пусть i = 0; i < цикл; i++) { // петля в течение 100 раз
ret = fib(input); // Вызвать функцию fib языка JavaScript
Логотип прогресса JavaScript:
__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/
// Рекурсивный алгоритм чисел Фибоначчи на языке C Инт фиб ((инт ф) { если (f < 2) возвращает f; возвращается fib ((f - 1) + fib ((f - 2)); Я не знаю.
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 информация # 2 была ФИБ: 832040 истек: 13283.773019
2023-03-06 11:00:33 infomation #1 javascript fib: 832040 истек: 21266.326974
It seems that
Было бы лучше, если бы у меня было меньше времени.