Legacy Tests - https://github.com/edx/load-tests (internal-only repo)
Current Tests - https://github.com/edx/edx-load-tests
Framework - https://github.com/locustio/locust(used currently in edx-load-tests. We also have a fork, and some legacy JMeter scripts)
Framework - http://www.sitespeed.io/ (Install via npm)
Useful add-in - https://github.com/edx/edx-sitespeed (for logged-in sessions)
Network throttling tools: Network Link Conditioner, tc (ubuntu native), wondersharper (which does not work on virtual machines), etc
PyInstrument can be helpful because of the way it writes output data as a call tree. More info here:
https://github.com/joerick/pyinstrument
from pyinstrument import Profiler profiler = Profiler(use_signal=False) profiler.start() # Do stuff here profiler.stop() # write profile data to file with open('my.log', 'w') as f: f.write(profiler.output_text()) |
Here are the steps to profile your python code with cProfile and then view the results using SnakeViz.
Add the following to the code that you want to profile
@contextmanager def collect_profile(file_prefix): """ Context manager to collect profile information. """ import cProfile import uuid profiler = cProfile.Profile() profiler.enable() try: yield finally: profiler.disable() profiler.dump_stats("{0}_{1}.profile".format(file_prefix, uuid.uuid4())) with collect_profile: <python_code_to_profile> |
OR, if you want to profile an entire function, you can use this decorator:
def collect_profile_func(file_prefix, enabled=False): """ Method decorator for collecting profile. """ import functools def _outer(func): """ Outer function decorator. """ @functools.wraps(func) def _inner(self, *args, **kwargs): """ Inner wrapper function. """ if enabled: with collect_profile(file_prefix): return func(self, *args, **kwargs) else: return func(self, *args, **kwargs) return _inner return _outer @contextmanager def collect_profile(file_prefix): """ Context manager to collect profile information. """ import cProfile import uuid profiler = cProfile.Profile() profiler.enable() try: yield finally: profiler.disable() profiler.dump_stats("{0}_{1}.profile".format(file_prefix, uuid.uuid4())) |
Then use SnakeViz by issuing:
snakeviz DIRECTORY/FILE_NAME.profile
When profiling locally, disable features that would affect performance numbers. For instance, the following can be set in the a local [lms/cms]/envs/private.py file:
from .common import INSTALLED_APPS, MIDDLEWARE_CLASSES, FEATURES def tuple_without(source_tuple, exclusion_list): """Return new tuple excluding any entries in the exclusion list. Needed because tuples are immutable. Order preserved.""" return tuple([i for i in source_tuple if i not in exclusion_list]) INSTALLED_APPS = tuple_without(INSTALLED_APPS, ['debug_toolbar', 'debug_toolbar_mongo']) MIDDLEWARE_CLASSES = tuple_without(MIDDLEWARE_CLASSES, [ 'django_comment_client.utils.QueryCountDebugMiddleware', 'debug_toolbar.middleware.DebugToolbarMiddleware', ]) DEBUG_TOOLBAR_MONGO_STACKTRACES = False import contracts contracts.disable_all() |