In [1]:
import copy
from fireplace.exceptions import GameOver
from fireplace.utils import play_full_game
import logging
import random
from fireplace import cards
import pstats

%load_ext snakeviz

cards.db.initialize()
logging.disable(logging.WARNING) #logging.NOTSET


[fireplace.__init__]: Initializing card database
INFO:fireplace:Initializing card database
[fireplace.__init__]: Merged 2253 cards
INFO:fireplace:Merged 2253 cards

In [2]:
def run_game():
    try:
        play_full_game();
    except GameOver:
        pass

In [3]:
%%capture c
random.seed(1857)
%timeit -n100 run_game()

In [4]:
c.stdout.splitlines()[-1]


Out[4]:
'100 loops, best of 3: 113 ms per loop'

In [5]:
%%capture
%%prun -D fireplace.prof
random.seed(1857)
for _ in range(100):
    run_game()

In [6]:
stats_f = 'fireplace.prof'
stats = pstats.Stats(stats_f)
stats.strip_dirs()
stats.dump_stats(stats_f)

In [33]:
import pandas as pd
from io import StringIO

index = pd.MultiIndex.from_tuples(stats.stats.keys())
df = pd.DataFrame(list(stats.stats.values()), index=index)
df.drop(df.columns[[4]], axis=1, inplace=True)
df.columns = ['ncalls', 'nreccalls', 'tottime', 'cumtime']
df.index.rename(['filename', 'lineno', 'function'], inplace=True)
df.sort_values(by='tottime', ascending=False)


Out[33]:
ncalls nreccalls tottime cumtime
filename lineno function
~ 0 <built-in method builtins.getattr> 2624348 3070936 1.60 3.10
entity.py 122 func 740903 741136 1.47 3.28
player.py 111 entities 1388040 1388040 0.72 1.05
utils.py 63 random_draft 200 200 0.62 2.28
card.py 417 events 575005 575005 0.60 3.70
144 events 696958 696958 0.57 0.69
actions.py 82 _broadcast 820564 836956 0.53 5.28
90 broadcast 39396 40159 0.52 6.62
~ 0 <built-in method builtins.any> 1547137 1547603 0.49 0.77
selector.py 70 <listcomp> 22902 22902 0.46 1.02
cardxml.py 183 collectible 500567 500567 0.43 0.55
156 card_class 462108 462108 0.43 0.96
game.py 68 entities 105079 105079 0.42 1.48
enum.py 453 __new__ 719292 719292 0.40 0.40
selector.py 109 value 456459 456459 0.37 1.09
~ 0 <method 'get' of 'dict' objects> 2040465 2040465 0.35 0.35
entity.py 93 _getattr 179829 179829 0.34 0.64
enum.py 209 __call__ 719292 719292 0.32 0.72
managers.py 10 __getitem__ 481890 481890 0.31 0.46
selector.py 145 <listcomp> 8295 8295 0.26 1.41
game.py 217 refresh_auras 19187 19187 0.26 3.88
managers.py 23 get 489028 489028 0.25 0.71
card.py 67 zone 1431097 1431097 0.23 0.23
selector.py 355 <lambda> 590255 590255 0.21 0.29
~ 0 <built-in method builtins.isinstance> 1039507 1039507 0.20 0.34
cardxml.py 176 type 208305 208305 0.19 0.44
actions.py 493 trigger 11873 24280 0.19 6.15
__init__.py 122 <listcomp> 344 344 0.18 0.91
card.py 179 entities 477248 477248 0.17 0.17
506 entities 639386 639386 0.17 0.17
... ... ... ... ... ... ...
actions.py 960 do 9 9 0.00 0.00
copy.py 215 _deepcopy_list 28 28 0.00 0.00
192 _deepcopy_atomic 134 134 0.00 0.00
utils.py 64 <lambda> 108 108 0.00 0.00
actions.py 1117 do 5 5 0.00 0.00
card.py 227 heal 4 4 0.00 0.00
utils.py 94 apply 5 5 0.00 0.00
actions.py 800 do 8 8 0.00 0.00
459 eval 4 4 0.00 0.00
card.py 733 deathrattles 12 12 0.00 0.00
actions.py 1069 get_target_args 4 4 0.00 0.00
random.py 93 seed 1 1 0.00 0.00
actions.py 779 do 4 4 0.00 0.00
random_picker.py 114 clone 4 4 0.00 0.00
lazynum.py 117 <genexpr> 20 20 0.00 0.00
~ 0 <function Random.seed at 0x10427a7b8> 1 1 0.00 0.00
actions.py 1076 do 4 4 0.00 0.00
card.py 251 <listcomp> 2 2 0.00 0.00
actions.py 1106 get_target_args 5 5 0.00 0.00
utils.py 100 <lambda> 18 18 0.00 0.00
55 <genexpr> 13 13 0.00 0.00
actions.py 746 do 1 1 0.00 0.00
player.py 248 fatigue 1 1 0.00 0.00
actions.py 434 do 1 1 0.00 0.00
rules.py 8 <lambda> 7 7 0.00 0.00
actions.py 759 do 1 1 0.00 0.00
neutral_legendary.py 165 <lambda> 4 4 0.00 0.00
actions.py 578 do 1 1 0.00 0.00
~ 0 <method 'disable' of '_lsprof.Profiler' objects> 1 1 0.00 0.00
hunter.py 26 <lambda> 1 1 0.00 0.00

458 rows × 4 columns


In [10]:
pd.options.display.float_format = '{:.2f}'.format
c = 'tottime'
breakdown = (pd.DataFrame(df.groupby(level='filename').sum()[c]  / df[c].sum())
    .sort_values(by=c, ascending=False))
breakdown


Out[10]:
tottime
filename
card.py 0.16
~ 0.15
entity.py 0.13
selector.py 0.10
actions.py 0.10
game.py 0.09
cardxml.py 0.06
player.py 0.05
utils.py 0.04
enum.py 0.04
managers.py 0.04
__init__.py 0.01
targeting.py 0.00
abc.py 0.00
uuid.py 0.00
aura.py 0.00
random.py 0.00
_weakrefset.py 0.00
lazynum.py 0.00
calendar.py 0.00
evaluator.py 0.00
random_picker.py 0.00
copy.py 0.00
<frozen importlib._bootstrap> 0.00
<ipython-input-2-082934741187> 0.00
deck.py 0.00
warrior.py 0.00
<string> 0.00
copyreg.py 0.00
warlock.py 0.00
switch.py 0.00
neutral_epic.py 0.00
mage.py 0.00
rules.py 0.00
neutral_legendary.py 0.00
hunter.py 0.00

In [32]:
from matplotlib import pyplot as plt
plt.style.use('ggplot')
%matplotlib inline

f, ax = plt.subplots(figsize=(10, 10))
breakdown.plot.pie(subplots=True, figsize=(10, 10), ax=ax, autopct='%.1f%%', fontsize=14)
ax.legend().set_visible(False)
plt.ylabel('')


Out[32]:
<matplotlib.text.Text at 0x11ee6e198>

In [45]:
import plotly.plotly as py
import cufflinks as cf
cf.set_config_file(world_readable=True,offline=False)

breakdown['file'] = breakdown.index
breakdown.iplot(kind='pie', labels='file', values='tottime')


Out[45]: