Skip to content

Commit

Permalink
Merge pull request #2 from jw3126/perf
Browse files Browse the repository at this point in the history
unrolled transform!
  • Loading branch information
oxinabox authored Jan 11, 2018
2 parents 9a13fe7 + c310e5b commit 61514df
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 50 deletions.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MD5.jl package is licensed under the MIT "Expat" License:

> Copyright (c) 2018: Lyndon White.
> Copyright (c) 2018: Lyndon White and Jan Weidner.
> Copyright (c) 2014: Elliot Saba. (SHA.jl)
> Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm, Copyright (C) 1991-2
>
Expand Down
96 changes: 47 additions & 49 deletions src/core.jl
Original file line number Diff line number Diff line change
@@ -1,56 +1,54 @@
# Nonlinear functions, in order to encourage inlining, these sadly are not an array of lambdas
f_round0(b,c,d) = SHA.Round0(b,c,d) #UInt32((b & c) | (~b & d))
f_round1(b,c,d) = UInt32((b & d) | (c & ~d))
f_round2(b,c,d) = SHA.Round1And3(b,c,d) # return UInt32(b ⊻ c ⊻ d) #xors
f_round3(b,c,d) = UInt32(c (b | ~d))

g_round0(i) = i
g_round1(i) = (5i+1) % 16
g_round2(i) = (3i + 5) % 16
g_round3(i) = 7i % 16


function conclude_round(a,b,c,d,f,g,pbuf,i)
@inbounds s = ss[i+1]
@inbounds k = kk[i+1]
@inbounds m = unsafe_load(pbuf, g+1)
f = f + a + k + m
a = d
d = c
c = b
b = b + lrot(s,f, 32)
a,b,c,d
end

@generated function transform!(context::MD5_CTX)
ret = quote
pbuf = buffer_pointer(context)
end
ex = quote
@inbounds A = context.state[1]
@inbounds B = context.state[2]
@inbounds C = context.state[3]
@inbounds D = context.state[4]
end
push!(ret.args, ex)
for i in 0:63
if 0 i 15
ex = :(F = (B & C) | ((~B) & D))
g = i
elseif 16 i 31
ex = :(F = (D & B) | ((~D) & C))
g = 5i + 1
elseif 32 i 47
ex = :(F = B C D)
g = 3i + 5
elseif 48 i 63
ex = :(F = C (B | (~D)))
g = 7i
end
push!(ret.args, ex)
g = (g % 16) + 1
ex = quote
temp = D
D = C
C = B
inner = A + F + $(kk[i+1]) + unsafe_load(pbuf, $g)
rot_inner = lrot($(ss[i+1]), inner, 32)
B = B + rot_inner
A = temp
end
push!(ret.args, ex)
end

function transform!(context::MD5_CTX)
pbuf = buffer_pointer(context)
a,b,c,d = context.state

for i in 0:15
f = f_round0(b,c,d)
g = g_round0(i)
a,b,c,d = conclude_round(a, b, c, d, f, g, pbuf, i)
end
for i in 16:31
f = f_round1(b,c,d)
g = g_round1(i)
a,b,c,d = conclude_round(a, b, c, d, f, g, pbuf, i)
end
for i in 32:47
f = f_round2(b,c,d)
g = g_round2(i)
a,b,c,d = conclude_round(a, b, c, d, f, g, pbuf, i)
end
for i in 48:63
f = f_round3(b,c,d)
g = g_round3(i)
a,b,c,d = conclude_round(a, b, c, d, f, g, pbuf, i)
ex = quote
@inbounds context.state[1] += A
@inbounds context.state[2] += B
@inbounds context.state[3] += C
@inbounds context.state[4] += D
end
push!(ret.args, ex)
quote
$ret
end
@inbounds context.state .+= [a,b,c,d]
end


function digest!(context::T) where {T<:MD5_CTX}
pad_remainder!(context)

Expand Down
16 changes: 16 additions & 0 deletions test/perf.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import MD5
using BenchmarkTools

data = randstring(10^4)

if Pkg.installed("Nettle") != nothing
import Nettle
@show Nettle.hexdigest("md5", data)
display(@benchmark Nettle.hexdigest("md5", data))
println()
end

@show bytes2hex(MD5.md5(data))
display(@benchmark MD5.md5(data))
println()

0 comments on commit 61514df

Please sign in to comment.