#NEWLINE# def calculate_scenario_stats( self , nth_pctile = 95 , format_numbers = True ) : #NEWLINE# #INDENT# "Compute various statistics from worker job result dicts.\n\n        :param nth_pctile: Use this percentile when calculating the stats\n        :param format_numbers: Should various floating-point numbers be\n        formatted as strings or left full-precision floats\n        :returns: A stats python dict which looks something like:\n            SERIES_STATS = {\n                'min': 1.1,\n                'max': 1.1,\n                'avg': 1.1,\n                'std_dev': 1.1,\n                'median': 1.1,\n            }\n            {\n                'agg_stats': {\n                    'worker_count': 1,\n                    'start': 1.1,\n                    'stop': 1.1,\n                    'req_count': 1,\n                    'retries': 0,\n                    'errors' : 0,\n                    'avg_req_per_sec': 1.1, # req_count / (stop - start)?\n                    'retry_rate': 0.0,\n                    'first_byte_latency': SERIES_STATS,\n                    'last_byte_latency': SERIES_STATS,\n                },\n                'worker_stats': {\n                    1: {  # keys are worker_ids\n                        'start': 1.1,\n                        'stop': 1.1,\n                        'req_count': 1,\n                        'retries': 0,\n                        'retry_rate': 0.0,\n                        'errors': 0,\n                        'avg_req_per_sec': 1.1, # req_count / (stop - start)?\n                        'first_byte_latency': SERIES_STATS,\n                        'last_byte_latency': SERIES_STATS,\n                    },\n                    # ...\n                },\n                'op_stats': {\n                    CREATE_OBJECT: { # keys are CRUD constants: CREATE_OBJECT, READ_OBJECT, etc.\n                        'req_count': 1, # num requests of this CRUD type\n                        'avg_req_per_sec': 1.1, # total_requests / sum(last_byte_latencies)\n                        'first_byte_latency': SERIES_STATS,\n                        'last_byte_latency': SERIES_STATS,\n                        'size_stats': {\n                            'small': { # keys are size_str values\n                                'req_count': 1, # num requests of this type and size\n                                'retries': 0, # num of retries\n                                'avg_req_per_sec': 1.1, # total_requests / sum(last_byte_latencies)\n                                'errors': 0,\n                                'retry_rate': 0.0,\n                                'first_byte_latency': SERIES_STATS,\n                                'last_byte_latency': SERIES_STATS,\n                            },\n                            # ...\n                        },\n                    },\n                    # ...\n                },\n                'size_stats': {\n                    'small': { # keys are size_str values\n                        'req_count': 1, # num requests of this size (for all CRUD types)\n                        'retries': 0, # num of retries\n                        'acutual_request_count': 1, # num requests includes retries\n                        'avg_req_per_sec': 1.1, # total_requests / sum(last_byte_latencies)\n                        'errors': 0,\n                        'retry_rate': 0.0,\n                        'first_byte_latency': SERIES_STATS,\n                        'last_byte_latency': SERIES_STATS,\n                    },\n                    # ...\n                },\n                'time_series': {\n                    'start': 1, # epoch time of first data point\n                    'data': [\n                        1, # number of requests finishing during this second\n                        # ...\n                    ],\n                },\n            }\n        " #NEWLINE# logging . info ( 'Calculating statistics...' ) #NEWLINE# agg_stats = dict ( start = ( 2 ** 32 ) , stop = 0 , req_count = 0 ) #NEWLINE# op_stats = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# for crud_type in [ ssbench . CREATE_OBJECT , ssbench . READ_OBJECT , ssbench . UPDATE_OBJECT , ssbench . DELETE_OBJECT ] : #NEWLINE# #INDENT# op_stats [ crud_type ] = dict ( req_count = 0 , avg_req_per_sec = 0 , size_stats = OrderedDict . fromkeys ( self . scenario . sizes_by_name . keys ( ) ) ) #NEWLINE# #UNINDENT# req_completion_seconds = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# start_time = 0 #NEWLINE# completion_time_max = 0 #NEWLINE# completion_time_min = ( 2 ** 32 ) #NEWLINE# stats = dict ( nth_pctile = nth_pctile , agg_stats = agg_stats , worker_stats = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } , op_stats = op_stats , size_stats = OrderedDict . fromkeys ( self . scenario . sizes_by_name . keys ( ) ) ) #NEWLINE# for results in self . unpacker : #NEWLINE# #INDENT# skipped = 0 #NEWLINE# for result in results : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# res_completed_at = result [ 'completed_at' ] #NEWLINE# res_completion_time = int ( res_completed_at ) #NEWLINE# res_worker_id = result [ 'worker_id' ] #NEWLINE# res_type = result [ 'type' ] #NEWLINE# res_size_str = result [ 'size_str' ] #NEWLINE# #UNINDENT# except KeyError as err : #NEWLINE# #INDENT# logging . info ( 'Skipped result with missing keys (%r): %r' , err , result ) #NEWLINE# skipped += 1 #NEWLINE# continue #NEWLINE# #UNINDENT# try : #NEWLINE# #INDENT# res_exception = result [ 'exception' ] #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# try : #NEWLINE# #INDENT# res_last_byte_latency = result [ 'last_byte_latency' ] #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# logging . info ( 'Skipped result with missing last_byte_latency key: %r' , result ) #NEWLINE# skipped += 1 #NEWLINE# continue #NEWLINE# #UNINDENT# if ( res_completion_time < completion_time_min ) : #NEWLINE# #INDENT# completion_time_min = res_completion_time #NEWLINE# start_time = ( res_completion_time - res_last_byte_latency ) #NEWLINE# #UNINDENT# if ( res_completion_time > completion_time_max ) : #NEWLINE# #INDENT# completion_time_max = res_completion_time #NEWLINE# #UNINDENT# req_completion_seconds [ res_completion_time ] = ( 1 + req_completion_seconds . get ( res_completion_time , 0 ) ) #NEWLINE# result [ 'start' ] = ( res_completed_at - res_last_byte_latency ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# logging . warn ( 'calculate_scenario_stats: exception from worker %d: %s' , res_worker_id , res_exception ) #NEWLINE# try : #NEWLINE# #INDENT# res_traceback = result [ 'traceback' ] #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# logging . warn ( 'traceback missing' ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# logging . info ( res_traceback ) #NEWLINE# #UNINDENT# #UNINDENT# if ( res_worker_id not in stats [ 'worker_stats' ] ) : #NEWLINE# #INDENT# stats [ 'worker_stats' ] [ res_worker_id ] = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# #UNINDENT# self . _add_result_to ( stats [ 'worker_stats' ] [ res_worker_id ] , result ) #NEWLINE# try : #NEWLINE# #INDENT# val = stats [ 'size_stats' ] [ res_size_str ] #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# stats [ 'size_stats' ] [ res_size_str ] = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( not val ) : #NEWLINE# #INDENT# stats [ 'size_stats' ] [ res_size_str ] = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# #UNINDENT# #UNINDENT# self . _add_result_to ( stats [ 'size_stats' ] [ res_size_str ] , result ) #NEWLINE# self . _add_result_to ( agg_stats , result ) #NEWLINE# type_stats = op_stats [ res_type ] #NEWLINE# self . _add_result_to ( type_stats , result ) #NEWLINE# try : #NEWLINE# #INDENT# val = type_stats [ 'size_stats' ] [ res_size_str ] #NEWLINE# #UNINDENT# except KeyError : #NEWLINE# #INDENT# type_stats [ 'size_stats' ] [ res_size_str ] = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( not val ) : #NEWLINE# #INDENT# type_stats [ 'size_stats' ] [ res_size_str ] = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# #UNINDENT# #UNINDENT# self . _add_result_to ( type_stats [ 'size_stats' ] [ res_size_str ] , result ) #NEWLINE# #UNINDENT# if ( skipped > 0 ) : #NEWLINE# #INDENT# logging . warn ( 'Total number of results skipped: %d' , skipped ) #NEWLINE# #UNINDENT# #UNINDENT# agg_stats [ 'worker_count' ] = len ( stats [ 'worker_stats' ] . keys ( ) ) #NEWLINE# self . _compute_req_per_sec ( agg_stats ) #NEWLINE# self . _compute_retry_rate ( agg_stats ) #NEWLINE# self . _compute_latency_stats ( agg_stats , nth_pctile , format_numbers ) #NEWLINE# jobs_per_worker = [ ] #NEWLINE# for worker_stats in stats [ 'worker_stats' ] . values ( ) : #NEWLINE# #INDENT# jobs_per_worker . append ( worker_stats [ 'req_count' ] ) #NEWLINE# self . _compute_req_per_sec ( worker_stats ) #NEWLINE# self . _compute_retry_rate ( worker_stats ) #NEWLINE# self . _compute_latency_stats ( worker_stats , nth_pctile , format_numbers ) #NEWLINE# #UNINDENT# stats [ 'jobs_per_worker_stats' ] = self . _series_stats ( jobs_per_worker , nth_pctile , format_numbers ) #NEWLINE# logging . debug ( ( 'Jobs per worker stats:\n' + pformat ( stats [ 'jobs_per_worker_stats' ] ) ) ) #NEWLINE# for op_stats_dict in op_stats . itervalues ( ) : #NEWLINE# #INDENT# if op_stats_dict [ 'req_count' ] : #NEWLINE# #INDENT# self . _compute_req_per_sec ( op_stats_dict ) #NEWLINE# self . _compute_retry_rate ( op_stats_dict ) #NEWLINE# self . _compute_latency_stats ( op_stats_dict , nth_pctile , format_numbers ) #NEWLINE# for ( size_str , size_stats ) in op_stats_dict [ 'size_stats' ] . iteritems ( ) : #NEWLINE# #INDENT# if size_stats : #NEWLINE# #INDENT# self . _compute_req_per_sec ( size_stats ) #NEWLINE# self . _compute_retry_rate ( size_stats ) #NEWLINE# self . _compute_latency_stats ( size_stats , nth_pctile , format_numbers ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# op_stats_dict [ 'size_stats' ] . pop ( size_str ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# #UNINDENT# for ( size_str , size_stats ) in stats [ 'size_stats' ] . iteritems ( ) : #NEWLINE# #INDENT# if size_stats : #NEWLINE# #INDENT# self . _compute_req_per_sec ( size_stats ) #NEWLINE# self . _compute_retry_rate ( size_stats ) #NEWLINE# self . _compute_latency_stats ( size_stats , nth_pctile , format_numbers ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# stats [ 'size_stats' ] . pop ( size_str ) #NEWLINE# #UNINDENT# #UNINDENT# time_series_data = [ req_completion_seconds . get ( t , 0 ) for t in range ( completion_time_min , ( completion_time_max + 1 ) ) ] #NEWLINE# stats [ 'time_series' ] = dict ( start = completion_time_min , start_time = start_time , stop = completion_time_max , data = time_series_data ) #NEWLINE# return stats