Форум сайта python.su
0
Добрый вечер.
import os, time
from random import randint
class ob():
def __init__(self, (x,y)):
self.xy = (x,y)
def render(self):
(x, y) = self.xy # some load
x*x # some load
def renderGlobal(self):
(x, y) = self.xy # some load
x*x # some load
if __name__ == '__main__':
npc_list = []
i = 0
while i < 1000:
npc = ob((randint(1,100), randint(1,100)))
npc_list.append(npc)
i += 1
obr = ob.render
for case in [0,1,2,3]:
if case == 0:
t = time.time()
print "case 0: classic FOR loop"
for n in npc_list:
n.render()
print "Time taken:", time.time() - t
if case == 1:
t = time.time()
print "case 1: loop using map()"
map(renderGlobal, npc_list)
print "Time taken:", time.time() - t
if case == 2:
t = time.time()
print "case 2: loop using map()"
map(ob.render, npc_list)
print "Time taken:", time.time() - t
if case == 3:
t = time.time()
print "case 3: loop using map()"
map(obr, npc_list)
print "Time taken:", time.time() - t
case 0: classic FOR loop
Time taken: 0.000545978546143
case 1: loop using map()
Time taken: 0.000361204147339
case 2: loop using map()
Time taken: 0.00108885765076
case 3: loop using map()
Time taken: 0.00101208686829
Отредактировано (Янв. 23, 2011 20:15:47)
Офлайн
14
1. Измеряйте дольше, в несколько итераций. Лучше, если получающиеся времена ближе к секундам, чем к миллисекундам.
2. map возвращает список значений - подумайте над этим.
3. Делайте профилирование вашего _реального_ кода - этот пример всего лишь показывает, что все варианты примерно равноценны, не стоит заморачиваться.
Усложните .render и увидите, где настоящие проблемы.
Офлайн
0
Андрей Светлов. спасибо за ответ.
Андрей Светловсо всем согласен, не учёл этого.
1. Измеряйте дольше, в несколько итераций. Лучше, если получающиеся времена ближе к секундам, чем к миллисекундам
case 0: classic FOR loop
Time taken: 0.513402938843
case 1: loop using map()
Time taken: 0.385162115097
case 2: loop using map()
Time taken: 1.02443599701
case 3: loop using map()
Time taken: 1.02541089058
Андрей Светловя этого изначально не учёл, спасибо. однако всёравно с учётом этого непонятен феноменальный отрыв case 1 по отношению к case 2,3. везде в этих case используется map.
2. map возвращает список значений - подумайте над этим.
Андрей СветловТак и сделаю, часто встречал такую рекомендацию и я её разделяю. Однако человек я такой, иногда клинит на мелочах, хочется понять хоть это и не несет особой смысловой нагрузки, просто интересно. Циклы используются очень часто, даже если с каждого получу мизерный выигрышь, буду этому безмерно рад, думаю лишним не будет.
3. Делайте профилирование вашего _реального_ кода - этот пример всего лишь показывает, что все варианты примерно равноценны, не стоит заморачиваться.
Усложните .render и увидите, где настоящие проблемы.
Отредактировано (Янв. 23, 2011 21:05:00)
Офлайн
14
Вызов unbound method непомерно дорогой. bound method - хорошая оптимизация, а unbound - как видим, дорогая.
Не зря его выкинули, на 3.1 картина ровная и ожидаемая.
import os, time
from random import randint
class ob():
def __init__(self, (x,y)):
self.xy = (x,y)
def render(self):
(x, y) = self.xy # some load
x*x # some load
def renderGlobal(self):
(x, y) = self.xy # some load
x*x # some load
def check():
npc_list = [ob((randint(1,100), randint(1,100))) for i in xrange(1000)]
COUNT = 1000
obr = ob.render
t = time.time()
print "case 0: classic FOR loop"
for i in xrange(COUNT):
for n in npc_list:
n.render()
print "Time taken:", time.time() - t
t = time.time()
print "case 1: loop using map()"
for i in xrange(COUNT):
map(renderGlobal, npc_list)
print "Time taken:", time.time() - t
t = time.time()
print "case 2: loop using map()"
for i in xrange(COUNT):
map(ob.render, npc_list)
print "Time taken:", time.time() - t
t = time.time()
print "case 3: loop using map()"
for i in xrange(COUNT):
map(obr, npc_list)
print "Time taken:", time.time() - t
t = time.time()
print "case 4: loop with global function"
for i in xrange(COUNT):
for n in npc_list:
renderGlobal(n)
print "Time taken:", time.time() - t
t = time.time()
print "case 5: loop with global function stored in local var"
rg = renderGlobal
for i in xrange(COUNT):
for n in npc_list:
rg(n)
print "Time taken:", time.time() - t
t = time.time()
print "case 6: loop with unbound method"
for i in xrange(COUNT):
for n in npc_list:
obr(n)
print "Time taken:", time.time() - t
if __name__ == '__main__':
check()
import dis
# dis.dis(check)
Офлайн
7
Андрей СветловВ 3.1 возвращается <map object>, по сути - итератор (или, точнее, генератор). Как, и range(…), например (то есть не список).
2. map возвращает список значений - подумайте над этим.
Отредактировано (Янв. 24, 2011 06:20:41)
Офлайн
0
Всем спасибо за советы и поправки, оставлюка я и правда всю оптимизацию на потом., если в таковой буду нуждаться.
Отредактировано (Янв. 25, 2011 20:31:10)
Офлайн