ID:1409710
 
So, after doing some testing, I've come across an interesting finding.

It turns out that my testing view()/range() is in fact, not faster than viewers()/hearers(). Not only that, my test environments seem to indicate over a large number of iterations, that view()/range() are in most cases, twice as fast as viewers()/hearers().

Not only that, iterating through the results of view()/range() for a specific type of object is still about twice as fast as looping through every element in sequence of viewers()/hearers().


Am I crazy? Can I get someone to double-check my findings:

Test machine:

3.2ghz Core i7, Oc'd to 3.6ghz
8GB RAM
Windows 7 Ultimate
Nvidia GTX 660 in dual SLI.

All tests run for approximately 100,000 iterations:

"if src in X":

view(10,usr): 1.554 seconds
oview(10,usr): 1.557 seconds
range(10,usr): 1.555 seconds
orange(10,usr): 1.546 seconds
hearers(10,usr): 3.884 seconds
ohearers(10,usr): 3.854 seconds
viewers(10,usr): 3.886 seconds
oviewers(10,usr): 3.880 seconds

I did a second test, iterating through a list of 11 mobs in a 10x10 map, with a total range of 10 tiles for each object.

I wound up finding that the iterative loop was 2.397 seconds for view/range derivatives, and 5.5 seconds with hearers/viewers derivatives.


Finally, my testing code:

I simply swapped each function out after five or six tests of each, noting the average results.

mob
Click()
while(count<100000)
if(src in range(10,usr))
count++ //accounts for an average of 0.015 seconds self CPU


mob
Click()
while(count<100000)
for(var/mob/M in range(10,usr))
count++ //accounts for an average of 0.015 seconds self CPU



I was sort of sold by the entire "Viewers/Hearers is faster." stuff people say around here all the time, and I'm quite embarrassed to have just found out that we may well have been wrong.

However, it does indeed make sense that it would be slower, because it's essentially checking all mobs within a particular range of the user, then checking if the specified mob is in their visibility list. --Thus, this is going to result in some added overhead.

Just because I'm not a fan of being wrong when can be helped, anybody wanna double-check my findings and/or dispute my methodology?
Okay, I'm finding some cases where viewers() and hearers() actually outperforms view(), but not range().

It appears, that range() is the fastest of the bunch, down and out. However, in best-case scenarios, where a large number of mobs are obscured by opaque walls, it appears that viewers() beats view() by a very small amount. When surrounded with opaque walls such that half of the map, and half the mobs are obscured by said wall, iterating through viewers/hearers() takes approximately 5.4 seconds per 100,000 operations, while operating through view() takes roughly 6.7 seconds per 100,000 operations, and iterating through range() takes approximately 2.7 seconds per 100,000 operations.

However, in worst-case situations where very few mobs are obscured by darkness, it appears that viewers() is slower than view() is equivalent to range().
This is actually really quite interesting, it's definitely something to take into consideration when you want to perform larger operations.

I don't suppose you plan on testing the CPU usage of the four to compare them against each other? Speed is all well and good, but when they use up more resources it counterbalances the entire justification.
And some additional test notes here:

My theory about moving bounding boxes being more efficient than checking range() has also been been proven wrong.

It turns out, it's awesome if the large bounding box doesn't move, but suffers around a 50% net performance loss compared to range() if you decide to move it around. This is especially true with larger bounding boxes.


Mask of Illusion wrote:
I don't suppose you plan on testing the CPU usage of the four to compare them against each other? Speed is all well and good, but when they use up more resources it counterbalances the entire justification.

CPU usage would be completely arbitrary. Speed is just a factor of CPU speed operating against the occupancy of a series of instructions. Therefore, CPU usage has already been tested, and can be weighed relatively using my reported times.
In response to Ter13
Ter13 wrote:
CPU usage would be completely arbitrary. Speed is just a factor of CPU speed operating against the occupancy of a series of instructions. Therefore, CPU usage has already been tested, and can be weighed relatively using my reported times.

I'd have to disagree with you here, if for example range() operated a second faster than view() but suffered by increasing the CPU usage by 2. Then running an operation on a much larger scale than what you used to test them could prove significant.

Maybe it's sleep deprivation and something is alluding me, but I've always had the impression that range() uses more CPU than view(). So for more intensive operations it's more practical to use view() because it yields quicker results.
Again, that's just not how computers work.

The "amount of CPU" you are talking about is just occupancy.

Occupancy is determined by how much of the processor's time is spent idle.

Thus, 2% CPU usage means that 2% of the CPU's available time is being utilized to process the load of operations fed to it each cycle the scheduler is tracking.

150% CPU usage means that it is taking 1.5 times the amount of time to complete a cycle than is allotted to a cycle.

Therefore, if a function takes 2% CPU occupancy, and another takes 4% occupancy, the second function will take 100% longer to complete than the first.

The only resource a function can take up, in regards to processing, is time. Therefore, CPU usage percentages will tell us nothing, unless you also list the time taken, and the core speed of the processor used for the measurement.
Now that I take a moment to think about it, that does make much more sense...

Aha, I'm having one of those days. Thanks for taking the time to explain that though!
I've been trying to avoid the use of view() and related functions all together, but this is very informative. Thanks!
I always assumed range() would be faster. Glad to know for sure now.