FMZ에 전략을 개발할 때 자바스크립트 언어를 사용 하 여 전략 아키텍처가 조사되기 때문에. 동시 설계 시나리오가 있다면,exchange.Go
이 함수는 일부 인터페이스에 동시 호출을 하기 위해 사용 됩니다. 따라서 일부 동시 시나리오의 요구 사항을 충족 합니다. 하지만 일련의 작업을 수행하기 위해 단일 스레드를 만들고 싶다면 불가능합니다. 예를 들어 파이썬 언어처럼,threading
라이브러리에서 동시에 디자인할 수 있습니다.
이 요구 사항에 따라 FMZ 플랫폼은 시스템의 하층 층을 업그레이드했습니다. 진정한 멀티 스레딩 지원 또한 자바스크립트 언어에 추가되었습니다. 자세한 기능에는 다음과 같습니다.
다음으로, 각각의 함수를 하나씩 이해하도록 하겠습니다.
이__Thread
함수는 스레드를 생성하고 함수를 동시에 실행할 수 있습니다. 예를 들어, 동시 함수를 생성해야 합니다.func1
, 무슨 일이func1
함수를 어떻게 할 수 있을까요? 우리는 0에서 9까지 축적하도록 할 수 있습니다. 점진적인 축적 과정을 보기 위해, 우리는 fun1 함수의 for 루프를 사용하여 특정 기간 동안 매번 일시 중지합니다.
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이며 두 번째 매개 변수는 문자열, 값, 배열 또는 JSON 객체 등이 될 수 있는 메시지를 전송합니다. 메시지는 동시 스레드 함수에서 메인 스레드에 전송 될 수 있으며 메인 스레드의 ID는 0으로 정의됩니다.
이__threadPeekMessage
function는 특정 스레드에서 보낸 메시지를 모니터링하는 데 사용됩니다. 첫 번째 매개 변수는 스레드의 특정 ID를 모니터링하는 것입니다. 두 번째 매개 변수는 타임 아웃 시간을 설정할 수 있습니다 (밀리 초에), 또는 차단을 의미하는 -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와 자바스크립트의 실행 효율을 비교하는 것이지만, 비교할 때 두 실행 방법을 순차적으로 실행할 수 있으며, 각각의 시간 소비가 계산됩니다. 두 실행 방법을 동시에 실행하도록 허용하는 것도 가능하며, 통계는 시간이 많이 걸립니다. 자바스크립트 언어 전략의 기본 동시 구현이 지원되었으므로, 테스트 전략은 동시 방법을 사용하여 자연스럽게 비교하고 동일한 알고리즘의 실행 속도를 비교합니다.
// 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)
}
두 개의 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은 높은 실행 효율을 가진 프로그램 코드입니다. 예제에서, 우리는
우리는 웹 사이트를 사용하여 변환할 수 있습니다: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 모델로 분석합니다wasm.parseModule()
FMZ에 의해 통합됩니다.
함수를 통해 wasm 모델 인스턴스를 생성wasm.buildInstance()
FMZ에 의해 통합됩니다.
그럼 전화해fib
이 wasm 모델 인스턴스에서 함수, 즉:ret = instance.callFunction('fib', input)
.
이 테스트 전략은 실제 봇 테스트에서만 사용할 수 있습니다. 자바스크립트 멀티 스레딩 기능은 지금까지 백테스팅을 지원하지 않습니다.
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
시간이 덜 걸리고 더 낫습니다.