Lua的HTTP解析器
问题描述:
我想解析Lua中的http POST请求。我的实现工作,但吃了很多CPU负载。这是至关重要的,因此它在嵌入式平台上。Lua的HTTP解析器
我看过其他的实现,但它们不适合,因为我的图像很难适应内存,所以我不会使用另一个库。我推出了自己的解析器,但它使用了太多的系统资源。问题是我如何优化这个以降低CPU负载。
这是一个基于OpenWRT的系统,所以我只有Lua 5.1。这是查找边界的核心函数(在str变量中)。它逐块读取输入块,并寻找它。
另一种解决方案是使用LUCI库来完成繁重的工作,但我不希望我的代码被集成到LUCI中。
--look for a pattern (str) and copy input until it is found to the output.
local function writeuntil(in_fp, str, out_fp)
local buff = ""
local ret = false
local bs = 4096 --Block size. The amount of data to read at once
local c = in_fp:read(bs)
local strStartPos = 1
while c do
local blockLen = string.len(c) --Not sure that a whole block is read, so get the size of the actual block.
local found = string.find(c, str, 1, true) --Try to locate str, so we don't have much work.
if (found ~= nil) then
if found > 2 then
out_fp:write(string.sub(c, 1, found - 1))
end
ret = true
break --we are done
else --Try to mach str till the end of the block
local strPos = string.find(c, string.sub(str, strStartPos, strStartPos), 1, true) --try to locate the first character
if strPos then --There is a starting character in the block
if (strPos > 1) then
out_fp:write(string.sub(c, 1, strPos - 1))
end
for i = strPos, blockLen do --iterate through the block
local ch = string.sub(c, i, i)
if ch == string.sub(str, strStartPos, strStartPos) then
buff = buff .. ch
if string.len(buff) == string.len(str) then
ret = true
break --We're done
end
strStartPos = strStartPos + 1
else --Lost track. Output.
if string.len(buff) > 0 then
out_fp:write(buff)
buff = ""
end
out_fp:write(ch)
strStartPos = 1
end
end
else
out_fp:write(c)
end
end
if ret then
break
end
c = in_fp:read(bs) --read next block
end
return ret
end
答
叶戈尔,你是对的,但我结束了这个解决方案。它现在使用的CPU少得多。这并不完美,因此scp更快(尽管这是用C实现的)。
--look for a pattern (str) and copy input until it is found to the output.
local function writeuntil(in_fp, str, out_fp)
local buff = ""
local ret = false
local bs = 4096 --Block size. The amount of data to read at once
local c = in_fp:read(bs)
local strStartPos = 1
local lastStrPos = 1
local needData = true
while c do
local blockLen = string.len(c) --Not sure that a whole block is read, so get the size of the actual block.
local found = string.find(c, str, 1, true) --Try to locate str, so we don't have much work.
if (found ~= nil) then
if found > 1 then
if #buff > 0 then
out_fp:write(buff)
end
out_fp:write(string.sub(c, 1, found - 1))
end
ret = true
break --we are done
else --Try to mach str till the end of the block
local strPos = string.find(c, string.sub(str, strStartPos, strStartPos), lastStrPos, true) --try to locate the first character
if strPos then --There is a starting character in the block
out_fp:write(string.sub(c, lastStrPos, strPos - 1))
for i = strPos, blockLen do --iterate through the block
local ch = string.sub(c, i, i)
if ch == string.sub(str, strStartPos, strStartPos) then
buff = buff .. ch
if string.len(buff) == string.len(str) then
ret = true
break --We're done
end
strStartPos = strStartPos + 1
lastStrPos = i + 1
else --Lost track. Output.
if string.len(buff) > 0 then
out_fp:write(buff)
buff = ""
end
out_fp:write(ch)
strStartPos = 1
if i == blockLen then
needData = true
else
lastStrPos = i + 1
needData = false
end
break
end
end
else
if ret == false then
if string.len(buff) > 0 then
out_fp:write(buff)
buff = ""
end
out_fp:write(string.sub(c, lastStrPos))
lastStrPos = 1
needData = true
else
break
end
end
end
if ret then
break
end
if needData then
c = in_fp:read(bs) --read next block
lastStrPos = 1
end
end
return ret
end
您正在开始过早地搜索单个字符。改变你的第21行:'local strPos = string.find(c,string.sub(str,strStartPos,strStartPos),math.max(1,#c - #str + strStartPos + 1),true) - - 找到第一个字符' –
我不明白它是否会有所帮助。 Str可以在缓冲区中的任何位置。 – Lev
这将减少大量无用的搜索。去尝试一下。 –