Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal
  • 0
DeGariless

Too long without yielding

Question

So, I wrote the program for the spawn computer of a server I play on. Shows rules, announcements etc. Here is is in case you care to look.

 

http://pastebin.com/QYpCrzEp

 

The program runs great for long periods of time, but will randomly show the error "Too long without yielding". It has plenty of os.sleep(x) calls to prevent it from erroring. You can see I have added some extra code near line 365 in hopes to prevent the computer from erroring out. It didn't seem to help nearly as much as I hoped. I think it has to do with when the server lags. Anyone know how to fix this? Thanks.

Link to post
Share on other sites

3 answers to this question

Recommended Posts

  • 0

How many players are in your list "playerData.players"?

You are using insertion sort to sort this list. This is quite slow for big lists. (time: n² with n as the size of the list, table.sort() uses a better sorting algorithm, n * log(n) )

But unless you have a very big list of users it probably isn't the reason

 

Another performance hint:

You can process the list returned by od.getPlayerList() before you continue using it:

local function updatePlayerData(curTime)
  local isOnlinePlayer = {} --This table is the key for speed improvements.
  for _, onlinePlayer in ipairs(od.getPlayerList()) do
    isOnlinePlayer[onlinePlayer] = true
  end
  --It allows you to take the 3 player loops out of the first loop.
  for _, v in pairs(playerData.owner) do
    --Instead of searching if a player is online you now get the answer instantly.
    if isOnlinePlayer[v.name] then
      v.lastseen = curTime
      --This replaces the usage of the variable 'found'.
      isOnlinePlayer[v.name] = nil
    end
  end
  for _, v in pairs(playerData.staff) do
    if isOnlinePlayer[v.name] then
      v.lastseen = curTime
      isOnlinePlayer[v.name] = nil
    end
  end
  for _, v in pairs(playerData.players) do
    if isOnlinePlayer[v.name] then
      v.lastseen = curTime
      isOnlinePlayer[v.name] = nil
    end
  end
  --All players that are still within isOnlinePlayer have to be added to the player list.
  for onlinePlayer in pairs(isOnlinePlayer) do
    local newPlayerData = {name = onlinePlayer, lastseen = curTime, firstseen = curTime}
    table.insert(playerData.players, newPlayerData)
  end
end

But again I'm not sure if your player list is really that big.

 

Here are some other hints:

  1. You can use "xpcall(main, debug.traceback)" for more detailed information than "pcall(main)".
  2. It would also help if you add some kind of logging to your program. (open a file with append mode and write something to the file before and after critical/suspicious parts of your code. (don't forget to do file:flush() after file:write() to ensure that there is no delayed writing)
Link to post
Share on other sites
  • 0

How many players are in your list "playerData.players"?

You are using insertion sort to sort this list. This is quite slow for big lists. (time: n² with n as the size of the list, table.sort() uses a better sorting algorithm, n * log(n) )

But unless you have a very big list of users it probably isn't the reason

 

There are about 30 players in the PlayerData.json file at the moment. I realize that as the number grows, it will become a problem. I plan to have some players automatically removed, or moved to a separate inactive players file of some sort. Thanks for the tip about sorting the table more efficiently. I'll I'll have to take that into consideration in the future.  

 

Another performance hint:

You can process the list returned by od.getPlayerList() before you continue using it:

 

But again I'm not sure if your player list is really that big.

 

Don't know why I didn't think of that.

 

 

Here are some other hints:

  1. You can use "xpcall(main, debug.traceback)" for more detailed information than "pcall(main)".
  2. It would also help if you add some kind of logging to your program. (open a file with append mode and write something to the file before and after critical/suspicious parts of your code. (don't forget to do file:flush() after file:write() to ensure that there is no delayed writing)

xpcall(main, debug.traceback) is exactly what I was originally looking for. Thanks :)

 

 

Thanks for all the tips. I really appreciate it, but unfortunately my problem is still not solved. The computer will still shut down and show "too long without yielding" even when it's left idling without running anything other than OpenOS. I'm now thinking that is has something to do with when the server does it's backup. Backup causes lag, lag causes computer to error out. There must be some way to prevent this from happening or to automatically restart the computer every so often. I'd like to assume that the computer needs to calculate how much time it's taking on an operation based on in game time instead of real world time.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.