Crystal Lang embedded Javascript interpreter using MuJS.
require "mujs"
js = Mujs.new
js.defn("print", 1) do |args|
puts args[0].as(String)
end
js.dostring(%[print("hello world")])more examples at spec/mujs_spec.cr.
-
Add the dependency to your
shard.yml:dependencies: mujs: github: bit4bit/mujs.cr
-
Run
shards install
see spec/mujs_spec.cr
Benchmarks comparing Crystal native code vs MuJS through Crystal bindings (release mode, Intel i5):
| Benchmark | Crystal Native | Through Bindings | Slower By |
|---|---|---|---|
| Function Call (1+2) | |||
| Direct Crystal | 462.8M ops/s | — | — |
| Crystal → MuJS (execute JS) | — | 9.3M ops/s | 49.5x |
MuJS → Crystal → MuJS (defn callback) |
— | 3.3M ops/s | 140.6x |
| Type Conversion - Number | 771.3M ops/s | 8.6M ops/s | 89.8x |
| Type Conversion - String | 751.0M ops/s | 4.7M ops/s | 159.1x |
| Type Conversion - Bool | 775.6M ops/s | 9.1M ops/s | 85.6x |
| Callback (C→JS→C) | 761.8M ops/s | 3.5M ops/s | 218.5x |
Key Findings:
- All MuJS calls go through Crystal FFI bindings
- One-way (Crystal→MuJS) is ~2.8x faster than round-trip (MuJS→Crystal→MuJS) (9.3M vs 3.3M ops/s)
- Strings are slowest - 159x slower than native Crystal (most expensive conversion)
- Booleans are fastest - "only" 86x slower than native
- Callbacks are worst - Crossing the boundary twice (C→MuJS→C) costs 218x performance penalty
Run benchmarks yourself:
crystal run benchmark/bench.cr --release --link-flags "-L/home/bit4bit/.local/lib -lmujs -lm"- Fork it (https://github.com/bit4bit/mujs.cr/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
- Jovany Leandro G.C - creator and maintainer