4 DebugRelease Armin Ronacher

CodeWarrior

2019/10/11 发布于 技术 分类

文字内容
1. DEBUG IS THE NEW
2. THE UNEXPECTED BENEFITS OF SLOW
3. ARMIN @MITSUHIKO RONACHER / FLASK, WERKZEUG, JINJA, CLICK, … / DIRECTOR OF ENGINEERING AT
5. 1. developer experience matters 2. the ability to debug matters 3. debugging does not stop when shipping a release
6. Python 3.7.4 (default, Jul 9 2019, 18:13:23) [Clang 10.0.1 (clang-1001.0.46.4)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> a_variable = 'Hello World!' >>> sys._getframe().f_locals['a_variable'] 'Hello World!'
7. RUNTIME INTROSPECTION
8. RUNTIME INTROSPECTION
9. RUNTIME INTROSPECTION
10. S K R O W “ N MY O ” E N I H C A M
11. MILLIONS OF BROWSER SESSIONS HUNDREDS OF COUNTRIES
12. IOT DEVICES MOBILE PHONES
13. LET'S DEBUG
14. you need basic debugging and introspection in production
15. PROD VS DEBUG PERF
16. let's talk about runtimes …
17. Simple Interpreter JIT compiled AOT compiled
18. • these are examples • not scientific • not entirely comparable
19. INTER PRETER
20. A Simple Interpreter: CPython
21. >>> import dis >>> >>> def add_numbers(a, b): ... return a + b ... >>> dis.dis(add_numbers) 2 0 LOAD_FAST 2 LOAD_FAST 4 BINARY_ADD 6 RETURN_VALUE 0 (a) 1 (b)
22. while ... { switch (...) { case TARGET(LOAD_FAST): { PyObject *value = GETLOCAL(oparg); if (value == NULL) { format_exc_check_arg(tstate, PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(co->co_varnames, oparg)); goto error; } Py_INCREF(value); PUSH(value); FAST_DISPATCH(); } }
23. case TARGET(BINARY_ADD): { PyObject *right = POP(); PyObject *left = TOP(); PyObject *sum; if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) { sum = unicode_concatenate(tstate, left, right, f, next_instr); } else { sum = PyNumber_Add(left, right); Py_DECREF(left); } Py_DECREF(right); SET_TOP(sum); if (sum == NULL) goto error; DISPATCH(); }
24. there is a lot of compiled code executing every instruction
25. import sys def failing_func(): raise Exception('Oh noes') def catching_func(): try:'>try: failing_func() except Exception:'>Exception: pass def stacktrace_making_func(): try:'>try: failing_func() except Exception:'>Exception: sys.exc_info()
26. mitsuhiko at argus in /tmp $ python -mtimeit -s 'from test import catching_func as x' 'x()' 1000000 loops, best of 3: 1.34 usec per loop mitsuhiko at argus in /tmp $ python -mtimeit -s 'from test import stacktrace_making_func as x' 'x()' 1000000 loops, best of 3: 1.44 usec per loop 7% l S r e w o
27. JIT
28. JIT Compiled Interpreter: V8
29. function throwingFunc() { throw new Error('Oh noes'); } function catchingFunc() { try { throwingFunc(); } catch (err) {} } function stacktraceMakingFunc() { try { throwingFunc(); } catch (err) { return err.stack; } }
30. catching x 160,895 ops/sec ±2.30% (60 runs sampled) stacktrace making x 26,495 ops/sec ±1.98% (86 runs sampled) r we % 3 8 o Sl
31. T O
32. Native Code: clang
33. well what's a stack trace anyways?
34. K C A T S G N I K L A W
35. there is a little DWARF in your computer
36. stack unwinding: go to where a function would return to
37. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 libsystem_kernel.dylib CoreFoundation CoreFoundation CoreFoundation HIToolbox HIToolbox HIToolbox AppKit AppKit AppKit YetAnotherMac YetAnotherMac libdyld.dylib YetanotherMac 0x00007fff61bc6c2a 0x00007fff349f505e 0x00007fff349f45ad 0x00007fff349f3ce4 0x00007fff33c8d895 0x00007fff33c8d5cb 0x00007fff33c8d348 0x00007fff31f4a95b 0x00007fff31f496fa 0x00007fff31f4375d 0x0000000108b7092b 0x0000000108b702a6 0x00007fff61a8e085 0x00000000000ea004 0x7fff61bc6000 + 3114 0x7fff349b9000 + 245854 0x7fff349b9000 + 243117 0x7fff349b9000 + 240868 0x7fff33c83000 + 43157 0x7fff33c83000 + 42443 0x7fff33c83000 + 41800 0x7fff31f30000 + 108891 0x7fff31f30000 + 104186 0x7fff31f30000 + 79709 0x10864e000 + 5384491 a_function_here + 64 start + 0 main (main.m:16)
38. okay it's “fast”, but it's also pretty bad
39. because better would be much slower
40. • unwinding on device • deferred symbolication • pain, suffering and disappointment
41. want stack traces? need to capture when exceptions are thrown
42. 1. debuggability incurs runtime cost 2. JIT/AOT optimizations break down 3. If you want debug functionality in production, percentage performance loss matters
43. Sentry exists, because cheap in-production debugging is amazing and not much slower in Python
44. BUT ARMIN, STACK TRACES ARE FAST!!!111
45. but we expect more
46. Exception Data Stacktraces Source Code Local Variables S S E L E M A H S ( T U B PLUG R O F IT'S ) T X E T N O C
47. value wh a t y o u have, Python d evelope rs
48. WHAT DO WE HAVE?
49. >>> import sys >>> sys._current_frames() {4656870848: ', line 1, code >}
50. >>> import sys >>> sys._getframe().f_locals {'__annotations__': {}, '__builtins__': , '__cached__': None, '__doc__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x1090d55d0>, '__name__': '__main__', '__package__': None, '__spec__': None, 'sys': }
51. >>> try: ... 1/0 ... except Exception as e: ... e.__traceback__ ...
52. from threading import Thread old_start = Thread.start Thread.start = make_new_start(old_start)
53. you can also attach a debugger, run some code and start a reverse python shell on a running process
54. & Python 3.7 has execution contexts (context vars)
55. WHAT WILL THE FUTURE BRING
56. K S A OUR Y QUESTIONS — I DON'T BITE —