जावास्क्रिप्ट मल्टीथ्रेडिंग समर्थन के साथ समवर्ती रणनीति निष्पादन

लेखक:लिडिया, बनाया गयाः 2023-03-07 15:12:04, अद्यतन किया गयाः 2023-09-18 20:04:21

img

रणनीति कार्यक्रम एक साथ निष्पादित होने दें, और जावास्क्रिप्ट रणनीति के लिए प्रणाली के नीचे बहु-थ्रेड समर्थन जोड़ें

जब जावास्क्रिप्ट भाषा का उपयोग करके एफएमजेड पर रणनीतियों का विकास करते हैं, क्योंकि रणनीति वास्तुकला को सर्वेक्षण किया जाता है।exchange.Gofunction का उपयोग कुछ इंटरफेस को समवर्ती कॉल करने के लिए किया जाता है, ताकि कुछ समवर्ती परिदृश्यों की आवश्यकताओं को पूरा किया जा सके। लेकिन यदि आप संचालन की एक श्रृंखला करने के लिए एक एकल थ्रेड बनाना चाहते हैं, तो यह असंभव है। उदाहरण के लिए पायथन भाषा की तरह,threadingकुछ समवर्ती डिजाइन करने के लिए पुस्तकालय.

इस आवश्यकता के आधार पर, एफएमजेड प्लेटफॉर्म ने सिस्टम की निचली परत को अपग्रेड किया है। जावास्क्रिप्ट भाषा में सच्चे मल्टीथ्रेडिंग समर्थन को भी जोड़ा गया है। विस्तृत सुविधाओं में शामिल हैंः

  • कस्टम फ़ंक्शन को एक साथ निष्पादित करने के लिए थ्रेड बनाएं.
  • इंटर-थ्रेड संचार।
  • साझा किए गए थ्रेडों के बीच संग्रहीत चर.
  • संसाधनों को पुनः प्राप्त करने और निष्पादन परिणाम वापस करने के लिए निष्पादन समाप्त करने के लिए थ्रेड की प्रतीक्षा करें.
  • बलपूर्वक धागे को समाप्त करें और संसाधनों को पुनः प्राप्त करें।
  • समवर्ती थ्रेड निष्पादन फ़ंक्शन में वर्तमान थ्रेड आईडी प्राप्त करें.

आगे, मैं आपको प्रत्येक फ़ंक्शन को एक-एक करके समझने के लिए ले जाऊंगा।

एक साथ कस्टम फ़ंक्शन निष्पादित करने के लिए थ्रेड बनाएँ

..__Threadfunction एक थ्रेड बना सकता है और एक साथ एक फ़ंक्शन निष्पादित कर सकता है. उदाहरण के लिए, आपको एक समवर्ती फ़ंक्शन बनाने की आवश्यकता हैfunc1, क्या करता हैfunc1हम इसे 0 से 9 तक जमा करने दे सकते हैं। क्रमिक जमा होने की प्रक्रिया को देखने के लिए, हम प्रत्येक बार ठहराव करने के लिए func1 फ़ंक्शन में 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)
    }
}

..__threadPostMessagefunction का उपयोग किसी थ्रेड को संदेश भेजने के लिए किया जाता है। पहला पैरामीटर विशिष्ट थ्रेड की आईडी है जिसे भेजा जाना है, और दूसरा पैरामीटर संदेश भेजा जाना है, जो एक स्ट्रिंग, एक मान, एक सरणी, या एक JSON ऑब्जेक्ट और इतने पर हो सकता है। संदेशों को समवर्ती थ्रेड कार्यों में मुख्य थ्रेड को भेजा जा सकता है, और मुख्य थ्रेड की आईडी 0 के रूप में परिभाषित की गई है।

