This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
unobtanium's profile picture

Calling pcall with arguments (unpack) lags the program

Started by unobtanium, 03 March 2014 - 01:53 PM
unobtanium #1
Posted 03 March 2014 - 02:53 PM
Hello,

still working on the Client for OpenPeripheral's Glasses and ran into a problem again.

Every two seconds the system updates the screen and calls functions from the peripherals.
The code below is using the unpack(param) function because this method/function needs them.
There is an other version of the code without unpack(param) which doesnt cause any trouble.

local noErr,res = pcall( net.callRemote, unit, method, unpack(param))
	  if noErr then
	    number = tonumber(res)
	  else
	    number = "ERROR"
	    if not errorThrown then
		  drawText("ERROR!!! DRAWING NUMBER WITH ARGUMENTS! " .. res ,1,1,14)
		  errorThrown = true
	    end
	  end


Every two seconds the whole screen gets cleared and rewritten again (i know that is not efficent…).
All objects on the screen get drawn step by step and if the code above gets executed the program experiences a short interruption, which looks like THIS
The more methods the worse it gets.

Is it just the pcall which doesn't like a lot of arguments or is it the unpacking process of the parameter? (I usually just used 1 or 3 arguments)

Thanks for reading.
unobtanium
CometWolf #2
Posted 03 March 2014 - 03:05 PM
Redrawing the whole screen sounds like bad idea, a quick way to optimize it would be to do the calculations first, then clear and draw it again. That should negate any slowdowns on the calculation part of things.

I don't see why it would be much of an issues, as unpack shouldn't be a very resource intensive function.. But you are saying it worked fine with the old non-unpack version, so let's assume that's the problem. Try replacing it with vararg if this is within a function. Alternatively, give this a try instead

function unpack (t, i)
  i = i or 1
  if t[i] ~= nil then
    return t[i], unpack(t, i + 1)
  end
