Browse Source

Implement all of the "benchmarks"

rexim 5 years ago
parent
commit
45cdc28409
7 changed files with 102 additions and 3 deletions
  1. 3 1
      .gitignore
  2. 26 1
      2020-09-04.md
  3. 7 0
      Makefile
  4. 19 0
      prime-naive.js
  5. 6 0
      prime-wasm.js
  6. 1 1
      prime.c
  7. 40 0
      prime.wat

+ 3 - 1
.gitignore

@@ -1 +1,3 @@
-a.out
+a.out
+prime
+*.wasm

+ 26 - 1
2020-09-04.md

@@ -3,6 +3,31 @@
 - [ ] Premise: Performance of WASM is probably comparable to native code
 - [ ] Premise: Performance of WASM is probably comparable to native code
   - [ ] Let's check it by implementing a Prime Number Crunching as a "Benchmark":
   - [ ] Let's check it by implementing a Prime Number Crunching as a "Benchmark":
     - [x] [Native C Implementation](./main.c)
     - [x] [Native C Implementation](./main.c)
-    - [ ] WebAssembly Implemention
+      ```console
+        $ time ./prime
+        179424673
+
+        real    0m52.964s
+        user    0m52.766s
+        sys     0m0.196s
+      ```
+    - [x] [JavaScript Implementation](./prime-naive.js)
+      ```console
+        $ time node prime-naive.js
+        179424673
+
+        real    2m4.781s
+        user    2m4.414s
+        sys     0m0.208s
+      ```
+    - [x] [WebAssembly Implemention](./prime.wat)
+      ```console
+        $ time node prime-wasm.js
+        179424673
+
+        real    1m17.061s
+        user    1m16.844s
+        sys     0m0.192s
+      ```
 - [ ] Idea: Let's imagine we invented a new image format that didn't exist before
 - [ ] Idea: Let's imagine we invented a new image format that didn't exist before
   - [ ] If we implement the image support in WASM can we make it feel like a native browser support
   - [ ] If we implement the image support in WASM can we make it feel like a native browser support

+ 7 - 0
Makefile

@@ -0,0 +1,7 @@
+all: prime prime.wasm
+
+prime: prime.c
+	$(CC) -O3 -o prime prime.c
+
+prime.wasm: prime.wat
+	wat2wasm prime.wat

+ 19 - 0
prime-naive.js

@@ -0,0 +1,19 @@
+const N = 10 * 1000 * 1000;
+const primes = [2];
+
+function is_prime(x) {
+    for (let i = 0; primes[i] * primes[i] <= x; ++i) {
+        if (x % primes[i] == 0) {
+            return false;
+        }
+    }
+    return true;
+}
+
+for (let x = 3; primes.length < N; ++x) {
+    if (is_prime(x)) {
+        primes.push(x);
+    }
+}
+
+console.log(primes[primes.length - 1]);

+ 6 - 0
prime-wasm.js

@@ -0,0 +1,6 @@
+const fs = require("fs");
+
+WebAssembly
+    .instantiate(new Uint8Array(fs.readFileSync("./prime.wasm")), {})
+    .then((obj) => console.log(obj.instance.exports.prime(10 * 1000 * 1000)))
+    .catch((x) => console.log(x));

+ 1 - 1
main.c → prime.c

@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 
 
-#define N (1000 * 1000)
+#define N (10 * 1000 * 1000)
 
 
 int primes[N] = {2};
 int primes[N] = {2};
 size_t primes_count = 1;
 size_t primes_count = 1;

+ 40 - 0
prime.wat

@@ -0,0 +1,40 @@
+(module
+ (memory (export "primes") 700 700)
+ (func $is_prime
+       (param $x i32)
+       (result i32)
+       (local $prime i32)
+       (local $i i32)
+       (local $result i32)
+       (set_local $i (i32.const 0))
+       (block
+        $exit
+        (loop
+         $top
+         (set_local $prime (i32.load (i32.mul (get_local $i) (i32.const 4))))
+         (set_local $result (i32.const 1))
+         (br_if $exit (i32.gt_s (i32.mul (get_local $prime) (get_local $prime)) (get_local $x)))
+         (set_local $result (i32.const 0))
+         (br_if $exit (i32.eq (i32.rem_s (get_local $x) (get_local $prime)) (i32.const 0)))
+         (set_local $i (i32.add (get_local $i) (i32.const 1)))
+         (br $top)))
+       (get_local $result))
+ (func (export "prime")
+       (param $n i32)
+       (result i32)
+       (local $primes_count i32)
+       (local $x i32)
+       (i32.store (i32.const 0) (i32.const 2))
+       (set_local $primes_count (i32.const 1))
+       (set_local $x (i32.const 2))
+       (block
+        $exit
+        (loop
+         $top
+         (set_local $x (i32.add (get_local $x) (i32.const 1)))
+         (br_if $exit (i32.ge_s (get_local $primes_count) (get_local $n)))
+         (br_if $top (i32.eqz (call $is_prime (get_local $x))))
+         (i32.store (i32.mul (get_local $primes_count) (i32.const 4)) (get_local $x))
+         (set_local $primes_count (i32.add (get_local $primes_count) (i32.const 1)))
+         (br $top)))
+       (i32.load (i32.mul (i32.sub (get_local $primes_count) (i32.const 1)) (i32.const 4)))))