Reputation: 155
I have the example code below. I have a Test
object which counts to ten, and then is ready to be destroyed. I have a class which is an wrapper for an array of these objects. This class uses the update
method every frame, and iterates through the array of Test
objects and update every one. If the current object has reached the maximum count, the reference to the object is removed, and when the iteration is finished, the array becomes compact.
require 'benchmark'
class Test
def update
@counter ||= 0
@counter += 1
end
def destroy?
@counter > 10
end
def dispose
# dispose this object
end
end
class Tests
def initialize(number)
@data = []
number.times do
@data.push(Test.new)
end
end
def add_data(data)
@data.push(data)
end
def update
@data.each_with_index do |t, index|
t.update
if t.destroy?
t.dispose # need to dispose the sprite object in my realcode before delete ref.
@data[index] = nil
end
end.compact!
end
# this would be another attempt, which is a little bit faster
# but this wont work because in my case the objects I use are
# sprite objects which needs to be disposed like shown above
# before the reference is removed
def update_2
@data.each(&:update)
@data.delete_if{|obj| obj.destroy?}
end
end
iterations = 2000000
Benchmark.bm do |x|
x.report {Tests.new(iterations).update}
x.report {Tests.new(iterations).update_2}
end
One problem is that this turns out to be performance heavy if many objects are added. Another problem is that, every frame, another object can be added through the add_data
method. I wondering if there could be another approach for all this, to make this be not so heavy to the performance.
edit I use a custom library(http://rmvxace.wikia.com/wiki/RGSS), therefore I edited my code above to make some more things clear. But the main problem stays the update method.
Upvotes: 0
Views: 138
Reputation: 19221
I can see a few performance issues with the code, although others may do better.
Here's what I think:
Also, your benchmarks always create an object and update it one time - this is not the best base for comparison.
for instance, your update_2 is actually much slower over time... which you aren't noticing at all with your benchmarks.
I updated your update_2 method and added an update_3 method which was a bit faster with the new benchmarks.
the update_3 method required an adjustment to the Test class, which now has a new method called update_or_destroy and returns true for update and false for destroy.
I also added an initializer method to reduce the lazy initialization effect (during my testing it showed to be an effective way to reduce the workload).
try this:
require 'benchmark'
class Test
def initialize
@counter ||= 0
end
def update
@counter += 1
end
def destroy?
@counter > 10
end
def dispose
# dispose this object
end
def update_or_destroy
update
if destroy?
dispose
false
else
true
end
end
end
class Tests
def initialize(number)
@data = []
number.times do
@data.push(Test.new)
end
end
def add_data(data)
@data.push(data)
end
def update
@data.each_with_index do |t, index|
t.update
if t.destroy?
t.dispose # need to dispose the sprite object in my realcode before delete ref.
@data[index] = nil
end
end.compact!
end
# this would be another attempt, which is a little bit faster
# but this wont work because in my case the objects I use are
# sprite objects which needs to be disposed like shown above
# before the reference is removed
def update_2_updated
# @data.each(&:update)
@data.delete_if{|obj| obj.update; obj.destroy?}
end
def update_3
@data.keep_if {|obj| obj.update_or_destroy}
end
end
iterations = 2000000
Benchmark.bm do |x|
x.report {Tests.new(iterations).update}
x.report {Tests.new(iterations).update_2_updated}
x.report {Tests.new(iterations).update_3}
end
#new benchmarks
iterations = 100000
test_object = Tests.new(iterations)
puts Benchmark.measure { iterations.times { test_object.update } }
test_object = Tests.new(iterations)
puts Benchmark.measure { iterations.times { test_object.update_2_updated } }
test_object = Tests.new(iterations)
puts Benchmark.measure { iterations.times { test_object.update_3 } }
Upvotes: 1