LuaJIT suddenly slows down

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

LuaJIT suddenly slows down

Patrick Rapin
Although I have been using Lua for 5 years, I only recently started to
use LuaJIT for image processing tasks.
My observation is that LuaJIT along with FFI for direct byte access is
just incredibly fast, comparable to my C++ reference implementation!

Today, during the implementation of a bitmap rotation, I saw a strange
timing behavior. The first test loops are extremely fast, but the next
ones are really slow.
I have tried the code with LuaJIT 2.0 git HEAD, compiled on Windows
using MSVC 32 bits, MSVC 64 bits, and Cygwin 32 bits. The behavior is
the same in all cases.
The test code below is a very very simplified portion of my code, but
it still shows the problem:

function Test()
        local function Internal()
        end
        for i=0,10000000 do
                Internal()
        end
end

for i=1,1000 do
        local t = os.clock()
        Test(pdst)
        print(("Test %d in %5.3f s"):format(i, os.clock() - t))
end


The test output looks like this on my machine:
.....
Test 93 in 0.004 s
Test 94 in 0.004 s
Test 95 in 0.004 s
Test 96 in 0.003 s
Test 97 in 0.004 s
Test 98 in 0.004 s
Test 99 in 0.004 s
Test 100 in 0.004 s
Test 101 in 0.003 s
Test 102 in 1.683 s
Test 103 in 1.682 s
Test 104 in 1.683 s

The 101 first loops only take 4 ms, while the next ones take 1.68 s,
so suddenly 420 times more!
How can this happen?

Reply | Threaded
Open this post in threaded view
|

Re: LuaJIT suddenly slows down

Mike Pall-31
Patrick Rapin wrote:
> function Test()
> local function Internal()
> end
> for i=0,10000000 do
> Internal()
> end
> end

You're creating a new closure for Internal() on every call. Don't
do that. LuaJIT specializes to each closure and there's a limit to
that. Create the closure outside of Test().

--Mike

Reply | Threaded
Open this post in threaded view
|

Re: LuaJIT suddenly slows down

Alexander Gladysh
On Fri, Sep 2, 2011 at 16:25, Mike Pall <[hidden email]> wrote:
> Patrick Rapin wrote:
>> function Test()
>>       local function Internal()
>>       end
>>       for i=0,10000000 do
>>               Internal()
>>       end
>> end

> You're creating a new closure for Internal() on every call. Don't
> do that. LuaJIT specializes to each closure and there's a limit to
> that. Create the closure outside of Test().

I suspect that calling collectgarbage("step") from time to time should
also help. No?

(But, of course, closure creation ought to be outside of the function
in this case.)

Alexander.

Reply | Threaded
Open this post in threaded view
|

Re: LuaJIT suddenly slows down

David Manura
In reply to this post by Mike Pall-31
On Fri, Sep 2, 2011 at 8:25 AM, Mike Pall <[hidden email]> wrote:
> You're creating a new closure for Internal() on every call. Don't
> do that. LuaJIT specializes to each closure and there's a limit to
> that. Create the closure outside of Test().

Lua 5.2 beta can cache that function [1-2], but LuaJit is currently
based on 5.1 semantics with environments, which doesn't necessarily in
general allow the optimizer to safely pull that function definition
outside.  You can do your own caching as such if your prefer to keep
the function inline:

  local Internal
  function Test()
    Internal = Internal or function() end
    for i=0,10000000 do Internal() end
  end

[1] http://www.lua.org/work/doc/manual.html - "Closures with the same
reference are always equal. Closures with any detectable difference
(different behavior, different definition) are always different."
[2] http://lua-users.org/lists/lua-l/2010-07/msg00862.html