Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 成人在线精品视频,精品国产一区二区三区在线,日韩美女在线

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          python struct 模塊

          python struct 模塊

          ython struct 模塊

          官方文檔:https://docs.python.org/3.7/library/struct.html?highlight=struct#module-struct

          該模塊執(zhí)行 Python 值和表示為 Python對(duì)象的 C struct 之間的轉(zhuǎn)換。bytes可用于處理存儲(chǔ)在文件中或來(lái)自網(wǎng)絡(luò)連接以及其他來(lái)源的二進(jìn)制數(shù)據(jù)。它使用 格式字符串作為 C 結(jié)構(gòu)布局的緊湊描述以及與 Python 值的預(yù)期轉(zhuǎn)換。

          默認(rèn)情況下,打包給定 C 結(jié)構(gòu)的結(jié)果包括填充字節(jié),以保持所涉及的 C 類型的正確對(duì)齊;同樣,開(kāi)箱時(shí)也會(huì)考慮對(duì)齊。選擇此行為是為了使打包結(jié)構(gòu)的字節(jié)與相應(yīng) C 結(jié)構(gòu)的內(nèi)存布局完全對(duì)應(yīng)。要處理與平臺(tái)無(wú)關(guān)的數(shù)據(jù)格式或省略隱式填充字節(jié),請(qǐng)使用standard大小和對(duì)齊而不是 native大小和對(duì)齊。

          struct 模塊的用途:

          1、按照指定格式將 Python 數(shù)據(jù)轉(zhuǎn)換為字符串,該字符串為字節(jié)流,如:網(wǎng)絡(luò)傳輸時(shí)不能傳輸int,此時(shí)先將int轉(zhuǎn)化為字節(jié)流,然后再發(fā)送。 2、按照指定格式將字節(jié)流轉(zhuǎn)換為 Python 指定的數(shù)據(jù)類型。 3、處理二進(jìn)制數(shù)據(jù),如果用 struct 來(lái)處理圖片文件的話,需要使用 ‘rb’/‘wb’ 以二進(jìn)制(字節(jié)流)讀寫的方式來(lái)處理文件。 4、處理 c 語(yǔ)言中的結(jié)構(gòu)體。

          1.函數(shù)和異常

          該模塊定義了以下異常和函數(shù):

          • exception
          exception struct.error

          在各種場(chǎng)合提出異常;參數(shù)是一個(gè)描述錯(cuò)誤的字符串。

          • pack
          struct.pack(format, v1, v2, ...) 

          返回一個(gè)字節(jié)對(duì)象,其中包含根據(jù)格式字符串格式打包的值 v1v2 、 ...。參數(shù)必須與格式要求的值完全匹配。

          • pack_into
          struct.pack_into(format, buffer, offset, v1, v2, ...)

          根據(jù)格式字符串格式打包值 v1,v2 ,...... ,并將打包的字節(jié)寫入從位置 offset 開(kāi)始的可寫緩沖區(qū)。注意,偏移量是必需的參數(shù)。

          • unpack
          struct.unpack(format, buffer)

          根據(jù)格式字符串 format 從緩沖區(qū)中解包 。結(jié)果是一個(gè)元組,即使它只包含一個(gè)項(xiàng)目。緩沖區(qū)的字節(jié)大小必須與格式所需的大小相匹配。

          • unpack_from
          struct.unpack_from(format, buffer, offset=0)

          根據(jù)格式字符串,從位置偏移開(kāi)始的緩沖區(qū)解包。結(jié)果是一個(gè)元組,即使它只包含一個(gè)項(xiàng)目。緩沖區(qū)的大小(以字節(jié)為單位)減去 offset 后,必須至少是格式所需的大小。

          • iter_unpack
          struct.iter_unpack(format, buffer)

          根據(jù)格式字符串 format從緩沖區(qū)中迭代解包。這個(gè)函數(shù)返回一個(gè)迭代器,它將從緩沖區(qū)中讀取相同大小的塊,直到它的所有內(nèi)容都被消耗完。緩沖區(qū)的字節(jié)大小必須是格式所需大小的倍數(shù)。每次迭代都會(huì)產(chǎn)生一個(gè)由格式字符串指定的元組。

          • calcsize
          struct.calcsize(format)

          返回與格式字符串 format 對(duì)應(yīng)的結(jié)構(gòu)體(以及由此產(chǎn)生的字節(jié)對(duì)象 )的大小。

          2.格式化字符串

          格式字符串是用于在打包和解包數(shù)據(jù)時(shí)指定預(yù)期布局的機(jī)制。它們是通過(guò)格式字符構(gòu)建的,它指定了被打包/解包的數(shù)據(jù)類型。此外,還有用于控制字節(jié)順序、大小和對(duì)齊的特殊字符。

          2.1 字節(jié)順序、大小和對(duì)齊

          默認(rèn)情況下,C 類型以機(jī)器的本機(jī)格式和字節(jié)順序表示,并在必要時(shí)通過(guò)跳過(guò)填充字節(jié)來(lái)正確對(duì)齊(根據(jù) C 編譯器使用的規(guī)則)。或者,格式字符串的第一個(gè)字符可用于指示打包數(shù)據(jù)的字節(jié)順序、大小和對(duì)齊方式,如下表所示:

          Character

          Byte order

          Size

          Alignment

          @

          native

          native

          native

          =

          native

          standard

          none

          <

          little-endian

          standard

          none

          >

          big-endian

          standard

          none

          !

          network (=big-endian)

          standard

          none

          如果第一個(gè)字符不是其中之一,'@'則為默認(rèn)。

          本機(jī)字節(jié)順序是大端或小端,具體取決于主機(jī)系統(tǒng)。例如:

          • Intel x86 和 AMD64 (x86-64) 是 little-endian;
          • 摩托羅拉 68000 和 PowerPC G5 是大端;
          • ARM 和 Intel Itanium 具有可切換的字節(jié)序(雙字節(jié)序)。

          可以使用sys.byteorder檢查系統(tǒng)的字節(jié)順序。

          本機(jī)大小和對(duì)齊方式是使用 C 編譯器的 sizeof 表達(dá)式確定的。這總是與本機(jī)字節(jié)順序相結(jié)合。

          標(biāo)準(zhǔn)大小僅取決于格式字符;

          '@''='之間的區(qū)別:兩者都使用本機(jī)字節(jié)順序,但后者的大小和對(duì)齊方式是標(biāo)準(zhǔn)化的。

          '!'適用于那些聲稱他們不記得網(wǎng)絡(luò)字節(jié)順序是大端還是小端的人。

          無(wú)法指示非本機(jī)字節(jié)順序(強(qiáng)制字節(jié)交換);使用適當(dāng)?shù)?<>

          注意:

          1. 填充僅在連續(xù)的結(jié)構(gòu)成員之間自動(dòng)添加。在編碼結(jié)構(gòu)的開(kāi)頭或結(jié)尾處不添加任何填充。
          2. 使用非原生大小和對(duì)齊方式時(shí)不添加填充,例如使用“<”、“>”、“=”和“!”。
          3. 要將結(jié)構(gòu)的結(jié)尾與特定類型的對(duì)齊要求對(duì)齊,請(qǐng)以該類型的代碼結(jié)束格式,并且重復(fù)計(jì)數(shù)為零。

          2.2格式字符串

          格式字符具有以下含義;考慮到它們的類型,C 和 Python 值之間的轉(zhuǎn)換應(yīng)該是顯而易見(jiàn)的。“標(biāo)準(zhǔn)大小”列是指使用標(biāo)準(zhǔn)大小時(shí)打包值的大小(以字節(jié)為單位);也就是說(shuō),當(dāng)格式字符串以 '<', '>', '!''=' 中的一個(gè)開(kāi)頭時(shí)。

          Format

          C Type

          Python type

          Standard size

          x

          pad byte

          no value


          c

          char

          bytes of length 1

          1

          b

          signed char

          integer

          1

          B

          unsigned char

          integer

          1

          ?

          _Bool

          bool

          1

          h

          short

          integer

          2

          H

          unsigned short

          integer

          2

          i

          int

          integer

          4

          I

          unsigned int

          integer

          4

          l

          long

          integer

          4

          L

          unsigned long

          integer

          4

          q

          long long

          integer

          8

          Q

          unsigned long long

          integer

          8

          n

          ssize_t

          integer


          N

          size_t

          integer


          e

          (6)

          float

          2

          f

          float

          float

          4

          d

          double

          float

          8

          s

          char[]

          bytes


          p

          char[]

          bytes


          P

          void *

          integer


          格式字符前面可以有一個(gè)整數(shù)重復(fù)計(jì)數(shù)。例如,格式字符串'4h'的含義與'hhhh'

          格式之間的空白字符被忽略;計(jì)數(shù)及其格式不能包含空格。

          對(duì)于's'格式字符,計(jì)數(shù)被解釋為字節(jié)的長(zhǎng)度,而不是像其他格式字符那樣的重復(fù)計(jì)數(shù);例如, '10s'表示單個(gè) 10 字節(jié)字符串,而'10c'表示 10 個(gè)字符。如果未給出計(jì)數(shù),則默認(rèn)為 1。對(duì)于打包,字符串將被截?cái)嗷蛴每兆止?jié)填充以使其適合。對(duì)于解包,生成的字節(jié)對(duì)象始終具有完全指定的字節(jié)數(shù)。作為一種特殊情況,'0s'表示單個(gè)空字符串(同時(shí) '0c'表示 0 個(gè)字符)。

          x當(dāng)使用其中一種整數(shù)格式('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q')打包值時(shí),如果x超出該格式的有效范圍,則引發(fā) struct.error。

          格式字符對(duì)'p'“Pascal 字符串”進(jìn)行編碼,這意味著存儲(chǔ)在固定字節(jié)數(shù)中的短可變長(zhǎng)度字符串,由計(jì)數(shù)給出。存儲(chǔ)的第一個(gè)字節(jié)是字符串的長(zhǎng)度,或 255,以較小者為準(zhǔn)。字符串的字節(jié)如下:如果傳入的字符串pack()太長(zhǎng)(長(zhǎng)于 count 減 1),則只 count-1 存儲(chǔ)字符串的前導(dǎo)字節(jié)。如果字符串短于 count-1,則用空字節(jié)填充它,以便使用精確計(jì)數(shù)的字節(jié)。請(qǐng)注意,對(duì)于unpack()'p'格式字符會(huì)消耗 count字節(jié),但返回的字符串不能包含超過(guò) 255 個(gè)字節(jié)。

          對(duì)于'?'格式字符,返回值為TrueFalse。打包時(shí)使用參數(shù)對(duì)象的真值。本機(jī)或標(biāo)準(zhǔn)布爾表示中的 0 或 1 將被打包,并且任何非零值將 在解包時(shí)為 True

          3.示例

          所有示例都假定本機(jī)字節(jié)順序、大小和與大端機(jī)器對(duì)齊。

          打包/解包三個(gè)整數(shù)的基本示例:

          >>> from struct import *
          >>> pack('hhl', 1, 2, 3)
          b'\x00\x01\x00\x02\x00\x00\x00\x03'
          >>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
          (1, 2, 3)
          >>> calcsize('hhl')
          8

          解壓的字段可以通過(guò)將它們分配給變量或?qū)⒔Y(jié)果包裝在命名元組中來(lái)命名:

          >>> record=b'raymond   \x32\x12\x08\x01\x08'
          >>> name, serialnum, school, gradelevel=unpack('<10sHHb', record)
          
          >>> from collections import namedtuple
          >>> Student=namedtuple('Student', 'name serialnum school gradelevel')
          >>> Student._make(unpack('<10sHHb', record))
          Student(name=b'raymond   ', serialnum=4658, school=264, gradelevel=8)

          格式字符的順序可能會(huì)影響大小,因?yàn)闈M足對(duì)齊要求所需的填充是不同的:

          >>> pack('ci', b'*', 0x12131415)
          b'*\x00\x00\x00\x12\x13\x14\x15'
          >>> pack('ic', 0x12131415, b'*')
          b'\x12\x13\x14\x15*'
          >>> calcsize('ci')
          8
          >>> calcsize('ic')
          5

          以下格式'llh0l'在末尾指定兩個(gè)填充字節(jié),假設(shè) long 在 4 字節(jié)邊界上對(duì)齊:

          >>> pack('llh0l', 1, 2, 3)
          b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

          4.類 Struct

          該模塊還定義了以下類型:

          class struct.Struct(format)

          返回一個(gè)新的 Struct 對(duì)象,該對(duì)象根據(jù)格式字符串 format 寫入和讀取二進(jìn)制數(shù)據(jù)。一次創(chuàng)建一個(gè) Struct 對(duì)象并調(diào)用它的方法比調(diào)用 struct 具有相同格式的函數(shù)更有效,因?yàn)楦袷阶址恍枰幾g一次。

          編譯后的Struct對(duì)象支持以下方法和屬性:

          • pack
          pack(v1, v2, ...)

          與函數(shù) pack() 相同,使用編譯格式。

          • pack_into
          pack_into(buffer, offset, v1, v2, ...)

          與函數(shù) pack_into() 相同,使用編譯格式 。

          • unpack
          unpack(buffer)

          與函數(shù) unpack() 相同,使用編譯格式。

          • unpack_from
          unpack_from(buffer, offset=0)

          與函數(shù) unpack_from() 相同,使用編譯格式。

          • iter_unpack
          iter_unpack(buffer)

          與函數(shù) iter_unpack() 相同,使用編譯格式。

          • format
          format

          用于構(gòu)造此 Struct 對(duì)象的格式字符串。

          • size
          size

          對(duì)應(yīng)于 format 的結(jié)構(gòu)體(以及由此 pack() 方法產(chǎn)生的字節(jié)對(duì)象)的大小。

          struct是python(包括版本2和3)中的內(nèi)建模塊,它用來(lái)在c語(yǔ)言中的結(jié)構(gòu)體與python中的字符串之間進(jìn)行轉(zhuǎn)換,數(shù)據(jù)一般來(lái)自文件或者網(wǎng)絡(luò)。

          常用方法

          struct.pack(fmt,v1,v2,…)

          返回的是一個(gè)字符串,是參數(shù)按照f(shuō)mt數(shù)據(jù)格式組合而成。

          struct.unpack(fmt,string)

          按照給定數(shù)據(jù)格式解開(kāi)(通常都是由struct.pack進(jìn)行打包)數(shù)據(jù),返回值是一個(gè)tuple

          格式符

          下面2張表來(lái)自官網(wǎng)

          Character

          Byte order

          Size

          Alignment

          @

          native

          native

          native

          =

          native

          standard

          none

          <

          little-endian

          standard

          none

          >

          big-endian

          standard

          none

          !

          network (=big-endian)

          standard

          none

          Format

          C Type

          Python type

          Standard size

          Notes

          x

          pad byte

          no value



          c

          char

          string of length 1

          1


          b

          signed char

          integer

          1

          (3)

          B

          unsigned char

          integer

          1

          (3)

          ?

          _Bool

          bool

          1

          (1)

          h

          short

          integer

          2

          (3)

          H

          unsigned short

          integer

          2

          (3)

          i

          int

          integer

          4

          (3)

          I

          unsigned int

          integer

          4

          (3)

          l

          long

          integer

          4

          (3)

          L

          unsigned long

          integer

          4

          (3)

          q

          long long

          integer

          8

          (2), (3)

          Q

          unsigned long long

          integer

          8

          (2), (3)

          f

          float

          float

          4

          (4)

          d

          double

          float

          8

          (4)

          s

          char[]

          string



          p

          char[]

          string



          P

          void *

          integer


          (5), (3)

          實(shí)例

          理論性的東西看起來(lái)都比較枯燥,來(lái)個(gè)實(shí)例代碼就容易理解多了。本例來(lái)實(shí)現(xiàn)往一個(gè)2進(jìn)制文件中按照某種特定格式寫入數(shù)據(jù),之后再將它讀出。相信通過(guò)這個(gè)例子,你就能基本掌握struct的使用。

          # -*- coding: utf-8 -*-
          
          '''
          數(shù)據(jù)格式為
          姓名 年齡 性別   職業(yè)
          lily 18  female teacher
          '''
          
          import os
          import struct
          
          fp=open('test.bin','wb')
          
          # 按照上面的格式將數(shù)據(jù)寫入文件中
          # 這里如果string類型的話,在pack函數(shù)中就需要encode('utf-8')
          name=b'lily'
          age=18
          sex=b'female'
          job=b'teacher'
          
          # int類型占4個(gè)字節(jié)
          fp.write(struct.pack('4si6s7s', name,age,sex,job))
          fp.flush()
          fp.close()
          
          # 將文件中寫入的數(shù)據(jù)按照格式讀取出來(lái)
          fd=open('test.bin','rb')
          # 21=4 + 4 + 6 + 7
          print(struct.unpack('4si6s7s',fd.read(21)))
          fd.close()
          

          運(yùn)行上面的代碼,可以看到讀出的數(shù)據(jù)與寫入的數(shù)據(jù)是完全一致的。

          python test.py
          (b'lily', 18, b'female', b'teacher')
          
          Process finished with exit code 0
          

          參考資料

          • https://docs.python.org/2/library/struct.html

          近項(xiàng)目中遇到一個(gè)文檔解析的場(chǎng)景,目標(biāo)是在瀏覽器端能預(yù)覽markdown文件。

          拿到這個(gè)需求,相信很多前端同學(xué)會(huì)想到使用開(kāi)源的庫(kù),比如github上很受歡迎的marked,當(dāng)然,是一個(gè)簡(jiǎn)單而有效的方案。

          但是如果你了解webassembly一點(diǎn)點(diǎn)的話,相信你也會(huì)覺(jué)得,像這種數(shù)據(jù)處理的活交給C++來(lái)干,沒(méi)錯(cuò)。

          好吧,我們抱著這個(gè)猜想開(kāi)始下面的嘗試吧。

          搭建環(huán)境

          為了把C++代碼編譯成能在瀏覽器上運(yùn)行的wasm,我們需要使用 Emscripten。 安裝Emscripten依賴如下幾個(gè)工具:Git、CMake、GCC、Python 2.7.x。

          編譯 Emscripten:

          git clone https://github.com/juj/emsdk.git
          cd emsdk
          ./emsdk install sdk-incoming-64bit binaryen-master-64bit
          ./emsdk activate sdk-incoming-64bit binaryen-master-64bit
          source ./emsdk_env.sh
          

          創(chuàng)建項(xiàng)目

          推薦如下的目錄結(jié)構(gòu):

          .
          ├── build
          ├── build.sh
          ├── include
          │   └── sundown
          │       ├── autolink.c
          │       ├── autolink.h
          │       ├── buffer.c
          │       ├── buffer.h
          │       ├── houdini.h
          │       ├── houdini_href_e.c
          │       ├── houdini_html_e.c
          │       ├── html.c
          │       ├── html.h
          │       ├── html_blocks.h
          │       ├── markdown.c
          │       ├── markdown.h
          │       ├── stack.c
          │       └── stack.h
          ├── src
          │   ├── index.cc
          │   └── wasm.c
          └── web
              ├── index.html
              ├── index.js
              ├── index.wasm
              └── test.md
          

          這里為了測(cè)試,我是直接使用了通過(guò)C解析markdown文檔開(kāi)源庫(kù)sundown。就是目錄中的include/sundown。

          我們需要一個(gè)入口文件,取一個(gè)名字wasm.c。

          #include <errno.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <string.h>
          #include <emscripten/emscripten.h>
          
          #include "markdown.h"
          #include "html.h"
          #include "buffer.h"
          
          #define READ_UNIT 1024
          #define OUTPUT_UNIT 64
          
          const char*
          EMSCRIPTEN_KEEPALIVE wasm_markdown(char* source)
          {
              struct buf *ib, *ob;
              struct sd_callbacks callbacks;
              struct html_renderopt options;
              struct sd_markdown *markdown;
          
              ib=bufnew(READ_UNIT);
              bufgrow(ib, READ_UNIT);
              size_t char_len=strlen(source);
              bufput(ib, source, char_len);
          
              ob=bufnew(OUTPUT_UNIT);
              sdhtml_renderer(&callbacks, &options, 0);
              markdown=sd_markdown_new(0, 16, &callbacks, &options);
              sd_markdown_render(ob, ib->data, ib->size, markdown);
              sd_markdown_free(markdown);
          
              /* cleanup */
              bufrelease(ib);
              bufrelease(ob);
          
              return (char *)(ob->data);
          }
          

          入口文件是調(diào)用lib的方法實(shí)現(xiàn)md字符解析,輸出html格式的字符。完成編碼部分,接下來(lái)就可以構(gòu)建了。

          這是我的build腳本:

          emcc src/wasm.c \
          -O3 \
          ./include/sundown/markdown.c \
          ./include/sundown/buffer.c \
          ./include/sundown/autolink.c \
          ./include/sundown/html.c \
          ./include/sundown/houdini_href_e.c \
          ./include/sundown/houdini_html_e.c \
          ./include/sundown/stack.c \
          -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap", "ccall"]' \
          -s TOTAL_MEMORY=67108864 \
          -s TOTAL_STACK=31457280 \
          -o build/index.js -I./include/sundown \
          
          cp build/index.js build/index.wasm web/
          

          解釋下其中的幾個(gè)參數(shù):

          • EXTRA_EXPORTED_RUNTIME_METHODS,允許js通過(guò)cwrap和ccall的方式調(diào)用c函數(shù)。
          • TOTAL_MEMORY,分配內(nèi)存大小。TOTAL_MEMORY,分配棧大小。因?yàn)閙d文檔比較大,默認(rèn)的5M不夠用。

          測(cè)試

          啟動(dòng)一個(gè)web Server,因?yàn)閣ebAssembly不支持file協(xié)議下加載。

          emrun --port 3000 ./web
          

          emrun是Emscriptem自帶的webServer工具,你也可以使用你喜歡的。

          初始化并調(diào)用C接口。

          <script src="http://127.0.0.1:3000/markdown.js"></script>
          <script>
          const wasm_markdown=Module.cwrap('wasm_markdown', 'string', ['string']);
          console.log(wasm_markdown('# hello wasm'));
          // 輸出:<h1>hello wasm</h1>
          </script>
          

          多線程

          先看DEMO,分析在代碼之后。

          const mdUrl='http://127.0.0.1:3000/markdown.js';
          
          class MarkdownParse {
              isInited=false;
              worker=undefined;
              async init(url) {
                  if (this.isInited) {
                      return;
                  }
                  return new Promise(rs=> {
                      const workerScripts=`
                          addEventListener('message', async(e)=> {
                            if (e.data=="startWorker") {
                              importScripts("${url}");
                              postMessage({ type: 'init' });
                            } else if (e.data.type==='parseData') {
                            	await markdown.ready;
                            	const data=markdown.parse(e.data.input);
                            	postMessage({ type: 'parseSuccess', data }); 
                            }
                          }, false)`;
                      this.worker=new Worker(window.URL.createObjectURL(new Blob([workerScripts])));
                      this.worker.addEventListener('message', e=> e.data.type==='init' ? rs() : '');
                      this.worker.postMessage("startWorker");
                      this.isInited=true;
                  })
              }
              async parse(input) {
                  if (!this.isInited) {
                      await this.init(mdUrl);
                  }
                  return new Promise(resolve=> {
                      this.worker.addEventListener('message', 
                          e=> e.data.type==='parseSuccess' ? 
                              resolve(e.data.data) : null
                      );
                      this.worker.postMessage({ type: 'parseData', input });
                  });
              }
          };
          
          (async()=> {
              const md=new MarkdownParse();
              // // 觸發(fā)多次解析
              // const html=[
              // 	await md.parse('# Hello Markdown'),	
              // 	await md.parse('- [ ] Todo1'),
              // 	await md.parse('- [ ] Todo2'),
              // 	await md.parse('- [x] Todo3'),
              // 	await md.parse('> Date.now()'),
              // 	await md.parse('`const a=Date.now();`'),
              // ];
              // document.querySelector('#markdown-body').innerHTML=html.join('');
          
              md.parse('123');
              const text=await (await fetch('test.md')).text();
              const testJS=()=> {
                  const a=Date.now();
                  // marked 是JS版本的markdown解析庫(kù)
                  marked(text);
                  return Date.now() - a;
              };
              const testWasm=async()=> {
                  const a=Date.now();
                  await md.parse(text);
                  return Date.now() - a;
              };
              const vs=async()=> {
                  const result={
                      js_parse_time: testJS(),
                      wasm_parse_time: await testWasm(),
                  };
                  result.speed=result.js_parse_time / result.wasm_parse_time;
                  // 顯示wasm和JS的解析速度對(duì)比
                  document.querySelector('#markdown-body').innerHTML=JSON.stringify(result);
              }
              await vs();
              // 輸出markdown的HTML
              // document.querySelector('#markdown-body').innerHTML=await md.parse(text);
          
          })();
          

          解析下思路,線抽線一個(gè)類 MarkdownParse 來(lái)實(shí)現(xiàn)wasm的加載和初始化以及api。 默認(rèn)情況下, web worker是不允許跨域的,但是,有方案的。web worker內(nèi)部提供了一個(gè)importScripts方法來(lái)加載非同源的JS。

          收獲&總結(jié)

          到此我們完成了今天的構(gòu)建webassembly應(yīng)用實(shí)例,有如下收獲:

          • wasm比JS,效率高出3倍左右
          • 通過(guò)web worker去處理wasm的加載,初始化,數(shù)據(jù)計(jì)算處理等,不會(huì)占用瀏覽器的主線程

          總結(jié),本文可能只是一個(gè)很小的場(chǎng)景,而且單從效率這點(diǎn)來(lái)看,JS的200ms對(duì)比wasm的50ms,其實(shí)對(duì)于前端來(lái)說(shuō),并沒(méi)有特別驚艷的優(yōu)勢(shì)。BUT,這只是一個(gè)開(kāi)始,wasm對(duì)前端帶來(lái)的性能提升會(huì)百花齊放,我們拭目以待吧~


          主站蜘蛛池模板: 亚洲一区中文字幕在线电影网 | 国产成人一区二区三区高清| 国产精品无圣光一区二区| 国产午夜三级一区二区三| 欧美亚洲精品一区二区| 亚洲色婷婷一区二区三区| 国产精品一区二区久久沈樵| 麻豆一区二区99久久久久| 久久久无码精品国产一区| 亚洲免费视频一区二区三区| 国产一区美女视频| 亚洲日本乱码一区二区在线二产线 | 久久精品一区二区三区日韩 | 国产激情无码一区二区| 亚洲一区二区三区在线视频| 日韩一区在线视频| 日韩AV无码一区二区三区不卡| 亚洲一区二区三区乱码在线欧洲| 亚洲视频一区调教| 欧洲无码一区二区三区在线观看| 成人精品一区二区三区不卡免费看| 日韩一区二区三区视频久久| 日本精品一区二区三区视频| 怡红院美国分院一区二区| 亚洲爆乳精品无码一区二区| 色窝窝免费一区二区三区| 国产成人精品一区二区A片带套| 成人在线观看一区| 日韩精品一区二区三区中文3d| 香蕉久久ac一区二区三区| 色屁屁一区二区三区视频国产| 亚洲a∨无码一区二区| 无码av中文一区二区三区桃花岛 | 无码国产精品一区二区免费式影视 | 中文字幕AV一区二区三区人妻少妇| 国产福利一区二区三区视频在线 | 精品久久综合一区二区| 精品久久综合一区二区| 亚洲成人一区二区| 香蕉久久一区二区不卡无毒影院| 99久久人妻精品免费一区|