bpo-31574: importlib dtrace (#3749)

Importlib was instrumented with two dtrace probes to profile import timing.

Signed-off-by: Christian Heimes <christian@python.org>
diff --git a/Doc/howto/instrumentation.rst b/Doc/howto/instrumentation.rst
index 7fca9aa..2ac939c 100644
--- a/Doc/howto/instrumentation.rst
+++ b/Doc/howto/instrumentation.rst
@@ -312,6 +312,17 @@
    Fires when the Python interpreter finishes a garbage collection
    cycle. ``arg0`` is the number of collected objects.
 
+.. c:function:: import__find__load__start(str modulename)
+
+   Fires before :mod:`importlib` attempts to find and load the module.
+   ``arg0`` is the module name.
+
+.. c:function:: import__find__load__done(str modulename, int found)
+
+   Fires after :mod:`importlib`'s find_and_load function is called.
+   ``arg0`` is the module name, ``arg1`` indicates if module was
+   successfully loaded.
+
 
 SystemTap Tapsets
 -----------------
diff --git a/Include/pydtrace.d b/Include/pydtrace.d
index 8836055..a6a5e7e 100644
--- a/Include/pydtrace.d
+++ b/Include/pydtrace.d
@@ -10,6 +10,8 @@
     probe line(const char *, const char *, int);
     probe gc__start(int);
     probe gc__done(long);
+    probe import__find__load__start(const char *);
+    probe import__find__load__done(const char *, int);
 };
 
 #pragma D attributes Evolving/Evolving/Common provider python provider
diff --git a/Include/pydtrace.h b/Include/pydtrace.h
index c43a253..037961d 100644
--- a/Include/pydtrace.h
+++ b/Include/pydtrace.h
@@ -34,6 +34,8 @@
 static inline void PyDTrace_INSTANCE_NEW_DONE(int arg0) {}
 static inline void PyDTrace_INSTANCE_DELETE_START(int arg0) {}
 static inline void PyDTrace_INSTANCE_DELETE_DONE(int arg0) {}
+static inline void PyDTrace_IMPORT_FIND_LOAD_START(const char *arg0) {}
+static inline void PyDTrace_IMPORT_FIND_LOAD_DONE(const char *arg0, int arg1) {}
 
 static inline int PyDTrace_LINE_ENABLED(void) { return 0; }
 static inline int PyDTrace_FUNCTION_ENTRY_ENABLED(void) { return 0; }
@@ -44,6 +46,8 @@
 static inline int PyDTrace_INSTANCE_NEW_DONE_ENABLED(void) { return 0; }
 static inline int PyDTrace_INSTANCE_DELETE_START_ENABLED(void) { return 0; }
 static inline int PyDTrace_INSTANCE_DELETE_DONE_ENABLED(void) { return 0; }
+static inline int PyDTrace_IMPORT_FIND_LOAD_START_ENABLED(void) { return 0; }
+static inline int PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED(void) { return 0; }
 
 #endif /* !WITH_DTRACE */
 
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-09-25-12-35-48.bpo-31574.5yX5r5.rst b/Misc/NEWS.d/next/Core and Builtins/2017-09-25-12-35-48.bpo-31574.5yX5r5.rst
new file mode 100644
index 0000000..e5c8ae2
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2017-09-25-12-35-48.bpo-31574.5yX5r5.rst
@@ -0,0 +1 @@
+Importlib was instrumented with two dtrace probes to profile import timing.
diff --git a/Python/import.c b/Python/import.c
index 5e841ca..e50ea4d 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -12,6 +12,7 @@
 #include "frameobject.h"
 #include "osdefs.h"
 #include "importdl.h"
+#include "pydtrace.h"
 
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
@@ -1667,9 +1668,18 @@
     }
     else {
         Py_XDECREF(mod);
+
+        if (PyDTrace_IMPORT_FIND_LOAD_START_ENABLED())
+            PyDTrace_IMPORT_FIND_LOAD_START(PyUnicode_AsUTF8(abs_name));
+
         mod = _PyObject_CallMethodIdObjArgs(interp->importlib,
                                             &PyId__find_and_load, abs_name,
                                             interp->import_func, NULL);
+
+        if (PyDTrace_IMPORT_FIND_LOAD_DONE_ENABLED())
+            PyDTrace_IMPORT_FIND_LOAD_DONE(PyUnicode_AsUTF8(abs_name),
+                                           mod != NULL);
+
         if (mod == NULL) {
             goto error;
         }