Why is this slow?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Why is this slow?

Jakab
When doing benchmark tests between Lua and Python, Lua beat it on almost
every test. However, it was considerably slower on a test of passing data
between Lua and C. Here is the Lua code:

function TestDataPass(caller)
	local c = {}
	c.peer = caller

	value = getData(c.peer, "testdata")
	setData(c.peer, "testdata", value + 1)

	return c
end

Here is the C code:

int getData(lua_State *L) 
{
	// 1st argument = calling object pointer (userdata)
	// 2nd argument = data name (string)
	TestObject *object = (TestObject *)lua_touserdata(L, 1);
	const char *varname = lua_tostring(L, 2);

	int value = object->GetData(varname);

	// push the return value on the stack
	lua_pushnumber(L, value);

	return 1;
} // getData

int setData(lua_State *L) 
{
	// 1st argument = calling object pointer (userdata)
	// 2nd argument = data name (string)
	// 3rd argument = data value (number)
	TestObject *object = (TestObject *)lua_touserdata(L, 1);
	const char *varname = lua_tostring(L, 2);
	int value = (int)lua_tonumber(L, 3);

	object->SetData(varname, value);

	return 0;
} // setData

void runtest(TestObject *obj)
{
	int oldtop = lua_gettop(L);
	int result = lua_dofile(L, "TestDataPass.lua");
	if (result != 0)
		return;

	// call the constructor
	lua_getglobal(L, "TestDataPass");
	lua_pushuserdata(L, obj);
	result = lua_call(L, 1, 1);
	if (result != 0)
	{
		lua_settop(L, oldtop);
		return;
	}
	// get the reference to the returned class (locking it so it won't
be
	// garbage collected)
	int classRef = lua_ref(L, 1);
	// free the class reference
	lua_unref(L, classRef);
} // runtest

TestObject is just a structure that maps a string to an integer.

I was able to call the runtest function around 30,000 times in 10 seconds,
but similar test using Python ran 500,000 times in 10 seconds. Am I doing
something wrong in my calls? When I tried a test just calling a do-nothing
function in Lua, it beat Python easily, so I assume that it's the paramater
passing that's slowing Lua down.

-Steve Jakab
Verant


Reply | Threaded
Open this post in threaded view
|

Re: Why is this slow?

Joshua Ritter
Hm... I would guess it has to do with the amount of memory being allocated
and freed in the Lua version...
Does your python version have an equivalent:

local c ={}
c.peer = caller

I am also skeptical of forcing the garbage collection like this...

Of course I am darned new to Lua myself!

-J


----- Original Message -----
From: "Jakab, Steve" <[hidden email]>
To: "Multiple recipients of list" <[hidden email]>
Sent: Wednesday, February 07, 2001 9:41 AM
Subject: Why is this slow?


> When doing benchmark tests between Lua and Python, Lua beat it on almost
> every test. However, it was considerably slower on a test of passing data
> between Lua and C. Here is the Lua code:
>
> function TestDataPass(caller)
> local c = {}
> c.peer = caller
>
> value = getData(c.peer, "testdata")
> setData(c.peer, "testdata", value + 1)
>
> return c
> end
>
> Here is the C code:
>
> int getData(lua_State *L)
> {
> // 1st argument = calling object pointer (userdata)
> // 2nd argument = data name (string)
> TestObject *object = (TestObject *)lua_touserdata(L, 1);
> const char *varname = lua_tostring(L, 2);
>
> int value = object->GetData(varname);
>
> // push the return value on the stack
> lua_pushnumber(L, value);
>
> return 1;
> } // getData
>
> int setData(lua_State *L)
> {
> // 1st argument = calling object pointer (userdata)
> // 2nd argument = data name (string)
> // 3rd argument = data value (number)
> TestObject *object = (TestObject *)lua_touserdata(L, 1);
> const char *varname = lua_tostring(L, 2);
> int value = (int)lua_tonumber(L, 3);
>
> object->SetData(varname, value);
>
> return 0;
> } // setData
>
> void runtest(TestObject *obj)
> {
> int oldtop = lua_gettop(L);
> int result = lua_dofile(L, "TestDataPass.lua");
> if (result != 0)
> return;
>
> // call the constructor
> lua_getglobal(L, "TestDataPass");
> lua_pushuserdata(L, obj);
> result = lua_call(L, 1, 1);
> if (result != 0)
> {
> lua_settop(L, oldtop);
> return;
> }
> // get the reference to the returned class (locking it so it won't
> be
> // garbage collected)
> int classRef = lua_ref(L, 1);
> // free the class reference
> lua_unref(L, classRef);
> } // runtest
>
> TestObject is just a structure that maps a string to an integer.
>
> I was able to call the runtest function around 30,000 times in 10 seconds,
> but similar test using Python ran 500,000 times in 10 seconds. Am I doing
> something wrong in my calls? When I tried a test just calling a do-nothing
> function in Lua, it beat Python easily, so I assume that it's the
paramater
> passing that's slowing Lua down.
>
> -Steve Jakab
> Verant
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Why is this slow?

Edgar Toernig
In reply to this post by Jakab
Hi,

"Jakab, Steve" wrote:
> 
> When doing benchmark tests between Lua and Python, Lua beat it on almost
> every test. However, it was considerably slower on a test of passing data
> between Lua and C. Here is the Lua code:
> 
> function TestDataPass(caller)
>         local c = {}
>         c.peer = caller
> 
>         value = getData(c.peer, "testdata")
>         setData(c.peer, "testdata", value + 1)
> 
>         return c
> end
> 
> Here is the C code:
> [...]
> 
> void runtest(TestObject *obj)
> {
>         int oldtop = lua_gettop(L);
>         int result = lua_dofile(L, "TestDataPass.lua");
>         if (result != 0)
>[...] 
> I was able to call the runtest function around 30,000 times in 10 seconds,
> but similar test using Python ran 500,000 times in 10 seconds. Am I doing
> something wrong in my calls?

They main performance killer is the lua_dofile().  Did you really want
to compile the testfile for each iteration of your test (3000/s)?  You
will not be testing data passing put compilation speed :-)  Do it once
before you call runtest the first time and I guess you'll already beat
Python ;-)

And then there's the Lua code itself.  I do not know if you really want
to create a new table each time TestDataPass() is called, but the line
"local c = {}" takes approximately half of the time.  And at last, you
should make the variable "value" a local.  They are faster than globals.

Ciao, ET.