..__threadPeekMessagefunction का उपयोग किसी निश्चित थ्रेड द्वारा भेजे गए संदेश की निगरानी करने के लिए किया जाता है। पहला पैरामीटर थ्रेड की विशिष्ट आईडी की निगरानी करना है। दूसरा पैरामीटर टाइमआउट समय (मिलीसेकंड में) सेट कर सकता है, या इसे -1 पर सेट किया जा सकता है, जिसका अर्थ है अवरोधित करना, और यह तब तक वापस नहीं आएगा जब तक कि कोई संदेश न हो। हम समवर्ती थ्रेड फ़ंक्शन में वर्तमान थ्रेड को मुख्य थ्रेड द्वारा भेजे गए संदेश को सुन सकते हैं, और मुख्य थ्रेड की आईडी को 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
}

उपरोक्त सभी कार्यों का एक सरल प्रदर्शन है। चलो थोड़ा अधिक जटिल परीक्षण उदाहरण देखें।

मूल बहु-थ्रेडेड जावास्क्रिप्ट और WASM के बीच प्रदर्शन तुलना

यह परीक्षण रणनीति पताःhttps://www.fmz.com/strategy/401463

एक नज़र में, आप यह नहीं जान सकते कि यह परीक्षण रणनीति क्या करती है। इससे कोई फर्क नहीं पड़ता, आइए इसे समझाते हैं। सबसे पहले, आइए जानें कि WASM क्या है।

WebAssemblyहैWASM, WebAssemblyएक नया एन्कोडिंग प्रारूप है और ब्राउज़र में चलाया जा सकता है,WASMके साथ इस्तेमाल किया जा सकता हैJavaScriptसह-अस्तित्व में है, और WASM कम स्तर की असेंबली भाषा की तरह है।

फिर परीक्षण रणनीति wasm और जावास्क्रिप्ट की निष्पादन दक्षता की तुलना करना है, लेकिन तुलना करते समय, दो निष्पादन विधियों को क्रमिक रूप से निष्पादित किया जा सकता है, और प्रत्येक की समय लेने वाली गणना की जाती है। दो निष्पादन विधियों को समवर्ती रूप से निष्पादित करने की अनुमति देना भी संभव है, और आंकड़े समय लेने वाले हैं। अब जब जावास्क्रिप्ट भाषा रणनीति के अंतर्निहित समवर्ती कार्यान्वयन का समर्थन किया गया है, तो परीक्षण रणनीति एक ही एल्गोरिथ्म की निष्पादन गति की तुलना करने और तुलना करने के लिए एक समवर्ती विधि का उपयोग करती है।

  • सी भाषा संस्करण का एल्गोरिथ्म, fib फलन
// Recursive algorithm of Fibonacci Numbers in C Language
int fib(int f) {
    if (f < 2) return f;
    return fib(f - 1) + fib(f - 2);
}
  • एल्गोरिथ्म का जावास्क्रिप्ट भाषा संस्करण, fib फंक्शन
// 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)
}

यह देखा जा सकता है कि दो फाइब फ़ंक्शन एल्गोरिदम का तर्क बिल्कुल समान है। निम्नलिखित परीक्षण रणनीति का स्रोत कोड हैः

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 एक उच्च निष्पादन दक्षता वाला प्रोग्राम कोड है। उदाहरण में, हम फिबोनाची संख्या पुनरावर्ती एल्गोरिथ्म के सी भाषा कोड को WASM में परिवर्तित करते हैं। प्रक्रिया इस तरह हैः

  1. सी भाषा के फ़ंक्शन कोड का एक टुकड़ा 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);
}
  1. इसके अलावा एक हेक्स स्ट्रिंग में Wasm कोड एन्कोड करें।

निम्नलिखित आदेशों का उपयोग किया जा सकता हैः

python -c "print('data:hex,'+bytes.hex(open('program.wasm','rb').read()))"

एन्कोडेड हेक्स स्ट्रिंग हैlet data = 'data:hex,0061736d0100000001868...कोड में।

  1. फिर फ़ंक्शन के माध्यम से इसे एक ओसम मॉडल में पार्स करेंwasm.parseModule()एफएमजेड द्वारा एकीकृत।

  2. फ़ंक्शन के माध्यम से एक wasm मॉडल उदाहरण बनाएँwasm.buildInstance()एफएमजेड द्वारा एकीकृत।

  3. तो कॉल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कम समय लगता है और बेहतर है।


संबंधित

अधिक