end
This is the unpack function defined in Lua. The actual function itself is written in C.
soruce: http://www.lua.org/pil/5.1.html
Bomb Bloke #3
Posted 03 March 2014 - 03:11 PM
Probably not C, considering we're talking about LuaJ. It's plausible that the function already IS implemented in Lua. I've no idea.
CometWolf #4
Posted 03 March 2014 - 03:13 PM
tbh java and C look the same to me, so i couldn't even tell the difference :P/>
unobtanium #5
Posted 03 March 2014 - 03:36 PM
I cant use vararg really :S
I used your unpack code and it still has the blinking effect i want to get rid of :(/>

Yeah maybe i read everything out first, save it in a table, clear the screen and redraw everything.
(I should probably save the objects in a table and just change them instead of drawing everything again.)

edit: maybe the usage of pcall AND unpack takes a lot of time. i dunno… just a thought
Edited on 03 March 2014 - 02:42 PM
MKlegoman357 #6
Posted 03 March 2014 - 04:21 PM
Or maybe your actual callRemote or method of your peripheral is causing lag.
CometWolf #7
Posted 03 March 2014 - 04:25 PM
Why can't you use varag? how is the param table defined?
unobtanium #8
Posted 03 March 2014 - 04:43 PM
@MKlegoman357: But why would it do that just when i add arguments to it?

@CometWolf:
My whole function looks like this:

Spoiler

function drawNumber(x,y,text,unit,method,maxNumber,c,cMax, param)
  c = colorHex[c]
  cMax = colorHex[cMax]
  local number = "NONE"
  if net.isPresentRemote(unit) and not (method == "NONE") then
    if not (type(param) == "table") then
      number = "NONE"
    elseif not (param[1] == nil) and countArray(param) >= 1 then
      local noErr,res = pcall( net.callRemote, unit, method, unpack(param, 1))
      if noErr then
        number = tonumber(res)
      else
        number = "ERROR"
        if not errorThrown then
          drawText("ERROR!!! DRAWING NUMBER WITH ARGUMENTS! " .. res ,1,1,14)
          errorThrown = true
        end
      end
    else
      local noErr,res = pcall( net.callRemote, unit,method)
      if noErr then
        number = tonumber(res)
      else
        number = "ERROR"
        if not errorThrown then
          drawText("ERROR!!! DRAWING NUMBER WITHOUT ARGUMENTS! " .. res ,1,1,14)
          errorThrown = true
        end
      end
    end
  end
  local lengthText = ((#text) + 2)*6
  local lengthNumber = (#(tostring(number)))*6
  local maxLength = (#(tostring(maxNumber)))*6
  if type(number) == "string" or (type(number) == "number" and number == maxNumber) then
    local var1 = b.addText(x,y,text .. ":",c)
    setZDimension(var1)
    local var2 = b.addText(x+lengthText,y,tostring(number),cMax)
    setZDimension(var2)
    local var3 = b.addText(x+lengthText+maxLength,y, " / " .. maxNumber, c)
    setZDimension(var3)
  else
    local var1 =  b.addText(x,y, text .. ":", c )
    setZDimension(var1)
    local var2 =  b.addText(x+lengthText+(maxLength-lengthNumber),y, number .. " / " .. maxNumber,c)
    setZDimension(var2)
  end
end
CometWolf #9
Posted 03 March 2014 - 04:52 PM

function drawNumber(x,y,text,unit,method,maxNumber,c,cMax, ...)
  c = colorHex[c]
  cMax = colorHex[cMax]
  local number = "NONE"
  if net.isPresentRemote(unit) and not (method == "NONE") then
	if #{...} == 0 then
	  number = "NONE"
	elseif  countArray({...}) >= 1 then
	  local noErr,res = pcall( net.callRemote, unit, method, ...)
	  if noErr then
		number = tonumber(res)
	  else
		number = "ERROR"
		if not errorThrown then
		  drawText("ERROR!!! DRAWING NUMBER WITH ARGUMENTS! " .. res ,1,1,14)
		  errorThrown = true
		end
	  end
	else
	  local noErr,res = pcall( net.callRemote, unit,method)
	  if noErr then
		number = tonumber(res)
	  else
		number = "ERROR"
		if not errorThrown then
		  drawText("ERROR!!! DRAWING NUMBER WITHOUT ARGUMENTS! " .. res ,1,1,14)
		  errorThrown = true
		end
	  end
	end
  end
  local lengthText = ((#text) + 2)*6
  local lengthNumber = (#(tostring(number)))*6
  local maxLength = (#(tostring(maxNumber)))*6
  if type(number) == "string" or (type(number) == "number" and number == maxNumber) then
	local var1 = b.addText(x,y,text .. ":",c)
	setZDimension(var1)
	local var2 = b.addText(x+lengthText,y,tostring(number),cMax)
	setZDimension(var2)
	local var3 = b.addText(x+lengthText+maxLength,y, " / " .. maxNumber, c)
	setZDimension(var3)
  else
	local var1 =  b.addText(x,y, text .. ":", c )
	setZDimension(var1)
	local var2 =  b.addText(x+lengthText+(maxLength-lengthNumber),y, number .. " / " .. maxNumber,c)
	setZDimension(var2)
  end
end
Should do the trick, dunno if the countArray function is nessacary, or if you could just replace it with #, so i left it in place. Im guessing the latter however, since the table would be numerically indexed now.
Edited on 03 March 2014 - 03:53 PM
unobtanium #10
Posted 03 March 2014 - 05:06 PM
Yeah, does the trick it gets rid of the updating.
However it throws an error now:
Failed to convert arg 'slot' value '{1.0=north}' to'ForgeDirection'
or
Failed to convert arg 'direction' value '{3.0=1.0, 2.0=1.0, 1.0=south}' to'ForgeDirection'
That doesnt sound good at all :S
Edited on 03 March 2014 - 04:10 PM
CometWolf #11
Posted 03 March 2014 - 05:11 PM
sounds like something's wrong with the argument you're passing it. From my experience, openP directions need to be east, south, north, west, up or down. Why is yours {1.0=north}? :P/> Maybe that equal is supposed to be a ","? Can't really know what's going on there unless i see the code calling the function.
unobtanium #12
Posted 03 March 2014 - 05:15 PM
Wait…
I called the function above and where the "…" (dots) are i send the table {"south", 1, 1} and it throws me an error.
site[k][10] = {"south", 1, 1}

drawNumber(site[s][k][2]+relX,site[s][k][3]+relY,site[s][k][4],site[s][k][5],site[s][k][6],site[s][k][7],site[s][k][8],site[s][k][9],site[s][k][10])
Edited on 03 March 2014 - 04:16 PM
CometWolf #13
Posted 03 March 2014 - 05:17 PM
Ah… that explains it. Try unpacking the table there instead, otherwise you're passing a table to the peripheral function.
unobtanium #14
Posted 03 March 2014 - 05:23 PM
Uhm yeah, that worked now^^ But it was still flickering…
I now tested it without unpacking and called it with the arguments "south", 1, 1 directly.
Aaaaand flickering. So it is probably the pcall calling with the extra arguments.
So unless there exists an other way to determine an error, i will go with the call-all-methods-first-then-draw version even though it will still freeze the program and prevents the user from interacting…
CometWolf #15
Posted 03 March 2014 - 05:25 PM
Does it flicker if you use an anonymous funciton to pass the arguments, instead of using pcall's arguments? I doubt this will change anything, but i wanna know anyways :P/>
Why would that prevent user interaction? Event's get queued up as normal even if the program is doing something else.
Edited on 03 March 2014 - 04:26 PM
Lyqyd #16
Posted 03 March 2014 - 05:36 PM
It will be easier to diagnose the flickering you describe if you post the whole code, which is an important part of asking a good question. I'd suspect that you're probably clearing the screen before gathering up new data to display, then writing that data to the cleared screen. Instead, you should gather up all of the new data to display, them clear the screen and write the new data. It's hard to tell for sure without seeing the rest of the code.
unobtanium #17
Posted 03 March 2014 - 05:40 PM
@CometWolf:
Using anonymous functions doesn't change anything :D/>
I dont know i allways have the feeling actions get eaten or the system is not responsive enought :(/>
I think if the system is working for 0.1 seconds and is not waiting for a event to pull then the e.g. mouse_click wont be activated.

@Lyqyd:
Here is the full code.
And you are suspecting right. I am clearing the screen before gathering information and rewriting/drawing it back on screen.
This would be the solution, but wanted to check if there would be an other one. (edit: or even a bug someone could fix)
Edited on 03 March 2014 - 04:41 PM
Lyqyd #18
Posted 03 March 2014 - 06:35 PM
Nope, the only fix to stop the flickering is to remove the time consuming stuff between the screen clear and the new data being written, which means you have to gather up the new set of data before clearing the screen.