Syntax and performance questions?
stuta opened this issue · comments
Hello. This seems great, it is very good to have same syntax as underscore.
- Is syntax different from https://lodash.com that everyone in javascript world is using now?
- Has anyone done performance tests against https://luafun.github.io?
Hi @stuta
Moses have lots of functions which were inspired/taken from lodash. As such, they have a quite similar syntax. Either way, since Moses is Lua and lodash is JavaScript, there are indeed some differences. Check out the tutorial for examples.
Regarding LuaFun, no there are no performance tests comparing Moses to LuaFun that I know of. But I believe on some points, LuaFun might be faster than Moses, since it ws designed with performance in mind and taking advantage of LuaJIT.
I tried this code:
local fn = require "fn" -- https://github.com/rtsisyk/luafun
local _ = require "moses" -- https://github.com/Yonaba/Moses/blob/master/doc/tutorial.md
local function filterFn(x)
return x % 2 == 0
end
local function mapFn(x)
return x + 0.1
end
local time1 = util.seconds()
local gen1 = fn.iter(arr):filter(filterFn):map(mapFn):take(3):totable()
time1 = util.seconds(time1)
print(string.format('%.6f seconds: %s', time1, table.concat(gen1, ', ')))
local time2 = util.seconds()
local gen2 = _(arr):filter(filterFn):map(mapFn):take(3):value()
time2 = util.seconds(time2)
print(string.format('%.6f seconds: %s', time2, table.concat(gen2, ', ')))
print(string.format("time1: %.6f / time2: %.6f, luafun is %.0f times faster than moses", time1, time2, time2/time1))
Result is different (filter is not working?), maybe I'm doing something wrong in moses?
0.000043 seconds: 2.1, 4.1, 6.1
0.943609 seconds: 1.1, 2.1, 3.1
time1: 0.000043 / time2: 0.943609, luafun is 21730 times faster than moses
I see why results are different. Actually, the syntax with Moses is defined with key-values pairs in mind as arguments for most functions. In your code, filter
and map
actually operate on keys of array arr
, not its values. I believe your example should be refactored like this :
local function filterFn(i, x) return x % 2 == 0 end
local function mapFn(i, x) return x + 0.1 end
local gen2 = _(arr):filter(filterFn):map(mapFn):take(3):value()
Regarding the time difference, I am a bit surprised...Have you run both codes with LuaJIT ?
I refactored the code.
Luajit 5.1:
0.000062 seconds: 2.1, 4.1, 6.1
3.179571 seconds: 2.1, 4.1, 6.1
time1: 0.000062 / time2: 3.179571, luafun is 51283 times faster than moses
Luajit 2.1 git:
0.000051 seconds: 2.1, 4.1, 6.1
0.958241 seconds: 2.1, 4.1, 6.1
time1: 0.000051 / time2: 0.958241, luafun is 18789 times faster than moses
There are some differences in times when running multiple times. Luafun does this lazily so the jit compiler does not kick in in 3 loops and luajit vs lua5.1 times are equal (depending on the run, times are very small).
Luafun is not maintained any more. If community could take all the good parts from there to moses it would be very good library.
Fixed code:
local _ = require "moses" -- https://github.com/Yonaba/Moses/blob/master/doc/tutorial.md
local fn = require "luafun" -- https://github.com/rtsisyk/luafun
local function filterFn(x)
return x % 2 == 0
end
local function mapFn(x)
return x + 0.1
end
local function filterFn2(_, x)
return x % 2 == 0
end
local function mapFn2(_, x)
return x + 0.1
end
local time1 = os.clock()
local gen1 = fn.iter(arr):filter(filterFn):map(mapFn):take(3):totable()
time1 = os.clock() - time1
print(string.format('%.6f seconds: %s', time1, table.concat(gen1, ', ')))
local time2 = os.clock()
local gen2 = _(arr):filter(filterFn2):map(mapFn2):take(3):value()
time2 = os.clock() - time2
print(string.format('%.6f seconds: %s', time2, table.concat(gen2, ', ')))
print(string.format("time1: %.6f / time2: %.6f, luafun is %.0f times faster than moses", time1, time2, time2/time1))
Since a specific error was not reported here, I will close this issue.
Thanks.