ents.FindInSphere() vs. ents.GetAll() ?

Which one is less costly? I guess it depends on what calculations you do on the entities but in my case, which one is better?


local entsTable = {}
local ply = LocalPlayer()

for k, v in pairs(ents.GetAll()) do
	if v:GetClass() == "keypad" or v:GetClass() == "keypad_wire" or v:GetClass() == "wd_explosive" or v:IsVehicle() then
		if v:GetPos():Distance( ply:GetPos() ) < 400 then
			table.insert(entsTable, v)
		end
	end
end

return entsTable

OR


ents.FindInSphere(ply:GetPos(), 400)

Thanks.

-snip-

I thought I hit edit, whoops. The other post contains the Lua without the html tags showing up so it’ll work as copy/paste.

Instead of using Distance use DistToSqr it’s less expensive

I’ve never had problems with FindInSphere though, so unless you have to run it lots in draw or think hooks i would just use it

Benchmark it:

https://dl.dropboxusercontent.com/u/26074909/tutoring/benchmarking_tips/benchmarking_hud_stuff.lua.html

https://dl.dropboxusercontent.com/u/26074909/tutoring/benchmarking_tips/benchmarking_nw_vars.lua.html

Personally, if you know what type of entities you’re looking for, I’d say keep a list. ents.GetAll( ) may be faster, depending on how many entities are spawned. ents.FindInCone is REALLY expensive, the other finds are not as bad, but still expensive.

For example, if you want to get all players in a radius, instead of using FindInSphere, use player.GetAll( ) and check Distance; it’ll still give you a “sphere” effect, and it’ll be cheaper.

If you want vehicles; instead of FindByClass; every time a vehicle is spawned add it to a list, when it is removed, remove it from the list; then you’ll have a small list to look through instead of all of them.

It depends on each context; run the benchmark and see.

Lua code was messing up and showing partial html tags, here:

Old: https://dl.dropboxusercontent.com/u/26074909/tutoring/benchmarking_tips/benchmarking_old_findinsphere_vs_ents_getall.lua.html

new: https://dl.dropboxusercontent.com/u/26074909/tutoring/benchmarking_tips/benchmarking_findinsphere_vs_ents_getall.lua.html

Remove the .html to get the lua file.

EDIT: Odd, I could’ve sworn I hit edit… Whoops…

Thanks for the benchmark code, I think I’ll try adding the entities to a list when spawned, seems like the right way to go.

I have to run it in a draw hook :confused:

[lua]
local output = {}
local ply = LocalPlayer()
local dist = 400
dist = dist^2

for k,v in pairs(ents.GetAll()) do
if v:GetClass() == “keypad” or v:GetClass() == “keypad_wire” or v:GetClass() == “wd_explosive” or v:IsVehicle() then
if (v:GetPos() - ply:GetPos()):LengthSqr() < dist then
output[ #output + 1 ] = v
end
end
end

return output
[/lua]

This should work and be a lot faster, no?

Why are you running it in a Draw hook?

There may be a quicker way; can you tell us exactly what you’re trying to achieve?

If you look at this: https://dl.dropboxusercontent.com/u/26074909/tutoring/benchmarking_tips/benchmarking_hud_stuff.lua.html

That function runs many times per frame to determine if hud elements should draw. Using table.HasValue many times over causes it to be VERY slow, taking many seconds. The other way took 0.08 for the same quantity…

If there is a better way, we’d be happy to help you ensure it is as optimized as possible.

Do your heavy lifting in a Tick hook rather than a drawing hook. You should get a bit less strain since Tick shouldn’t run as often as the drawing hooks, or you could also use a timer if that’s more simple.

In your drawing hook, you could just reference the data you got from the Tick/timer. It would be significantly more efficient.

EDIT:
Fixed Think to Tick because I was away from my code. Thanks OzymandiasJ.

I need to find all entities of certain classes within a certain range of the player. Then I need to draw stuff in the Paint hook at all of the positions of the entities within the range using ent:GetPos():ToScreen().

Oh, I never thought it made much difference, thanks for the tip! My only concern is, if it doesn’t run as often won’t the 2d elements appear to be slightly out of sync with the position of the entity on screen?

If you have super-human players who can detect minute changes every .03 seconds, then maybe. But I do this for names above player heads, and you really can’t tell, even when it starts fading out. (I also do it for text on doors)

It’s much better to do it in a Tick hook not a Think hook, think runs much more often than Tick and the location of Shared realm entities can only move during a Tick hook, so doing extra calculations more often will have no positive effect.

Thank you for that, Tick is what I meant. I was at work and realized it when I opened up my code.

Even though a tick hook doesn’t run as often, will it still be suitable for calculating the position of 2d elements? Or will the output be the same?

When calculating movement, make sure you link it to time, not to FPS. A lot of old games linked their games to FPS so if you try playing them today it is like you have a speed-hack. If you tie it to time, then that issue will be gone.