lua-users home
lua-l archive

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


On 20/04/11 14:59, Valerio Schiavoni wrote:
Hello,

the following code throws a stack overflow error with luajit, but it
works fine (although slowly) with lua 5.1.4.

Also, if you have suggestions on how to improve the running time of it
that'd be nice.


--save as : test-bench-luajit.lua
-- convert big or small number in scientific notation into a decimal string
function to_dec_string(s)
	s = tostring(s)
	local start, stop = string.find(s, "e", 1, true)
	-- not scientific
	if not start then return s end

	local positif = true
	if string.sub(s, 1, 1) == "-" then
		s = tonumber(string.sub(s, 2))
		positif = false
	end

	local t = split(s, "e")
	local m, e = t[1], t[2]
	local t = split(m, ".")
	if t[2] then
		m = t[1]..t[2]
	end

	if string.sub(e, 1, 1) == "-" then
		e = tonumber(string.sub(e, 2))
		for i = 1, e - 1 do
			m = "0"..m
		end
		m = "0."..m
	else
		e = tonumber(e) - #m + 1
		for i = 1, e do
			m = m.."0"
		end
	end
	if not positif then m = "-"..m end
	return m
end

function encode(data)
	local t = type(data)

	if t == 'table' then -- list(array) or hash
		local i = 1
		local list = true
		for k, v in pairs(data) do
			if k ~= i then
				list = false
				break
			end
			i = i + 1
		end
		local out = ''
		if list then
			out = 'l'
			for k, v in pairs(data) do
				out = out..encode(v)
			end
		else -- hash
			out = 'd'
			for k, v in pairs(data) do
				out = out..encode(k)..encode(v)
			end
		end
		return out..'e'
	elseif t == 'string' then
		return #data..':'..data
	elseif t == 'number' then
		-- we need to convert scientific notation to decimal
		return 'i'..to_dec_string(data)..'e'
	elseif t == 'nil' then -- extension of benc
		return 'n'
	elseif t == 'boolean' then -- extension of benc
		if data then
			return 't'
		else
			return 'f'
		end
	end
end

data_sizes={1000,10000,100000,1000000}

print("Bench nested arrays with fixed-size string")
for k,v in pairs(data_sizes) do
	
	local gen="a"
	for i=1,(v/100) do --to avoid stackoverlow
		gen={gen}
	end
	
	start=os.clock()
	enc_data=encode(gen)
	print((v/100), os.clock()-start)
end


best regards,
Valerio



didn't have time to test it and I can't get luatrace to run right now but that split function doesn't look right.

unless I misunderstood the code(of-course it's possible) then the following should replace it an is a *LOT* faster.
As a guess I'd say the stack overflow comes from your use of recursion.

on a string with 1908 random letters tests solely on the split function implementation are below.

function gsplit(s, sep)
	local res = {}
	sep = sep or ' '
	for v in s:gmatch('[^' .. sep .. ']+') do
		res[#res + 1] = v
	end
	return res
end

in lua 5.1.4:
real	0m0.010s
user	0m0.008s
sys	0m0.000s

in luajit2 beta6:
real	0m0.006s
user	0m0.004s
sys	0m0.000s




the original split function:

in lua 5.1.4:
real	0m1.354s
user	0m1.344s
sys	0m0.008s

in luajit2 beta6:
real	0m0.337s
user	0m0.316s
sys	0m0.020s