summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py/emitglue.c6
-rw-r--r--py/misc.h2
-rw-r--r--py/mpconfig.h33
-rw-r--r--py/parse.c12
-rwxr-xr-xpy/py-version.sh3
-rw-r--r--py/scope.c6
-rw-r--r--py/showbc.c2
-rw-r--r--tests/bench/bench.py10
-rw-r--r--tests/bench/loop_count-1-range.py7
-rw-r--r--tests/bench/loop_count-2-range_iter.py7
-rw-r--r--tests/bench/loop_count-3-while_up.py8
-rw-r--r--tests/bench/loop_count-4-while_down_gt.py7
-rw-r--r--tests/bench/loop_count-5-while_down_ne.py7
-rw-r--r--tests/bench/var-1-constant.py8
-rw-r--r--tests/bench/var-2-global.py10
-rw-r--r--tests/bench/var-3-local.py10
-rw-r--r--tests/bench/var-4-arg.py9
-rw-r--r--tests/bench/var-5-class-attr.py11
-rw-r--r--tests/bench/var-6-instance-attr.py14
-rw-r--r--tests/bench/var-7-instance-meth.py17
-rwxr-xr-xtests/run-bench-tests97
-rw-r--r--unix/main.c7
22 files changed, 279 insertions, 14 deletions
diff --git a/py/emitglue.c b/py/emitglue.c
index 231e32ac2..ed3b385d9 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -96,9 +96,11 @@ void mp_emit_glue_assign_byte_code(mp_raw_code_t *rc, byte *code, uint len, uint
DEBUG_printf(" %02x", code[i]);
}
DEBUG_printf("\n");
-#if MICROPY_DEBUG_PRINTERS
- mp_byte_code_print(code, len);
#endif
+#if MICROPY_DEBUG_PRINTERS
+ if (mp_verbose_flag > 0) {
+ mp_byte_code_print(code, len);
+ }
#endif
}
diff --git a/py/misc.h b/py/misc.h
index 0c8161d10..5eb662409 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -156,4 +156,6 @@ void vstr_vprintf(vstr_t *vstr, const char *fmt, va_list ap);
// Debugging helpers
int DEBUG_printf(const char *fmt, ...);
+extern uint mp_verbose_flag;
+
#endif // _INCLUDED_MINILIB_H
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 78147609c..435140dc7 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -34,6 +34,39 @@
// values below.
/*****************************************************************************/
+/* Memory allocation policy */
+
+// Initial amount for parse rule stack
+#ifndef MP_ALLOC_PARSE_RULE_INIT
+#define MP_ALLOC_PARSE_RULE_INIT (64)
+#endif
+
+// Increment for parse rule stack
+#ifndef MP_ALLOC_PARSE_RULE_INC
+#define MP_ALLOC_PARSE_RULE_INC (16)
+#endif
+
+// Initial amount for parse result stack
+#ifndef MP_ALLOC_PARSE_RESULT_INIT
+#define MP_ALLOC_PARSE_RESULT_INIT (32)
+#endif
+
+// Increment for parse result stack
+#ifndef MP_ALLOC_PARSE_RESULT_INC
+#define MP_ALLOC_PARSE_RESULT_INC (16)
+#endif
+
+// Initial amount for ids in a scope
+#ifndef MP_ALLOC_SCOPE_ID_INIT
+#define MP_ALLOC_SCOPE_ID_INIT (4)
+#endif
+
+// Increment for ids in a scope
+#ifndef MP_ALLOC_SCOPE_ID_INC
+#define MP_ALLOC_SCOPE_ID_INC (6)
+#endif
+
+/*****************************************************************************/
/* Micro Python emitters */
// Whether to emit CPython byte codes (for debugging/testing)
diff --git a/py/parse.c b/py/parse.c
index 13b137fb3..f512eea3b 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -134,13 +134,13 @@ STATIC void push_rule(parser_t *parser, int src_line, const rule_t *rule, int ar
return;
}
if (parser->rule_stack_top >= parser->rule_stack_alloc) {
- rule_stack_t *rs = m_renew_maybe(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc * 2);
+ rule_stack_t *rs = m_renew_maybe(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MP_ALLOC_PARSE_RULE_INC);
if (rs == NULL) {
memory_error(parser);
return;
}
parser->rule_stack = rs;
- parser->rule_stack_alloc *= 2;
+ parser->rule_stack_alloc += MP_ALLOC_PARSE_RULE_INC;
}
rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];
rs->src_line = src_line;
@@ -263,13 +263,13 @@ STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
return;
}
if (parser->result_stack_top >= parser->result_stack_alloc) {
- mp_parse_node_t *pn = m_renew_maybe(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc * 2);
+ mp_parse_node_t *pn = m_renew_maybe(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MP_ALLOC_PARSE_RESULT_INC);
if (pn == NULL) {
memory_error(parser);
return;
}
parser->result_stack = pn;
- parser->result_stack_alloc *= 2;
+ parser->result_stack_alloc += MP_ALLOC_PARSE_RESULT_INC;
}
parser->result_stack[parser->result_stack_top++] = pn;
}
@@ -350,11 +350,11 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
parser->had_memory_error = false;
- parser->rule_stack_alloc = 64;
+ parser->rule_stack_alloc = MP_ALLOC_PARSE_RULE_INIT;
parser->rule_stack_top = 0;
parser->rule_stack = m_new(rule_stack_t, parser->rule_stack_alloc);
- parser->result_stack_alloc = 64;
+ parser->result_stack_alloc = MP_ALLOC_PARSE_RESULT_INIT;
parser->result_stack_top = 0;
parser->result_stack = m_new(mp_parse_node_t, parser->result_stack_alloc);
diff --git a/py/py-version.sh b/py/py-version.sh
index 42474ef6a..daa25489e 100755
--- a/py/py-version.sh
+++ b/py/py-version.sh
@@ -1,6 +1,7 @@
#!/bin/bash
-git_tag="$(git describe --dirty || echo unknown)"
+# Note: git describe doesn't work if no tag is available
+git_tag="$(git describe --dirty 2> /dev/null || git rev-parse --short HEAD)"
git_hash="$(git rev-parse --short HEAD 2> /dev/null || echo unknown)"
git_files_are_clean=1
# Check if there are any modified files.
diff --git a/py/scope.c b/py/scope.c
index 8d3f7bada..ab29af78a 100644
--- a/py/scope.c
+++ b/py/scope.c
@@ -71,7 +71,7 @@ scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, uint
}
scope->raw_code = mp_emit_glue_new_raw_code();
scope->emit_options = emit_options;
- scope->id_info_alloc = 8;
+ scope->id_info_alloc = MP_ALLOC_SCOPE_ID_INIT;
scope->id_info = m_new(id_info_t, scope->id_info_alloc);
return scope;
@@ -92,8 +92,8 @@ id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added) {
// make sure we have enough memory
if (scope->id_info_len >= scope->id_info_alloc) {
- scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc * 2);
- scope->id_info_alloc *= 2;
+ scope->id_info = m_renew(id_info_t, scope->id_info, scope->id_info_alloc, scope->id_info_alloc + MP_ALLOC_SCOPE_ID_INC);
+ scope->id_info_alloc += MP_ALLOC_SCOPE_ID_INC;
}
// add new id to end of array of all ids; this seems to match CPython
diff --git a/py/showbc.c b/py/showbc.c
index ccb703f26..d8ab4be07 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -89,7 +89,7 @@ void mp_byte_code_print(const byte *ip, int len) {
{
qstr source_file = code_info[4] | (code_info[5] << 8) | (code_info[6] << 16) | (code_info[7] << 24);
qstr block_name = code_info[8] | (code_info[9] << 8) | (code_info[10] << 16) | (code_info[11] << 24);
- printf("File %s, block %s\n", qstr_str(source_file), qstr_str(block_name));
+ printf("File %s, block '%s'\n", qstr_str(source_file), qstr_str(block_name));
machine_int_t bc = (code_info + code_info_size) - ip;
machine_uint_t source_line = 1;
printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
diff --git a/tests/bench/bench.py b/tests/bench/bench.py
new file mode 100644
index 000000000..0cd40a93f
--- /dev/null
+++ b/tests/bench/bench.py
@@ -0,0 +1,10 @@
+import time
+
+
+ITERS = 20000000
+
+def run(f):
+ t = time.time()
+ f(ITERS)
+ t = time.time() - t
+ print(t)
diff --git a/tests/bench/loop_count-1-range.py b/tests/bench/loop_count-1-range.py
new file mode 100644
index 000000000..e22adf6cb
--- /dev/null
+++ b/tests/bench/loop_count-1-range.py
@@ -0,0 +1,7 @@
+import bench
+
+def test(num):
+ for i in range(num):
+ pass
+
+bench.run(test)
diff --git a/tests/bench/loop_count-2-range_iter.py b/tests/bench/loop_count-2-range_iter.py
new file mode 100644
index 000000000..fe4a3857e
--- /dev/null
+++ b/tests/bench/loop_count-2-range_iter.py
@@ -0,0 +1,7 @@
+import bench
+
+def test(num):
+ for i in iter(range(num)):
+ pass
+
+bench.run(test)
diff --git a/tests/bench/loop_count-3-while_up.py b/tests/bench/loop_count-3-while_up.py
new file mode 100644
index 000000000..1ab8054a0
--- /dev/null
+++ b/tests/bench/loop_count-3-while_up.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ i = 0
+ while i < num:
+ i += 1
+
+bench.run(test)
diff --git a/tests/bench/loop_count-4-while_down_gt.py b/tests/bench/loop_count-4-while_down_gt.py
new file mode 100644
index 000000000..de8dee2ca
--- /dev/null
+++ b/tests/bench/loop_count-4-while_down_gt.py
@@ -0,0 +1,7 @@
+import bench
+
+def test(num):
+ while num > 0:
+ num -= 1
+
+bench.run(test)
diff --git a/tests/bench/loop_count-5-while_down_ne.py b/tests/bench/loop_count-5-while_down_ne.py
new file mode 100644
index 000000000..b9a1af414
--- /dev/null
+++ b/tests/bench/loop_count-5-while_down_ne.py
@@ -0,0 +1,7 @@
+import bench
+
+def test(num):
+ while num != 0:
+ num -= 1
+
+bench.run(test)
diff --git a/tests/bench/var-1-constant.py b/tests/bench/var-1-constant.py
new file mode 100644
index 000000000..eec977909
--- /dev/null
+++ b/tests/bench/var-1-constant.py
@@ -0,0 +1,8 @@
+import bench
+
+def test(num):
+ i = 0
+ while i < 20000000:
+ i += 1
+
+bench.run(test)
diff --git a/tests/bench/var-2-global.py b/tests/bench/var-2-global.py
new file mode 100644
index 000000000..5758ad61a
--- /dev/null
+++ b/tests/bench/var-2-global.py
@@ -0,0 +1,10 @@
+import bench
+
+ITERS = 20000000
+
+def test(num):
+ i = 0
+ while i < ITERS:
+ i += 1
+
+bench.run(test)
diff --git a/tests/bench/var-3-local.py b/tests/bench/var-3-local.py
new file mode 100644
index 000000000..124b48429
--- /dev/null
+++ b/tests/bench/var-3-local.py
@@ -0,0 +1,10 @@
+import bench
+
+
+def test(num):
+ ITERS = 20000000
+ i = 0
+ while i < ITERS:
+ i += 1
+
+bench.run(test)
diff --git a/tests/bench/var-4-arg.py b/tests/bench/var-4-arg.py
new file mode 100644
index 000000000..cf050c58f
--- /dev/null
+++ b/tests/bench/var-4-arg.py
@@ -0,0 +1,9 @@
+import bench
+
+
+def test(num):
+ i = 0
+ while i < num:
+ i += 1
+
+bench.run(lambda n:test(20000000))
diff --git a/tests/bench/var-5-class-attr.py b/tests/bench/var-5-class-attr.py
new file mode 100644
index 000000000..02ae874ac
--- /dev/null
+++ b/tests/bench/var-5-class-attr.py
@@ -0,0 +1,11 @@
+import bench
+
+class Foo:
+ num = 20000000
+
+def test(num):
+ i = 0
+ while i < Foo.num:
+ i += 1
+
+bench.run(test)
diff --git a/tests/bench/var-6-instance-attr.py b/tests/bench/var-6-instance-attr.py
new file mode 100644
index 000000000..787ed870f
--- /dev/null
+++ b/tests/bench/var-6-instance-attr.py
@@ -0,0 +1,14 @@
+import bench
+
+class Foo:
+
+ def __init__(self):
+ self.num = 20000000
+
+def test(num):
+ o = Foo()
+ i = 0
+ while i < o.num:
+ i += 1
+
+bench.run(test)
diff --git a/tests/bench/var-7-instance-meth.py b/tests/bench/var-7-instance-meth.py
new file mode 100644
index 000000000..f9d463f40
--- /dev/null
+++ b/tests/bench/var-7-instance-meth.py
@@ -0,0 +1,17 @@
+import bench
+
+class Foo:
+
+ def __init__(self):
+ self._num = 20000000
+
+ def num(self):
+ return self._num
+
+def test(num):
+ o = Foo()
+ i = 0
+ while i < o.num():
+ i += 1
+
+bench.run(test)
diff --git a/tests/run-bench-tests b/tests/run-bench-tests
new file mode 100755
index 000000000..59074bb87
--- /dev/null
+++ b/tests/run-bench-tests
@@ -0,0 +1,97 @@
+#! /usr/bin/env python3
+
+import os
+import subprocess
+import sys
+import argparse
+import re
+from glob import glob
+from collections import defaultdict
+
+# Tests require at least CPython 3.3. If your default python3 executable
+# is of lower version, you can point MICROPY_CPYTHON3 environment var
+# to the correct executable.
+if os.name == 'nt':
+ CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe')
+ MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../windows/micropython.exe')
+else:
+ CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3')
+ MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../unix/micropython')
+
+def run_tests(pyb, test_dict):
+ test_count = 0
+ testcase_count = 0
+
+ for base_test, tests in test_dict.items():
+ print(base_test + ":")
+ for test_file in tests:
+
+ # run Micro Python
+ if pyb is None:
+ # run on PC
+ try:
+ output_mupy = subprocess.check_output([MICROPYTHON, '-X', 'emit=bytecode', test_file[0]])
+ except subprocess.CalledProcessError:
+ output_mupy = b'CRASH'
+ else:
+ # run on pyboard
+ pyb.enter_raw_repl()
+ try:
+ output_mupy = pyb.execfile(test_file).replace(b'\r\n', b'\n')
+ except pyboard.PyboardError:
+ output_mupy = b'CRASH'
+
+ output_mupy = float(output_mupy.strip())
+ test_file[1] = output_mupy
+ testcase_count += 1
+
+ test_count += 1
+ baseline = None
+ for t in tests:
+ if baseline is None:
+ baseline = t[1]
+ print(" %.3fs (%+06.2f%%) %s" % (t[1], (t[1] * 100 / baseline) - 100, t[0]))
+
+ print("{} tests performed ({} individual testcases)".format(test_count, testcase_count))
+
+ # all tests succeeded
+ return True
+
+def main():
+ cmd_parser = argparse.ArgumentParser(description='Run tests for Micro Python.')
+ cmd_parser.add_argument('--pyboard', action='store_true', help='run the tests on the pyboard')
+ cmd_parser.add_argument('files', nargs='*', help='input test files')
+ args = cmd_parser.parse_args()
+
+ # Note pyboard support is copied over from run-tests, not testes, and likely needs revamping
+ if args.pyboard:
+ import pyboard
+ pyb = pyboard.Pyboard('/dev/ttyACM0')
+ pyb.enter_raw_repl()
+ else:
+ pyb = None
+
+ if len(args.files) == 0:
+ if pyb is None:
+ # run PC tests
+ test_dirs = ('bench',)
+ else:
+ # run pyboard tests
+ test_dirs = ('basics', 'float', 'pyb')
+ tests = sorted(test_file for test_files in (glob('{}/*.py'.format(dir)) for dir in test_dirs) for test_file in test_files)
+ else:
+ # tests explicitly given
+ tests = sorted(args.files)
+
+ test_dict = defaultdict(lambda: [])
+ for t in tests:
+ m = re.match(r"(.+?)-(.+)\.py", t)
+ if not m:
+ continue
+ test_dict[m.group(1)].append([t, None])
+
+ if not run_tests(pyb, test_dict):
+ sys.exit(1)
+
+if __name__ == "__main__":
+ main()
diff --git a/unix/main.c b/unix/main.c
index d66a68d78..a7e4a907e 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -58,6 +58,7 @@
// Command line options, with their defaults
bool compile_only = false;
uint emit_opt = MP_EMIT_OPT_NONE;
+uint mp_verbose_flag;
#if MICROPY_ENABLE_GC
// Heap size of GC heap (if enabled)
@@ -205,7 +206,9 @@ STATIC void do_str(const char *str) {
int usage(char **argv) {
printf(
-"usage: %s [-X <opt>] [-c <command>] [<filename>]\n"
+"usage: %s [<opts>] [-X <implopt>] [-c <command>] [<filename>]\n"
+"Options:\n"
+"-v : verbose (trace various operations); can be multiple\n"
"\n"
"Implementation specific options:\n", argv[0]
);
@@ -371,6 +374,8 @@ int main(int argc, char **argv) {
a += 1;
} else if (strcmp(argv[a], "-X") == 0) {
a += 1;
+ } else if (strcmp(argv[a], "-v") == 0) {
+ mp_verbose_flag++;
} else {
return usage(argv);
}