[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Is it supposed to be faster to call a C function than a Lua function when in Lua?
- From: Sean Conner <sean@...>
- Date: Thu, 27 Jun 2013 02:15:43 -0400
It was thus said that the Great Eric Wing once stated:
> I've been doing some performance benchmarks to quantify the cost of
> crossing between scripting language to native code. I'm using Lua as
> my theoretical ideal best performance case. I'm only looking at the
> cost of the function call overhead, not the execution time of doing
> stuff in the function.
>
> One interesting thing came up I didn't expect. Calling a C function
> that takes no parameters and returns no values is faster than calling
> a Lua function with the same signature. On one of my test devices, the
> call time was
> 0.167 microseconds per call calling to C
> 0.234 microseconds per call calling Lua
>
> Passing a number and returning a number via C was:
> 0.235 microseconds per call
>
> Is this the expected behavior? I know my simple arguments in this case
> make things much easier, but I was always under the impression that
> crossing the language bridge was much more expensive than staying in
> the interpreter (i.e. you're only supposed to win if the stuff you do
> in your function on the native side is computationally expensive
> enough to overcome the cost of calling the function).
I can see that being the case. I wrote a quick test (code at bottom of
email) and the results are rather interesting (dual core Pentium 2.6GHz,
running Linux 2.6.9 and Lua 5.1.5):
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.15020370483398
C overhead 0.12874603271484
Lua overhead 0.13828277587891
C overhead 0.10013580322266
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.15974044799805
C overhead 0.64849853515625 ?!
Lua overhead 0.58174133300781 ?!
C overhead 0.19073486328125
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.15974044799805
C overhead 0.1215934753418
Lua overhead 0.16927719116211
C overhead 0.10967254638672
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.15020370483398
C overhead 0.12874603271484
Lua overhead 0.15974044799805
C overhead 0.10013580322266
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.16212463378906
C overhead 0.11920928955078
Lua overhead 0.56982040405273 ?!
C overhead 0.45061111450195
Some odd results. I thought that might be due to garbage collection (due
to the how the C function is defined---check the code), so I reran the code,
this time with some forced garbage collection before the tests:
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.17166137695312
C overhead 0.20980834960938
Lua overhead 0.51021575927734 ?!
C overhead 0.20027160644531
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.15974044799805
C overhead 0.61988830566406 ?!
Lua overhead 0.2288818359375
C overhead 0.11920928955078
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.15974044799805
C overhead 0.13113021850586
Lua overhead 0.14066696166992
C overhead 0.10967254638672
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.15974044799805
C overhead 0.12874603271484
Lua overhead 0.15020370483398
C overhead 0.26941299438477 ?!
[spc]lucy:/tmp>lua test.lua
Lua overhead 0.14781951904297
C overhead 0.13113021850586
Lua overhead 0.15020370483398
C overhead 0.15974044799805
Generally, the C function is faster, but not always, and now that I think
about it, the pauses might be due to task switching (processing being
pre-empted). Now, the reason why the C function is faster is that there is
nothing *to* the C function, and thus, nothing to do (or interpret).
A better test might be a longer run to smooth out the jitters, and maybe
subtract out the overhead of getting the time.
-spc (Anyway, code below)
-- ****************************************
-- the following modules are available at
-- https://github.com/spc476/lua-conmanorg
-- ****************************************
sys = require "org.conman.sys"
cc = require "org.conman.cc"
luanull = function() end
cnull = cc.compile("cnull",[[
#include <lua.h>
#include <lauxlib.h>
int cnull(lua_State *L)
{
return 0;
}
]])
--collectgarbage('collect') -- uncomment to change timings
--collectgarbage('collect')
-- okay, get the time, run the test 100 times, then read the time again.
zen = sys.gettimeofday()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
tao = sys.gettimeofday()
print("Lua overhead",((tao - zen) * 1000000) / 100)
zen = sys.gettimeofday()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
tao = sys.gettimeofday()
print("C overhead",((tao - zen) * 1000000) / 100)
zen = sys.gettimeofday()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull() luanull()
tao = sys.gettimeofday()
print("Lua overhead",((tao - zen) * 1000000) / 100)
zen = sys.gettimeofday()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull() cnull()
tao = sys.gettimeofday()
print("C overhead",((tao - zen) * 1000000) / 100)