# pip install --user yappi # python -m yappi -o yappi.out -f pstat $(which ansible-playbook) $EARGS -i $INVENTORY $PLAYBOOK # python -m pstats yappi.out #* sort cumulative #* stats 10
$ python -m pstats yappi.out
Welcome to the profile statistics browser.
yappi.out% sort cumulative
yappi.out% stats 10
Thu Jun 15 15:13:33 2017 yappi.out
696168 function calls (711009 primitive calls) in 1.493 seconds
Ordered by: cumulative time
List reduced from 2744 to 10 due to restriction <10>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 1.820 1.820 /var/cache/ansible/ansible.checkout.clean/bin/ansible-playbook:21()
3 0.000 0.000 0.966 0.322 /usr/lib/python2.7/site-packages/pkg_resources/__init__.py:95(_SetuptoolsVersionMixin)
6 0.000 0.000 0.922 0.154 /usr/lib/python2.7/site-packages/pkg_resources/__init__.py:577(IResourceProvider)
1 0.000 0.000 0.911 0.911 /usr/lib64/python2.7/site-packages/yaml/__init__.py:87(safe_load)
1 0.003 0.003 0.911 0.911 /usr/lib64/python2.7/site-packages/yaml/__init__.py:64(load)
2 0.000 0.000 0.908 0.454 /usr/lib64/python2.7/site-packages/yaml/constructor.py:35(SafeLoader.get_single_data)
1 0.000 0.000 0.857 0.857 /usr/lib64/python2.7/site-packages/yaml/composer.py:29(SafeLoader.get_single_node)
1 0.000 0.000 0.857 0.857 /usr/lib64/python2.7/site-packages/yaml/composer.py:50(SafeLoader.compose_document)
1/4010 0.021 0.021 0.857 0.000 /usr/lib64/python2.7/site-packages/yaml/composer.py:63(SafeLoader.compose_node)
1/618 0.010 0.010 0.856 0.001 /usr/lib64/python2.7/site-packages/yaml/composer.py:117(SafeLoader.compose_mapping_node)
== Example outputs ==
http://tannerjc.net/notebooks/ansible+hosts+forks+items+performance.html
== Benchmarking Scripts ==
=== top level script ===
#!/bin/bash
VERSION=$(ansible --version | head -n1 | awk '{print $2}')
PLAYBOOK=ping_benchmark.yml
#PLAYBOOK=file_benchmark.yml
#PLAYBOOK=site.yml
INVENTORY=inventory.py
EARGS="-vvvv -c ssh"
EARGS="-c ssh"
EARGS="-c local"
FORKSTART=9
FORKSTOP=10
FORKINC=1
HOSTSTART=10
HOSTSTOP=100
HOSTINC=10
ITEMSTART=1
ITEMSTOP=10
ITEMINC=1
for HOSTCOUNT in $(seq $HOSTSTART $HOSTINC $HOSTSTOP); do
let "FORK_START=HOSTCOUNT-1"
for FORKCOUNT in $(seq $FORK_START $FORKINC $HOSTCOUNT); do
for ITEMCOUNT in $(seq $ITEMSTART $ITEMINC $ITEMSTOP); do
export MAXHOSTS=$HOSTCOUNT
export MAXITEMS=$ITEMCOUNT
OUTDIR=pstat_data/$VERSION
if [ ! -d $OUTDIR ]; then
mkdir -p $OUTDIR
fi
OUTFILE=$OUTDIR/H${HOSTCOUNT}_F${FORKCOUNT}_I${ITEMCOUNT}.pstat
echo $OUTFILE
python -m yappi -o $OUTFILE -f pstat $(which ansible-playbook) \
--forks=$FORKCOUNT $EARGS -i $INVENTORY $PLAYBOOK
done
done
done
=== inventory script ===
#!/usr/bin/env python
import json
import os
import sys
import uuid
from pprint import pprint
MAXHOSTS = os.environ.get('MAXHOSTS') or 10
if not isinstance(MAXHOSTS, int):
MAXHOSTS = int(MAXHOSTS)
MAXITEMS = os.environ.get('MAXITEMS') or 10
if not isinstance(MAXITEMS, int):
MAXITEMS = int(MAXITEMS)
INV = {}
INV['_meta'] = {'hostvars': {}}
groups = ['all']
hosts = ['x' + str(x) for x in range(0, MAXHOSTS)]
for idx, group in enumerate(groups):
INV[group] = {}
INV[group]['children'] = []
INV[group]['vars'] = {}
INV[group]['hosts'] = [x for x in hosts]
for host in hosts:
INV['_meta']['hostvars'][host] = {}
INV['_meta']['hostvars'][host]['ansible_connection'] = 'local'
INV['_meta']['hostvars'][host]['ansible_ssh_host'] = 'el7host'
INV['_meta']['hostvars'][host]['ansible_ssh_user'] = 'root'
INV['_meta']['hostvars'][host]['ansible_ssh_private_key_file'] = '~/.ssh/id_TEST'
items = [str(x) for x in range(0, MAXITEMS)]
items = ['/opt/test/%s' % host + x for x in items]
items = [x + '/' + str(uuid.uuid4()) for x in items]
INV['_meta']['hostvars'][host]['TESTLIST'] = items
print json.dumps(INV, indent=2)
=== playbook ===
---
# from https://gist.github.com/michelleperz/fe3a0eb4eda888221229730e34b28b89
- hosts: all
gather_facts: no
tasks:
- ping:
with_items: "{{ TESTLIST }}"
=== summary script ===
#!/usr/bin/env python
import json
import operator
import os
import pstats
from pprint import pprint
BASEDIR = 'pstat_data'
records = []
for root, dirs, files in os.walk(BASEDIR):
for x in files:
VERSION = os.path.basename(root)
cfile = x.replace('.pstat', '')
HOSTS = cfile.split('_')[0].replace('H', '')
FORKS = cfile.split('_')[1].replace('F', '')
ITEMS = cfile.split('_')[2].replace('I', '')
filepath = os.path.join(root, x)
ps = pstats.Stats(filepath)
sortby = 'cumulative'
sb = ps.strip_dirs().sort_stats(sortby)
DURATION = sb.total_tt
print('{0} {1:>4} {2:>4} {3:>4} {4:>20}'.format(VERSION, HOSTS, FORKS, ITEMS, DURATION))
record = {
'version': VERSION,
'hosts': int(HOSTS),
'forks': int(FORKS),
'items': int(ITEMS),
'time': DURATION
}
records.append(record)
records.sort(key=operator.itemgetter('time'))
pprint(records[-10:])
with open('durations.json', 'wb') as f:
f.write(json.dumps(records))
import epdb; epdb.st()
== resources ==
* https://bitbucket.org/sumerc/yappi
* http://stefaanlippens.net/python_profiling_with_pstats_interactive_mode/
* https://pymotw.com/2/profile/
* https://github.com/lberruti/ansible-perftest
* https://github.com/ansible/ansible/issues/12239
[[Category:Ansible]]