summaryrefslogtreecommitdiff
path: root/perfprofd
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2018-07-09 13:33:59 -0700
committerAndreas Gampe <agampe@google.com>2018-07-09 17:35:59 -0700
commitc18c2d0b9dad09c20018a3002f02d343576ac134 (patch)
tree49f4cc904344ee329d867931a49b26c68607cbe0 /perfprofd
parentf854eb868a7682135f36f3a0bf8ed462ef464501 (diff)
downloadextras-c18c2d0b9dad09c20018a3002f02d343576ac134.tar.gz
Perfprofd: Update python script to produce a config proto
Bug: 110555909 Test: mmma system/extras/perfprofd/scripts Test: manual Change-Id: I3cbeb217852fae2eabf4176dafc30e73f6623d30
Diffstat (limited to 'perfprofd')
-rw-r--r--perfprofd/scripts/Android.bp18
-rw-r--r--perfprofd/scripts/perf_config_proto.py213
2 files changed, 172 insertions, 59 deletions
diff --git a/perfprofd/scripts/Android.bp b/perfprofd/scripts/Android.bp
index 1cd755cf..93aed1c8 100644
--- a/perfprofd/scripts/Android.bp
+++ b/perfprofd/scripts/Android.bp
@@ -69,3 +69,21 @@ python_binary_host {
"simpleperf-inferno",
],
}
+
+python_binary_host {
+ name: "perf_config_proto",
+ defaults: ["perfprofd_python_default"],
+ main: "perf_config_proto.py",
+ srcs: [
+ "perf_config_proto.py",
+ ":perfprofd_config_proto",
+ ],
+ libs: [
+ // Soong won't add "libprotobuf-python" to the dependencies if
+ // filegroup contains .proto files. So add it here explicitly.
+ "libprotobuf-python",
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/perfprofd/scripts/perf_config_proto.py b/perfprofd/scripts/perf_config_proto.py
index c94910f8..52614ceb 100644
--- a/perfprofd/scripts/perf_config_proto.py
+++ b/perfprofd/scripts/perf_config_proto.py
@@ -19,77 +19,172 @@
# Generate with:
# aprotoc -I=system/extras/perfprofd --python_out=system/extras/perfprofd/scripts \
# system/extras/perfprofd/binder_interface/perfprofd_config.proto
-import perfprofd_config_pb2
+#
+# Note: it is necessary to do a '*' import to not have to jump through hoops
+# with reflective instantiation.
+from perfprofd_config_pb2 import *
+
+# Necessary for introspection.
+from google.protobuf.descriptor import FieldDescriptor
import sys
-config_options = [
- ('collection_interval_in_s', 'u'),
- ('use_fixed_seed', 'u'),
- ('main_loop_iterations', 'u'),
- ('destination_directory', 's'),
- ('config_directory', 's'),
- ('perf_path', 's'),
- ('sampling_period', 'u'),
- ('sample_duration_in_s', 'u'),
- ('only_debug_build', 'b'),
- ('hardwire_cpus', 'b'),
- ('hardwire_cpus_max_duration_in_s', 'u'),
- ('max_unprocessed_profiles', 'u'),
- ('stack_profile', 'b'),
- ('collect_cpu_utilization', 'b'),
- ('collect_charging_state', 'b'),
- ('collect_booting', 'b'),
- ('collect_camera_active', 'b'),
- ('process', 'i'),
- ('use_elf_symbolizer', 'b'),
- ('send_to_dropbox', 'b'),
-]
+PROTO_FIELD_TYPE_NAMES = {
+ FieldDescriptor.TYPE_DOUBLE: "double",
+ FieldDescriptor.TYPE_FLOAT: "float",
+ FieldDescriptor.TYPE_INT64: "int64",
+ FieldDescriptor.TYPE_UINT64: "uint64",
+ FieldDescriptor.TYPE_INT32: "int32",
+ FieldDescriptor.TYPE_FIXED64: "fixed64",
+ FieldDescriptor.TYPE_FIXED32: "fixed32",
+ FieldDescriptor.TYPE_BOOL: "bool",
+ FieldDescriptor.TYPE_STRING: "string",
+ FieldDescriptor.TYPE_GROUP: "group",
+ FieldDescriptor.TYPE_MESSAGE: "message",
+ FieldDescriptor.TYPE_BYTES: "bytes",
+ FieldDescriptor.TYPE_UINT32: "uint32",
+ FieldDescriptor.TYPE_ENUM: "enum",
+ FieldDescriptor.TYPE_SFIXED32: "sfixed32",
+ FieldDescriptor.TYPE_SFIXED64: "sfixed64",
+ FieldDescriptor.TYPE_SINT32: "sint32",
+ FieldDescriptor.TYPE_SINT64: "sint64",
+}
+def get_type_string(proto_field_type):
+ if proto_field_type in PROTO_FIELD_TYPE_NAMES:
+ return PROTO_FIELD_TYPE_NAMES[proto_field_type]
+ return "unknown type"
-def collect_and_write(filename):
- config = perfprofd_config_pb2.ProfilingConfig()
-
- for (option, option_type) in config_options:
- input = raw_input('%s(%s): ' % (option, option_type))
- if input == '':
- # Skip this argument.
- continue
- elif input == '!':
- # Special-case input, end argument collection.
- break
- # Now do some actual parsing work.
- if option_type == 'u' or option_type == 'i':
- option_val = int(input)
- elif option_type == 'b':
- if input == '1' or input == 't' or input == 'true':
- option_val = True
- elif input == '0' or input == 'f' or input == 'false':
- option_val = False
- else:
- assert False, 'Unknown boolean %s' % input
+def read_message(msg_descriptor, indent):
+ istr = ' ' * indent
+ print('%s%s' % (istr, msg_descriptor.name))
+ # Create an instance
+ instance = globals()[msg_descriptor.name]()
+
+ # Fill fields.
+
+ primitive_fields = [None]
+ message_fields = [None]
+ for field in msg_descriptor.fields:
+ if field.type == FieldDescriptor.TYPE_MESSAGE:
+ message_fields.append(field)
else:
- assert False, 'Unknown type %s' % type
- setattr(config, option, option_val)
+ primitive_fields.append(field)
+
+ def table_loop(fields, field_fn):
+ while True:
+ # Print selection table
+ maxlen = len(str(len(fields) - 1))
+ def pad_index(key):
+ while len(key) < maxlen:
+ key = ' ' + key
+ return key
- f = open(filename, "wb")
- f.write(config.SerializeToString())
- f.close()
+ for i in xrange(1, len(fields)):
+ print('%s%s: %s' % (istr, pad_index(str(i)), fields[i].name))
+ print('%s%s: done' % (istr, pad_index('0')))
+ print('%s%s: end' % (istr, pad_index('!')))
+
+ sel = raw_input('%s ? ' % (istr))
+ if sel == '!':
+ # Special-case input, end argument collection.
+ return False
+
+ try:
+ sel_int = int(sel)
+ if sel_int == 0:
+ return True
+
+ if sel_int > 0 and sel_int < len(fields):
+ field = fields[sel_int]
+ if not field_fn(field):
+ return False
+ else:
+ print('Not a valid input (%d)!' % (sel_int))
+ continue
+ except:
+ print('Not a valid input! (%s, %s)' % (sel, str(sys.exc_info()[0])))
+ continue
+
+# # 1) Non-message-type fields. Assume they are not repeated.
+ if len(primitive_fields) > 1:
+ print('%s(Primitives)' % (istr))
+
+ def primitive_fn(field):
+ input = raw_input('%s -> %s (%s): ' % (istr, field.name, get_type_string(field.type)))
+ if input == '':
+ # Skip this field
+ return True
+ if input == '!':
+ # Special-case input, end argument collection.
+ return False
+
+ # Simplification: assume ints or bools or strings, but not floats
+ if field.type == FieldDescriptor.TYPE_BOOL:
+ input = input.lower()
+ set_val = True if input == 'y' or input == 'true' or input == '1' else False
+ elif field.type == FieldDescriptor.TYPE_STRING:
+ set_val = input
+ else:
+ try:
+ set_val = int(input)
+ except:
+ print('Could not parse input as integer!')
+ return True
+ setattr(instance, field.name, set_val)
+ return True
+
+ if not table_loop(primitive_fields, primitive_fn):
+ return (instance, False)
+
+ # 2) Message-type fields. These may be repeated.
+ if len(message_fields) > 1:
+ print('%s(Nested messages)' % (istr))
+
+ def message_fn(field):
+ sub_msg, cont = read_message(field.message_type, indent + 4)
+ if sub_msg is not None:
+ if field.label == FieldDescriptor.LABEL_REPEATED:
+ # Repeated field, use extend.
+ getattr(instance, field.name).extend([sub_msg])
+ else:
+ # Singular field, copy into.
+ getattr(instance, field.name).CopyFrom(sub_msg)
+ return cont
+
+ if not table_loop(message_fields, message_fn):
+ return (instance, False)
+
+ return (instance, True)
+
+
+def collect_and_write(filename):
+ config, _ = read_message(ProfilingConfig.DESCRIPTOR, 0)
+
+ if config is not None:
+ with open(filename, "wb") as f:
+ f.write(config.SerializeToString())
def read_and_print(filename):
- config = perfprofd_config_pb2.ProfilingConfig()
+ config = ProfilingConfig()
- f = open(filename, "rb")
- config.ParseFromString(f.read())
- f.close()
+ with open(filename, "rb") as f:
+ config.ParseFromString(f.read())
print config
-if sys.argv[1] == 'read':
- read_and_print(sys.argv[2])
-elif sys.argv[1] == 'write':
- collect_and_write(sys.argv[2])
-else:
- print 'Usage: python perf_config_proto.py (read|write) filename'
+def print_usage():
+ print('Usage: python perf_config_proto.py (read|write) filename')
+
+
+if __name__ == "__main__":
+ if len(sys.argv) < 3:
+ print_usage()
+ elif sys.argv[1] == 'read':
+ read_and_print(sys.argv[2])
+ elif sys.argv[1] == 'write':
+ collect_and_write(sys.argv[2])
+ else:
+ print_usage()