我试图在Lua中解析http POST请求。我的实现工作,但吃掉了很多CPU负载。这很关键,因此它位于嵌入式平台上。
我已经查看了其他实现,但它们不合适,因为我的图像几乎不适合内存,因此我不会使用其他库。我推出了自己的解析器,但它使用了太多的系统资源。问题是如何优化它以降低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
答案 0 :(得分:0)
--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