Commits

Remi Meier committed 63a8719

stm: expose add_penalty to app-level, add log_statistics.py tool

Comments (0)

Files changed (7)

pypy/module/thread/__init__.py

         'at_commit':              'stm.at_commit',
         'run_commit':             'stm.run_commit',
         'should_commit':          'stm.should_commit',
+        'add_penalty':            'stm.add_penalty',
     }
 
     def __init__(self, space, *args):

pypy/module/thread/stm.py

 def should_commit(space):
     from pypy.rlib import rstm
     rstm.should_commit()
+
+
+def add_penalty(space, w_work_penalty, w_allocation_penalty):
+    if we_are_translated():
+        rstm.add_penalty(space.int_w(w_work_penalty),
+                         space.int_w(w_allocation_penalty))

pypy/tool/log_statistics.py

+#!/usr/bin/python
+
+
+from stmlogparser import parse, EventTypes
+args = None
+
+
+############## STATS ################
+from collections import defaultdict
+from itertools import groupby, ifilter
+
+def file_line_stats(logs):
+    files = defaultdict(lambda : defaultdict(list))
+    for tid, events in logs.items():
+        for time, kind, line_dict in events:
+            if 'file' not in line_dict:
+                continue
+            f_dict = files[line_dict['file']]
+            f_dict[line_dict['line']].append(kind)
+
+    fil = lambda x: True \
+        if not args.file_filter or x[0].count(args.file_filter) \
+        else False
+            
+    for f_name, f_dict in ifilter(fil, files.items()):
+        print "FILE:", f_name
+        lines = sorted(f_dict.keys())
+        for line in lines:
+            kinds = f_dict[line]
+            counts = [(EventTypes.reverse_mapping[f[0]],
+                       len(list(f[1])))
+                       for f in groupby(sorted(kinds))]
+            stats = map(lambda c: "%s: %s" % (c[0][0], c[1]), counts)
+            print "%s:\t%s" % (line, ", ".join(stats))
+        print "====================="
+
+
+
+
+
+
+############## MAIN ################
+
+def main():
+    print "Parse..."
+    logs = parse(args.file)
+    print "Parsed."
+
+    file_line_stats(logs)
+
+
+
+if __name__ == "__main__":
+    import argparse
+
+    parser = argparse.ArgumentParser(
+        description='Print statistics about stm log files')
+    parser.add_argument('file', help='logfile to parse')
+    parser.add_argument('--file-filter', help='filter files')
+
+    args = parser.parse_args()
+
+    main()

pypy/tool/plot_log.py

     print "Parsed."
 
     print "Draw..."
-    axs[0].set_title(args.title)
+    if args.title:
+        axs[0].set_title(args.title)
     plot_logs(logs, axs[0])
     axs[0].set_ylabel("Thread")
     axs[0].set_yticks([r+0.5 for r in range(len(logs))])

pypy/tool/stmlogparser.py

 
 
 
-class EventTypes:
-    INIT_TRANSACTION         = 1
-    MAKE_INEVITABLE          = 2
-    COMMIT_TRANSACTION       = 3
-    ABORT_TRANSACTION        = 4
-    INEVITABLE_INSIDE_ATOMIC = 5
-    INC_ATOMIC               = 6
-    DEC_ATOMIC               = 7
-    DESCRIPTOR_INIT          = 8
-    DESCRIPTOR_DONE          = 9
-    SHOULD_COMMIT            = 10
+def enum(*sequential, **named):
+    enums = dict(zip(sequential, range(len(sequential))), **named)
+    reverse = dict((value, key) for key, value in enums.iteritems())
+    enums['reverse_mapping'] = reverse
+    return type('Enum', (), enums)
+
+EventTypes = enum(
+    'INIT_TRANSACTION',
+    'MAKE_INEVITABLE',
+    'COMMIT_TRANSACTION',
+    'ABORT_TRANSACTION',
+    'INEVITABLE_INSIDE_ATOMIC',
+    'INC_ATOMIC',
+    'DEC_ATOMIC',
+    'DESCRIPTOR_INIT',
+    'DESCRIPTOR_DONE',
+    'SHOULD_COMMIT')

pypy/translator/stm/src_stm/et.c

   // Print complete log information
 #if RPY_STM_CONTENTION_PENALTY == 1
   format = "%s {\"time\":\"%llx\", \"reason\":\"%s\", \"file\":\"%s\", "
-    "\"transactions_scenario_rma\":%d, \"line\":%d, \"td\":%s }\n";
+    "\"transactions_scenario_rma\":%d, \"line\":%d, \"td\":%s, "
+    "\"opcode\":\"%hhx\" }\n";
   if (PYPY_HAVE_DEBUG_PRINTS)
     fprintf(PYPY_DEBUG_FILE, format, PYPY_DEBUG_THREAD_ID,
 	    time, reason, _abort_buf, transactions_scenario_rma, 
-	    line, _abort_buf2);
+	    line, _abort_buf2, co_code->rs_chars.items[last_instr]);
 #else
   format = "%s {\"time\":\"%llx\", \"reason\":\"%s\", \"file\":\"%s\", "
-    "\"line\":%d, \"td\":%s }\n";
+    "\"line\":%d, \"td\":%s, "
+    "\"opcode\":\"%hhx\" }\n";
   if (PYPY_HAVE_DEBUG_PRINTS)
     fprintf(PYPY_DEBUG_FILE, format, PYPY_DEBUG_THREAD_ID,
-	    time, reason, _abort_buf, line, _abort_buf2);
+	    time, reason, _abort_buf, line, _abort_buf2,
+	    co_code->rs_chars.items[last_instr]);
 #endif
 
   PYPY_DEBUG_STOP("stm-log");

pypy/translator/stm/src_stm/rpyintf.c

 {
   struct tx_descriptor *d = thread_descriptor;
 #if RPY_STM_CONTENTION_PENALTY == 1
+  /* Separate penalties, because allocation should add to reads.size()
+     which is not easily possible. Just adding to penalty would
+     create small transactions (penalty>limit && reads<limit/2). */
   d->allocation_penalty += allocation_penalty;
   d->penalty += penalty;
 #else