Skip to content

Commit a45d6d3

Browse files
committed
can pass features during comp, waiting to give some time to think about how best to expose these
wip: can conditioanlly load rayon functions waiting to decided if that is a good idea cfg and cfg not prevent compiler warnings removed codeloader now that cfg doesn't produce errors temp add log to test package compliation finish flag support, document, and expose update_with_join
1 parent 7e937c9 commit a45d6d3

File tree

9 files changed

+207
-12
lines changed

9 files changed

+207
-12
lines changed

README.md

+26-2
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,47 @@
11
[![Hex.pm Version](http://img.shields.io/hexpm/v/blake3.svg?style=flat)](https://hex.pm/packages/blake3)
22

33
# Blake3
4+
45
Elixir bindings for the Rust Blake3 implementation.
56
These bindings use [`:rustler`](https://github.com/rusterlium/rustler) to connect to the hashing functions.
67

7-
88
## Installation
9+
910
The package can be installed by adding `blake3` to your list of dependencies in `mix.exs`:
1011

1112
```elixir
1213
def deps do
1314
[
14-
{:blake3, "~> 0.2.0"}
15+
{:blake3, "~> 0.3.0"}
1516
]
1617
end
1718
```
1819

1920
run `mix deps.get` and `mix deps.compile` to pull and build the bindings
2021

22+
## Configuration
23+
24+
There are feature options in the rust implementation that allow for additional SIMD instructions and multithreading. They can be set though environment variable or `Mix.Config`.
25+
26+
```shell
27+
export BLAKE3_SIMD_MODE=c
28+
export BLAKE3_RAYON=true
29+
```
30+
31+
or
32+
33+
```elixir
34+
config :blake3,
35+
simd_mode: :c_neon,
36+
rayon: :true
37+
```
38+
39+
* `c` enables C/assembly implementations and AVX-512 support
40+
* `c_neon` enables ARM NEON support
41+
* `rayon` enables Rayon-based multithreading
42+
43+
When changing configuration you will need to call `mix deps.compile` to enable the features.
44+
2145
## Example Usage
2246

2347
```elixir

config/config.exs

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
use Mix.Config
2+
# config :blake3, simd_mode: "std"
3+
# config :blake3, rayon: :false

lib/blake3.ex

+10
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,14 @@ defmodule Blake3 do
8585
def reset(state) do
8686
Native.reset(state)
8787
end
88+
89+
@doc """
90+
updates state with the potential to multithreading. The rayon
91+
feature needs to be enabled and the input need to be large enough.
92+
for more information see:
93+
[comment](https://github.com/BLAKE3-team/BLAKE3/blob/fdd329ba57896faac4ae797775c175ad880cbe42/src/lib.rs#L948-L981)
94+
"""
95+
def update_with_join(state, data) do
96+
Native.update_with_join(state, data)
97+
end
8898
end

lib/blake3/native.ex

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ defmodule Blake3.Native do
99
def hash(_str), do: error()
1010
def new(), do: error()
1111
def update(_state, _str), do: error()
12+
def update_with_join(_state, _str), do: error()
1213
def finalize(_state), do: error()
1314
def derive_key(_context, _key), do: error()
1415
def keyed_hash(_key, _str), do: error()

mix.exs

+34-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
defmodule Blake3.MixProject do
1+
defmodule MixBlake3.Project do
22
use Mix.Project
33

44
def project do
@@ -48,11 +48,43 @@ defmodule Blake3.MixProject do
4848
[
4949
blake3: [
5050
path: "native/blake3",
51-
mode: rustc_mode(Mix.env())
51+
mode: rustc_mode(Mix.env()),
52+
default_features: default_features?(),
53+
features: config_features()
5254
]
5355
]
5456
end
5557

5658
defp rustc_mode(:prod), do: :release
5759
defp rustc_mode(_), do: :debug
60+
61+
defp default_features? do
62+
simd = Application.get_env(:blake3, :simd_mode) || System.get_env("BLAKE3_SIMD_MODE")
63+
rayon = Application.get_env(:blake3, :rayon) || System.get_env("BLAKE3_RAYON")
64+
65+
case {simd, rayon} do
66+
{nil, nil} -> true
67+
_ -> false
68+
end
69+
end
70+
71+
defp config_features() do
72+
simd =
73+
case Application.get_env(:blake3, :simd_mode) || System.get_env("BLAKE3_SIMD_MODE") do
74+
"c" -> "c"
75+
:c -> "c"
76+
"c_neon" -> "c_neon"
77+
:c_neon -> "c_neon"
78+
_ -> "std"
79+
end
80+
81+
rayon =
82+
case Application.get_env(:blake3, :rayon) || System.get_env("BLAKE3_RAYON") do
83+
"true" -> "rayon"
84+
true -> "rayon"
85+
_ -> nil
86+
end
87+
88+
Enum.filter([simd, rayon], fn x -> x !== nil end)
89+
end
5890
end

mix.lock

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
%{
2-
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm"},
3-
"ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
4-
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
5-
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
6-
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm"},
7-
"rustler": {:hex, :rustler, "0.21.0", "68cc4fc015d0b9541865ea78e78e9ef2dd91ee4be80bf543fd15791102a45aca", [:mix], [{:toml, "~> 0.5.2", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm"},
8-
"toml": {:hex, :toml, "0.5.2", "e471388a8726d1ce51a6b32f864b8228a1eb8edc907a0edf2bb50eab9321b526", [:mix], [], "hexpm"},
2+
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
3+
"ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f1155337ae17ff7a1255217b4c1ceefcd1860b7ceb1a1874031e7a861b052e39"},
4+
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "a10c6eb62cca416019663129699769f0c2ccf39428b3bb3c0cb38c718a0c186d"},
5+
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"},
6+
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
7+
"rustler": {:hex, :rustler, "0.21.0", "68cc4fc015d0b9541865ea78e78e9ef2dd91ee4be80bf543fd15791102a45aca", [:mix], [{:toml, "~> 0.5.2", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "e5429378c397f37f1091a35593b153aee1925e197c6842d04648d802edb52f80"},
8+
"toml": {:hex, :toml, "0.5.2", "e471388a8726d1ce51a6b32f864b8228a1eb8edc907a0edf2bb50eab9321b526", [:mix], [], "hexpm", "f1e3dabef71fb510d015fad18c0e05e7c57281001141504c6b69d94e99750a07"},
99
}

native/blake3/Cargo.lock

+99
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

native/blake3/Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@ name = "blake3"
33
version = "0.2.1"
44
authors = ["Thomas Jean <thomas.jean486@gmail.com>"]
55

6+
[features]
7+
8+
default = ["blake3/default"]
9+
c = ["blake3/c"]
10+
c_neon = ["blake3/c_neon"]
11+
std = ["blake3/std"]
12+
rayon = ["blake3/rayon"]
13+
14+
615
[lib]
716
name = "blake3"
817
path = "src/lib.rs"

native/blake3/src/lib.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ use rustler::resource::ResourceArc;
88
use std::io::Write;
99
use std::sync::Mutex;
1010

11-
1211
pub struct HasherResource(Mutex<blake3::Hasher>);
1312

1413
rustler_export_nifs!(
1514
"Elixir.Blake3.Native",
1615
[("hash", 1, hash),
1716
("new",0, new),
1817
("update",2,update),
18+
("update_with_join",2,update_with_join),
1919
("finalize",1,finalize),
2020
("derive_key",2,derive_key),
2121
("keyed_hash",2,keyed_hash),
@@ -131,3 +131,21 @@ fn reset<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult<Term<'a>> {
131131

132132
Ok((resource).encode(env))
133133
}
134+
135+
fn update_with_join<'a>(env: Env<'a>, args: &[Term<'a>]) -> NifResult<Term<'a>> {
136+
let resource: ResourceArc<HasherResource> = args[0].decode()?;
137+
let buf : types::Binary = args[1].decode()?;
138+
139+
140+
let mut hasher = resource.0.try_lock().unwrap();
141+
#[cfg(feature = "rayon")]{
142+
hasher.update_with_join::<blake3::join::RayonJoin>(&buf);
143+
}
144+
145+
#[cfg(not(feature = "rayon"))]{
146+
hasher.update_with_join::<blake3::join::SerialJoin>(&buf);
147+
}
148+
149+
Ok((resource).encode(env))
150+
151+
}

0 commit comments

Comments
 (0)