nitc: add memory_logger.nit
authorJean Privat <jean@pryen.org>
Fri, 24 Jun 2016 02:28:25 +0000 (22:28 -0400)
committerJean Privat <jean@pryen.org>
Fri, 24 Jun 2016 02:28:25 +0000 (22:28 -0400)
Signed-off-by: Jean Privat <jean@pryen.org>

src/compiler/compiler.nit
src/compiler/memory_logger.nit [new file with mode: 0644]

index c013295..3c0ab59 100644 (file)
@@ -18,6 +18,7 @@ module compiler
 import separate_erasure_compiler
 import global_compiler
 import compiler_ffi
+import memory_logger
 
 import platform::android
 import platform::pnacl
diff --git a/src/compiler/memory_logger.nit b/src/compiler/memory_logger.nit
new file mode 100644 (file)
index 0000000..1f96451
--- /dev/null
@@ -0,0 +1,76 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Extension to inject memory-tracing instrumentation in code generated by `nitc`.
+module memory_logger
+
+import abstract_compiler
+
+redef class ToolContext
+       # --trace-memory
+       var opt_trace_memory = new OptionBool("Enable dynamic measure of memory usage", "--trace-memory")
+
+       init do
+               self.option_context.add_option opt_trace_memory
+       end
+end
+
+redef class AbstractCompiler
+       redef fun compile_before_main(v)
+       do
+               super
+
+               if not modelbuilder.toolcontext.opt_trace_memory.value then return
+
+               header.add_decl("#include <time.h>")
+               header.add_decl("extern FILE *mlog;")
+               header.add_decl("extern struct timespec mlog_last;")
+               header.add_decl("extern struct timespec mlog_time0;")
+               v.add_decl("FILE *mlog;")
+               v.add_decl("struct timespec mlog_last;")
+               v.add_decl("struct timespec mlog_time0;")
+       end
+
+       redef fun compile_begin_main(v)
+       do
+               super
+
+               if not modelbuilder.toolcontext.opt_trace_memory.value then return
+
+               v.add("mlog = fopen(\"memory.log\", \"w\");")
+               v.add("clock_gettime(CLOCK_MONOTONIC, &mlog_time0);")
+       end
+end
+
+redef class AbstractCompilerVisitor
+       redef fun nit_alloc(size, tag)
+       do
+               if not compiler.modelbuilder.toolcontext.opt_trace_memory.value then return super
+
+               # Log time each 10ms (ie 1e7ns)
+               var tw = get_name("mtw")
+               add_decl("struct timespec {tw};")
+               add("clock_gettime(CLOCK_MONOTONIC, &{tw});")
+               add("if(mlog_last.tv_sec < {tw}.tv_sec || mlog_last.tv_nsec + 1e7 < {tw}.tv_nsec) \{")
+               add("mlog_last = {tw};")
+               add("fprintf(mlog, \"# %f\\n\", 1000.0*{tw}.tv_sec + 1e-6*{tw}.tv_nsec - (1000.0*mlog_time0.tv_sec + 1e-6*mlog_time0.tv_nsec));")
+               add("\}")
+
+               # Print size and tag the mlog
+               var str = "\"+\\t%d\\t%s\\n\", {size}, \"{tag or else "?"}\""
+               add("fprintf(mlog, {str});")
+
+               return super
+       end
+end