I'm working on creating a game mode, I'm running into a fps problem. Over time the fps get lower and lower. I normally get around 200, but by the end of the game it goes down to 30. I'm wondering what would cause the FPS to gradually get lower.
don't call surface.GetTextureID or Material in any think or paint hooks
[QUOTE=PortalGod;46332378]don't call surface.GetTextureID or Material in any think or paint hooks[/QUOTE]
Hmm, I have all of them being called to a local var outside the think/paint hooks anyone else know of anything that could cause it??
don't create any panels in any think/paint hooks either
pretty much don't do anything expensive inside them
[QUOTE=PortalGod;46332415]don't create any panels in any think/paint hooks either
pretty much don't do anything expensive inside them[/QUOTE]
What do you mean by "expensive" the only thing I can think of that might be "expensive" is the player is tracing in at least 3 times/places on the paint hook.
[QUOTE=digipixel;46332460]What do you mean by "expensive" the only thing I can think of that might be "expensive" is the player is tracing in at least 3 times/places on the paint hook.[/QUOTE]
Don't use certain garry functions like table.HasValue.
try not to use timers, use CurTime() instead.
Here's an example of the meaning expensive ( benchmark: [url]https://dl.dropboxusercontent.com/u/26074909/tutoring/_utilities/util_benchmark.lua[/url] ) using table.HasValue vs direct-access.. 15 seconds vs 0.08 seconds when running the same hook 100 million times: [url]https://dl.dropboxusercontent.com/u/26074909/tutoring/benchmarking_tips/benchmarking_hud_stuff.lua.html[/url]
Proper hud creation: [url]https://dl.dropboxusercontent.com/u/26074909/tutoring/vgui/proper_hud_creation.lua.html[/url]
A hook that runs x times every frame is already running O( n ) times, if we add a look via table.HasValue then it becomes an exponentially growing in cost function O( n^2 ), but if we use one of Luas strongest abilities, being a language of tables Lua is quite fantastic using direct-access, then we are adding a constant O( 1 ) being the lowest possible cost we don't add "any cost" to the execution.
There are a lot of little things that can increase cost, maybe not on the order of something obvious as the above example, but memory leaks can be tricky to find if you don't know what to look for or how certain things work.
surface.CreateFont creates a font, the interesting thing is they are NEVER released until the game is closed ( I don't think this has been fixed yet ) meaning that if you join one server and then another of a different game-mode and they try to use a font from the previous game-mode it'll work but others that didn't join the previous game-mode will get an error... This is one of the leaks, BUT and a big but at that is that it does exactly what you want it to... It creates a font; if you create it in a loop or repeating hook then it'll keep recreating it which takes memory until there is no memory left to give ( then crash )..
Material does something too, although I'm pretty sure these are wiped when you leave / join a different game. But, if you keep calling it in a loop or repeated hook, it'll keep loading the material into memory until you run out of memory ( and crash ).
There are other things that are just like it.
Traces are fine, I've run a lot of stress-tests with traces and haven't noticed anything out of the norm, nor have I noticed a memory leak with them so you should be fine with them...
How can I get around table.HasValue Right now I'm calling it on the think hook to handle keyboard input like so
[CODE]if input.IsKeyDown( key ) && !table.HasValue( keys, key ) && IsNotBusy() then
-- Do stuff
table.insert( keys, key)
end
if !input.IsKeyDown( key ) && table.HasValue( keys, key ) then
-- Do stuff
table.RemoveByValue( keys, key )
end[/CODE]
is there a way around using table.HasValue but still have the same functionally?
This code cannot slow down your fps, the problem is elsewhere, show your "paint" hook
-snip-
[QUOTE=digipixel;46333007]How can I get around table.HasValue Right now I'm calling it on the think hook to handle keyboard input like so
[CODE]if input.IsKeyDown( key ) && !table.HasValue( keys, key ) && IsNotBusy() then
-- Do stuff
table.insert( keys, key)
end
if !input.IsKeyDown( key ) && table.HasValue( keys, key ) then
-- Do stuff
table.RemoveByValue( keys, key )
end[/CODE]
is there a way around using table.HasValue but still have the same functionally?[/QUOTE]
Yes,
Show us your table.
this is the full code I'm using
[CODE]local KeyList =
{
KEY_0,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_A,
KEY_APOSTROPHE,
KEY_APP,
KEY_B,
KEY_BACKQUOTE,
KEY_BACKSLASH,
KEY_BACKSPACE,
KEY_BREAK,
KEY_C,
KEY_CAPSLOCK,
KEY_CAPSLOCKTOGGLE,
KEY_COMMA,
KEY_COUNT,
KEY_D,
KEY_DELETE,
KEY_DOWN,
KEY_E,
KEY_END,
KEY_ENTER,
KEY_EQUAL,
KEY_ESCAPE,
KEY_F,
KEY_F1,
KEY_F10,
KEY_F11,
KEY_F12,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_FIRST,
KEY_G,
KEY_H,
KEY_HOME,
KEY_I,
KEY_INSERT,
KEY_J,
KEY_K,
KEY_L,
KEY_LALT,
KEY_LAST,
KEY_LBRACKET,
KEY_LCONTROL,
KEY_LEFT,
KEY_LSHIFT,
KEY_LWIN,
KEY_M,
KEY_MINUS,
KEY_N,
KEY_NONE,
KEY_NUMLOCK,
KEY_NUMLOCKTOGGLE,
KEY_O,
KEY_P,
KEY_PAD_0,
KEY_PAD_1,
KEY_PAD_2,
KEY_PAD_3,
KEY_PAD_4,
KEY_PAD_5,
KEY_PAD_6,
KEY_PAD_7,
KEY_PAD_8,
KEY_PAD_9,
KEY_PAD_DECIMAL,
KEY_PAD_DIVIDE,
KEY_PAD_ENTER,
KEY_PAD_MINUS,
KEY_PAD_MULTIPLY,
KEY_PAD_PLUS,
KEY_PAGEDOWN,
KEY_PAGEUP,
KEY_PERIOD,
KEY_Q,
KEY_R,
KEY_RALT,
KEY_RBRACKET,
KEY_RCONTROL,
KEY_RIGHT,
KEY_RSHIFT,
KEY_RWIN,
KEY_S,
KEY_SCROLLLOCK,
KEY_SCROLLLOCKTOGGLE,
KEY_SEMICOLON,
KEY_SLASH,
KEY_SPACE,
KEY_T,
KEY_TAB,
KEY_U,
KEY_UP,
KEY_V,
KEY_W,
KEY_X,
KEY_XBUTTON_A,
KEY_XBUTTON_B,
KEY_XBUTTON_BACK,
KEY_XBUTTON_DOWN,
KEY_XBUTTON_LEFT,
KEY_XBUTTON_LEFT_SHOULDER,
KEY_XBUTTON_LTRIGGER,
KEY_XBUTTON_RIGHT,
KEY_XBUTTON_RIGHT_SHOULDER,
KEY_XBUTTON_RTRIGGER,
KEY_XBUTTON_START,
KEY_XBUTTON_STICK1,
KEY_XBUTTON_STICK2,
KEY_XBUTTON_UP,
KEY_XBUTTON_X,
KEY_XBUTTON_Y,
KEY_XSTICK1_DOWN,
KEY_XSTICK1_LEFT,
KEY_XSTICK1_RIGHT,
KEY_XSTICK1_UP,
KEY_XSTICK2_DOWN,
KEY_XSTICK2_LEFT,
KEY_XSTICK2_RIGHT,
KEY_XSTICK2_UP,
KEY_Y,
KEY_Z,
}
local MouseList =
{
MOUSE_LEFT,
MOUSE_RIGHT,
MOUSE_MIDDLE,
MOUSE_4,
MOUSE_5,
MOUSE_WHEEL_UP,
MOUSE_WHEEL_DOWN,
MOUSE_COUNT,
MOUSE_FIRST,
MOUSE_LAST,
}
local function IsNotBusy()
if LocalPlayer():IsTyping() || gui.IsGameUIVisible() || gui.IsConsoleVisible() then
return false
end
return true
end
local keys = {}
local mouses = {}
function KeyEvents()
local keyin, mousein, keyout, mouseout
for _, key in pairs(KeyList) do
if input.IsKeyDown( key ) && !table.HasValue( keys, key ) && IsNotBusy() then
keyin = key
table.insert( keys, key)
end
if !input.IsKeyDown( key ) && table.HasValue( keys, key ) then
keyout = key
table.RemoveByValue( keys, key )
end
end
for _, mouse in pairs(MouseList) do
if input.IsMouseDown( mouse ) && !table.HasValue( mouses, mouse ) && IsNotBusy() then
mousein = mouse
table.insert( mouses, mouse)
end
if !input.IsMouseDown( mouse ) && table.HasValue( mouses, mouse ) then
mouseout = mouse
table.RemoveByValue( mouses, mouse )
end
end
if keyin != nil || mousein != nil then
GAMEMODE:KeyDown( keyin, mousein )
end
if keyout != nil || mouseout != nil then
GAMEMODE:KeyUp( keyout, mouseout )
end
end
hook.Add("Think", "KeyLisener", KeyEvents)
[/CODE]
I'm guessing I could do a keys[key] = true/false
[editline]26th October 2014[/editline]
If I where to make my own function like
[CODE]function HasValue(table, value)
for _, val in pairs(table) do
if val == value then return true end
end
return false
end[/CODE]
would it make much of a difference?
[QUOTE=digipixel;46336447]this is the full code I'm using
I'm guessing I could do a keys[key] = true/false
would it make much of a difference?[/QUOTE]
You're using pairs on an array-like table, that's a waste of resources.
[quote]
[B]I'm guessing I could do a keys[key] = true/false
would it make much of a difference?[/B][/quote]
Yes, this is the preferred way of doing it.
Make the values the key, and 'true' the value so that you index the table using the key and get true or nil.
e.g.
[lua]
local KeyList =
{
[KEY_0] = true,
[KEY_1] = true,
[KEY_2] = true,
}
local function validkey(key) return KeyList[key] or false end
[/lua]
[QUOTE=digipixel;46336447]
If I where to make my own function like
[CODE]function HasValue(table, value)
for _, val in pairs(table) do
if val == value then return true end
end
return false
end[/CODE]
would it make much of a difference?[/QUOTE]
Yes, do what vexx said, with the keys[key] = true; then to check it do if keys[key]
The function you just wrote is what the table.HasValue function is, and if you are running this function every so often, and you are running it twice it seems, it will cause low fps due to the looping through table.
You must have really bad computers if it slow down from 200 to 30fps just by looping on a table with ~100 items, lol
Also notice that he said it's only happening after a certain time.
It happens over time and I have this as my pc [url]http://pcpartpicker.com/user/Craigbett/saved/dqsnTW[/url] which is total over kill for gmod. So I know it's something I put into it. It should never get to 30fps with the build I have. Changing the way I handle input seems to have fixed it.
[QUOTE=AnonTakesOver;46332837]Don't use certain garry functions like table.HasValue.
try not to use timers, use CurTime() instead.[/QUOTE]
timers aren't really that bad unless you're doing something stupid like iterating a value every second or something in that regard. personally I don't use the timer library much because I think it makes my code a lot harder to read but as far as preformance goes I don't see how it's any more expensive than doing something like
[code]local nextthink = 0
if ( nextthink < CurTime() ) then
-- do things?
nextthink = CurTime() + delay
end[/code]
Sorry, you need to Log In to post a reply to this thread.