lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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)