lua-users home
lua-l archive

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


Mike Pall wrote:
> Actually the fast paths in the interpreter are never called from
> compiled code. The trace recorder recogizes a known function and
> simulates the fast path by recording the appropriate IR instead.
> This can be as simple as a single instruction (see below) or a
> maze of conditions and transformations (e.g. string.sub).

Hi Mike,

Can you elaborate on string functions, please?

I recently did a test implementation of FIX message parsing in lua.
LuaJIT 2.0 was a bit faster than parsing by the quickfix 1.13.2
C++ library. The fact that LuaJIT outperforms C++ is great but I feel
it could do better because quickfix parser is quite slow.

Basically, a FIX message is a list of tag=value delimited by '\001' (so
called SOH symbol). Each tag is a number. I look it up in a table and
convert to a human-readable form (e.g. 35 to MsgType). I construct a
table with human readable tags as keys and their values.

For example, this message

'8=FIX4.2|9=222|35=A|34=1|10=123|' (replace all pipes with SOHs)

will be converted to

{ BeginString='FIX4.2', BodyLength='222', MsgType='A', CheckSum='123' }

(CheckSum and BodyLength have wrong values but it doesn't matter)

For some reason I can't use -j so I can only guess (BTW, I built
LuaJIT with lang/gcc44 with -m32 option on NetBSD/amd64 - default
compiler could'n find unwind.h). Surely, string.find is not the
greatest contributor but could it be that LuaJIT doesn't optimize
a case of searching for a single char?

I search for the SOH and for the equal sign. I also do string.sub to
get a tag and a value.

local function parse_impl(msg, pos, ver)

    local tags = tags_by_ver[ver]

    local res = { BeginString = ver }
    while true do
        local eq  = string.find(msg, '=', pos, true)
        local soh = string.find(msg, '\001', eq + 1, true)
        local tag = string.sub(msg, pos, eq - 1)
        local tdef = tags[tag]
        local val = string.sub(msg, eq + 1, soh - 1)
        pos = soh + 1
        if type(tdef) == 'string' then
            res[tdef] = val
            if tag == '10' then
                --pos = (soh or string.len(msg)) + 1
                break
            end
        else
            -- handling of more complex fields is skipped
        end
    end
    return res, pos
end

Thanks,
Alex