작은 도서관
article thumbnail

WebAssembly란

웹 브라우저에서 작동되는 프로그래밍 언어로, webAssembly 자체로 코드를 작성하기보다 C, C++, Rust등의 소스 언어를 컴파일하는 타겟 언어로써 고안되었다.

브라우저에서 실행할 때는 javascript에서 webAssembly를 실행시키는 코드를 작성해 네이티브에 가까운 속도로 실행시킬 수 있다.

그럼 이 webAssembly로 컴파일된 함수를 node에서 사용하면 어떨까?

함수 작성

성능 비교를 위해 백엔드 서버에서 해시 함수를 사용하는 상황을 가정하고, 다음과 같은 해시함수를 작성한다.

export default function generateHash(input) {
  let hash = 2166136261;

  for (let i = 0; i < input.length; i++) {
    const charCode = input.charCodeAt(i);
    for (let j = 0; j < 100000; j++) {
      hash ^= charCode;
      hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
    }
  }

  return hash;
}

이 함수는 시행 시간을 측정하기 용이하게 일부러 매우 비효율적으로 작성했고, 이제 이를 wasm으로 빌드하기 위해서 assemblyScript로 옮겨 작성한다.

export function generateHash(input: string): i32 {
  let hash: i32 = 2166136261;

  for (let i: i32 = 0; i < input.length; i++) {
    const charCode: i32 = input.charCodeAt(i);
    for (let j: i32 = 0; j < 100000; j++) {
      hash ^= charCode;
      hash += (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
    }
  }

  return hash;
}

 

assemblyscript파일을 wasm파일로 컴파일하기 위해선 다음 명령어를 사용한다.

// hash.ts는 assemblyScript 원본 파일, hash.wasm은 타겟 파일
> asc hash.ts -o hash.wasm

 

node에서 함수 불러오기

node에서 기본적으로 wasm모듈을 불러오는 기능을 지원하나, wasm 모듈을 assemblyscript로 빌드했기 때문에 여러 편의성을 제공하는 assemblyscript 패키지를 별도로 설치했다.

import loader from "@assemblyscript/loader";
import fs from "fs/promises";

const loadWasmModule = async () => {
  const file = await fs.readFile("./src/modules/common/hash.wasm");
  wasmModule = await loader.instantiate(file);
};

const runWasmHash = (password) => {
  const { __newString, generateHash } = wasmModule.exports;
  return generateHash(__newString(password));
};

실행 시간 비교

wasm으로 작성된 함수가 훨씬 빠른 시간 안에 실행됨을 알 수 있었다.

ffi와의 차이점

  ffi wasm
로드 오버헤드가 큼 instantiate 이후는 쉬움
디버깅 디버깅 어려움(고수준의 native 이해 필요) 디버깅 쉬움
확장 어려움 브라우저에서 동작가능

 

레퍼런스

한글로 되어있는 레퍼런스가 없어서 힘들었다...

https://nodejs.org/en/learn/getting-started/nodejs-with-webassembly (nodejs docs)

https://www.assemblyscript.org/getting-started.html#setting-up-a-new-project (assemblyScript)

https://github.com/AssemblyScript/assemblyscript/tree/main/lib/loader (loader)

profile

작은 도서관

@Flrea

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!