{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Contents\n", "\n", "[Overview](#Overview)\n", "\n", "[Tracing code](#Tracing-code)\n", " * [Syntax](#Syntax)\n", " * [Tracing tips](#Tracing-tips)\n", " * [Implementation](#Implementation-of-@trace)\n", "\n", "[Manipulating traces](#Manipulating-traces)\n", " * [Custom text/HTML](#Custom-text/HTML)\n", " * [Map, filter, collect](#Map,-filter,-collect)\n", "\n", "[Saving traces to disk](#Saving-traces-to-disk)\n", "\n", "[Working with mutable state](#Working-with-mutable-state)\n", "\n", "[Debugging with traces](#Debugging-with-traces)\n", " * [Debugging test failures](#Debugging-test-failures)\n", " * [Displaying extra information](#Displaying-extra-information)\n", "\n", "[Profiling](#Profiling)\n", " * [Type stability](#Type-stability)\n", " * [Grouping and benchmarking](#Grouping-and-benchmarking)\n", " * [Profiling the compiler](#Profiling-the-compiler)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Overview\n", "\n", "[TraceCalls.jl](https://github.com/cstjean/TraceCalls.jl) is a functional tracing package for debugging and exploring Julia code. It records and displays a tree of function calls. For example, here is how [Calculus.jl](https://github.com/johnmyleswhite/Calculus.jl) computes the second-derivative of `sin(x) + sqrt(x)`:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "
#1() => -1.0914708926553454
Calculus.second_derivative(f, 1.0) => -1.0914708926553454
Calculus.derivative(f, :central) => Calculus.#20
Calculus.derivative(f, :scalar, :central) => Calculus.#20
Calculus.finite_difference_hessian(f, Calculus.#20, 1.0, :central) => -1.0914708926553454
Calculus.finite_difference(Calculus.#20, 1.0, :central) => -1.0914708926553454
Calculus.finite_difference(f, 1.0000060554544523, :central) => 1.0402956965076036
f(1.0000121109455733) => 1.8414835837724568
f(0.9999999999633314) => 1.8414709847697501
Calculus.finite_difference(f, 0.9999939445455476, :central) => 1.0403089152121567
f(1.0) => 1.8414709848078965
f(0.9999878890910952) => 1.8414583857213915
Calculus.derivative(f, :central) => Calculus.#20
Calculus.derivative(f, :scalar, :central) => Calculus.#20
#3() => DomainError()
Calculus.second_derivative(f, 0.0) => DomainError()
Calculus.derivative(f, :central) => Calculus.#58
Calculus.derivative(f, :scalar, :central) => Calculus.#58
Calculus.finite_difference_hessian(f, Calculus.#58, 0.0, :central) => DomainError()
Calculus.finite_difference(Calculus.#58, 0.0, :central) => DomainError()
Calculus.finite_difference(f, 6.0554544523933395e-6, :central) => 288.35028436717505
f(1.2110908904786679e-5) => 0.0034921840266401915
f(0.0) => 0.0
Calculus.finite_difference(f, -6.0554544523933395e-6, :central) => DomainError()
f(0.0) => 0.0
f(-1.2110908904786679e-5) => DomainError()
#1() => 256
Calculus.second_derivative(f, 1.0) => 256
Calculus.derivative(f, :central) => 208
Calculus.derivative(f, :scalar, :central) => 208
Calculus.finite_difference_hessian(f, Calculus.#20, 1.0, :central) => 16
Calculus.finite_difference(Calculus.#20, 1.0, :central) => 16
Calculus.finite_difference(f, 1.0000060554544523, :central) => 0
f(1.0000121109455733) => 0
f(0.9999999999633314) => 0
Calculus.finite_difference(f, 0.9999939445455476, :central) => 0
f(1.0) => 0
f(0.9999878890910952) => 0
#1() => [2, 1, 2, 3, 2]
LightGraphs.randomwalk({3, 2} undirected simple Int64 graph, 2, 5) => [2, 1, 2, 3, 2]
eltype({3, 2} undirected simple Int64 graph) => Int64
LightGraphs.vertices({3, 2} undirected simple Int64 graph) => 1:3
LightGraphs.nv({3, 2} undirected simple Int64 graph) => 3
eltype({3, 2} undirected simple Int64 graph) => Int64
LightGraphs.SimpleGraphs.fadj({3, 2} undirected simple Int64 graph) => Array{Int64,1}[[2], [1, 3], [2]]
LightGraphs.out_neighbors({3, 2} undirected simple Int64 graph, 2) => [1, 3]
LightGraphs.SimpleGraphs.fadj({3, 2} undirected simple Int64 graph, 2) => [1, 3]
LightGraphs.out_neighbors({3, 2} undirected simple Int64 graph, 1) => [2]
LightGraphs.SimpleGraphs.fadj({3, 2} undirected simple Int64 graph, 1) => [2]
LightGraphs.out_neighbors({3, 2} undirected simple Int64 graph, 2) => [1, 3]
LightGraphs.SimpleGraphs.fadj({3, 2} undirected simple Int64 graph, 2) => [1, 3]
LightGraphs.out_neighbors({3, 2} undirected simple Int64 graph, 3) => [2]
LightGraphs.SimpleGraphs.fadj({3, 2} undirected simple Int64 graph, 3) => [2]
LightGraphs.out_neighbors({3, 2} undirected simple Int64 graph, 2) => [1, 3]
LightGraphs.SimpleGraphs.fadj({3, 2} undirected simple Int64 graph, 2) => [1, 3]
LightGraphs.out_neighbors({3, 2} undirected simple Int64 graph, 2) => [1, 3]
LightGraphs.SimpleGraphs.fadj({3, 2} undirected simple Int64 graph, 2) => [1, 3]
#1() => [2, 1, 2, 3, 2]
LightGraphs.randomwalk({3, 2} undirected simple Int64 graph, 2, 5) => [2, 1, 2, 3, 2]
eltype({3, 2} undirected simple Int64 graph) => Int64
LightGraphs.vertices({3, 2} undirected simple Int64 graph) => 1:3
LightGraphs.out_neighbors({3, 2} undirected simple Int64 graph, 2) => [1, 3]
LightGraphs.out_neighbors({3, 2} undirected simple Int64 graph, 1) => [2]
#7() => 1:3
LightGraphs.vertices({3, 2} undirected simple Int64 graph) => 1:3
LightGraphs.nv({3, 2} undirected simple Int64 graph) => 3
eltype({3, 2} undirected simple Int64 graph) => Int64
LightGraphs.SimpleGraphs.fadj({3, 2} undirected simple Int64 graph) => Array{Int64,1}[[2], [1, 3], [2]]
#17() => [2,1,2,1,2]
LightGraphs.randomwalk(AnyOldGraph, 2, 5) => [2,1,2,1,2]
eltype(AnyOldGraph) => Int64
LightGraphs.vertices(AnyOldGraph) => 1:3
LightGraphs.nv(AnyOldGraph) => 3
eltype(AnyOldGraph) => Int64
LightGraphs.SimpleGraphs.fadj(AnyOldGraph) => Array{Int64,1}[[2], [1, 3], [2]]
LightGraphs.out_neighbors(AnyOldGraph, 2) => [1,3]
LightGraphs.SimpleGraphs.fadj(AnyOldGraph, 2) => [1,3]
LightGraphs.out_neighbors(AnyOldGraph, 1) => [2]
LightGraphs.SimpleGraphs.fadj(AnyOldGraph, 1) => [2]
LightGraphs.out_neighbors(AnyOldGraph, 2) => [1,3]
LightGraphs.SimpleGraphs.fadj(AnyOldGraph, 2) => [1,3]
LightGraphs.out_neighbors(AnyOldGraph, 1) => [2]
LightGraphs.SimpleGraphs.fadj(AnyOldGraph, 1) => [2]
LightGraphs.out_neighbors(AnyOldGraph, 2) => [1,3]
LightGraphs.SimpleGraphs.fadj(AnyOldGraph, 2) => [1,3]
#17() => [2,1,2,1,2]
LightGraphs.randomwalk(AnyOldGraph, 2, 5) => [2,1,2,1,2]
eltype(AnyOldGraph) => Int64
LightGraphs.vertices(AnyOldGraph) => 1:3
LightGraphs.nv(AnyOldGraph) => 3
eltype(AnyOldGraph) => Int64
LightGraphs.out_neighbors(AnyOldGraph, 2) => [1,3]
LightGraphs.out_neighbors(AnyOldGraph, 1) => [2]
LightGraphs.out_neighbors(AnyOldGraph, 2) => [1,3]
LightGraphs.out_neighbors(AnyOldGraph, 1) => [2]
LightGraphs.out_neighbors(AnyOldGraph, 2) => [1,3]
#17() => [2,1,2,1,2]
LightGraphs.randomwalk(AnyOldGraph, 2, 5) => [2,1,2,1,2]
LightGraphs.out_neighbors(AnyOldGraph, 2) => [1,3]
LightGraphs.SimpleGraphs.fadj(AnyOldGraph, 2) => [1,3]
LightGraphs.out_neighbors(AnyOldGraph, 2) => [1,3]
LightGraphs.SimpleGraphs.fadj(AnyOldGraph, 2) => [1,3]
LightGraphs.out_neighbors(AnyOldGraph, 2) => [1,3]
LightGraphs.SimpleGraphs.fadj(AnyOldGraph, 2) => [1,3]
#21() => nothing
LightGraphs.out_neighbors(AnyOldGraph, 2) => 2
LightGraphs.out_neighbors(AnyOldGraph, 3) => 3
LightGraphs.out_neighbors(AnyOldGraph, 2) => 2
LightGraphs.out_neighbors(AnyOldGraph, 1) => 1
LightGraphs.out_neighbors(AnyOldGraph, 2) => 2
#31() => [5,5,5]
many_5s(3) => [5,5,5]
push5!([5,5,5]) => [5,5,5]
push5!([5,5,5]) => [5,5,5]
push5!([5,5,5]) => [5,5,5]
#33() => [5,5,5]
many_5s(3) => [5,5,5]
push5!([]) => [5]
push5!([5]) => [5,5]
push5!([5,5]) => [5,5,5]
#35() => [5,5,5]
many_5s(3) => [5,5,5]
#37() => DomainError()
Optim.optimize(logplus10, [0.0], Optim.BFGS{LineSearches.#hagerzhang!,Optim.##115#119}(LineSearches.hagerzhang!, Optim.#115, true), Optim.Options{Void}(1.0e-32, 1.0e-32, 1.0e-8, false, 1000, false, false, false, false, 1, nothing, NaN)) => DomainError()
Optim.optimize(Optim.OnceDifferentiable(logplus10, Optim.g!, Optim.fg!), [0.0], Optim.BFGS{LineSearches.#hagerzhang!,Optim.##115#119}(LineSearches.hagerzhang!, Optim.#115, true), Optim.Options{Void}(1.0e-32, 1.0e-32, 1.0e-8, false, 1000, false, false, false, false, 1, nothing, NaN)) => DomainError()
Optim.update_state!(Optim.OnceDifferentiable(logplus10, Optim.g!, Optim.fg!), Optim.BFGSState{Float64,1,Array{Float64,1}}(\"BFGS\", 1, [0.0], 2.302585092994046, 1, 1, 0, [NaN], [0.1], [0.1], NaN, [2.37575e-314], [1.69069e-320], [NaN], [1.0], [-0.1], [-12.4999], [0.133333], 1.0, false, LineSearches.LineSearchResults{Float64}([0.0, 1.0, 5.0, 25.0], [2.30259, 2.29253, 2.25129, 2.0149], [-0.01, -0.010101, -0.0105263, -0.0133333], 0)), Optim.BFGS{LineSearches.#hagerzhang!,Optim.##115#119}(LineSearches.hagerzhang!, Optim.#115, true)) => DomainError()
Optim.perform_linesearch!(Optim.BFGSState{Float64,1,Array{Float64,1}}(\"BFGS\", 1, [0.0], 2.302585092994046, 1, 1, 0, [NaN], [0.1], [0.1], NaN, [2.37575e-314], [1.69069e-320], [NaN], [1.0], [-0.1], [-12.4999], [0.133333], 1.0, false, LineSearches.LineSearchResults{Float64}([0.0, 1.0, 5.0, 25.0], [2.30259, 2.29253, 2.25129, 2.0149], [-0.01, -0.010101, -0.0105263, -0.0133333], 0)), Optim.BFGS{LineSearches.#hagerzhang!,Optim.##115#119}(LineSearches.hagerzhang!, Optim.#115, true), Optim.OnceDifferentiable(logplus10, Optim.g!, Optim.fg!)) => DomainError()
Calculus.finite_difference!(logplus10, [-12.5], [0.133333], :central) => DomainError()
logplus10([-12.4999]) => DomainError()
Optim.perform_linesearch!(Optim.BFGSState{Float64,1,Array{Float64,1}}(\"BFGS\", 1, [0.0], 2.302585092994046, 1, 1, 0, [NaN], [0.1], [0.1], NaN, [2.37575e-314], [1.69069e-320], [NaN], [1.0], [-0.1], [-12.4999], [0.133333], 1.0, false, LineSearches.LineSearchResults{Float64}([0.0, 1.0, 5.0, 25.0], [2.30259, 2.29253, 2.25129, 2.0149], [-0.01, -0.010101, -0.0105263, -0.0133333], 0)), Optim.BFGS{LineSearches.#hagerzhang!,Optim.##115#119}(LineSearches.hagerzhang!, Optim.#115, true), Optim.OnceDifferentiable(logplus10, Optim.g!, Optim.fg!)) => DomainError()
Calculus.finite_difference!(logplus10, [-12.5], [0.133333], :central) => DomainError()
logplus10([-12.4999]) => DomainError()
#39() => DomainError()
Optim.perform_linesearch!(Optim.BFGSState{Float64,1,Array{Float64,1}}(\"BFGS\", 1, [0.0], 2.302585092994046, 1, 1, 0, [NaN], [0.1], [0.1], NaN, [2.37575e-314], [1.69069e-320], [NaN], [1.0], [-0.1], [-12.4999], [0.133333], 1.0, false, LineSearches.LineSearchResults{Float64}([0.0, 1.0, 5.0, 25.0], [2.30259, 2.29253, 2.25129, 2.0149], [-0.01, -0.010101, -0.0105263, -0.0133333], 0)), Optim.BFGS{LineSearches.#hagerzhang!,Optim.##115#119}(LineSearches.hagerzhang!, Optim.#115, true), Optim.OnceDifferentiable(logplus10, Optim.g!, Optim.fg!)) => DomainError()
Optim.checked_dphi0!(Optim.BFGSState{Float64,1,Array{Float64,1}}(\"BFGS\", 1, [0.0], 2.302585092994046, 1, 1, 0, [NaN], [0.1], [0.1], NaN, [2.37575e-314], [1.69069e-320], [NaN], [1.0], [-0.1], [-12.4999], [0.133333], 1.0, false, LineSearches.LineSearchResults{Float64}([0.0, 1.0, 5.0, 25.0], [2.30259, 2.29253, 2.25129, 2.0149], [-0.01, -0.010101, -0.0105263, -0.0133333], 0)), Optim.BFGS{LineSearches.#hagerzhang!,Optim.##115#119}(LineSearches.hagerzhang!, Optim.#115, true)) => -0.009999999996070853
Optim.alphaguess!(Optim.BFGSState{Float64,1,Array{Float64,1}}(\"BFGS\", 1, [0.0], 2.302585092994046, 1, 1, 0, [NaN], [0.1], [0.1], NaN, [2.37575e-314], [1.69069e-320], [NaN], [1.0], [-0.1], [-12.4999], [0.133333], 1.0, false, LineSearches.LineSearchResults{Float64}([0.0, 1.0, 5.0, 25.0], [2.30259, 2.29253, 2.25129, 2.0149], [-0.01, -0.010101, -0.0105263, -0.0133333], 0)), Optim.BFGS{LineSearches.#hagerzhang!,Optim.##115#119}(LineSearches.hagerzhang!, Optim.#115, true), -0.009999999996070853, Optim.OnceDifferentiable(logplus10, Optim.g!, Optim.fg!)) => 1.0
Calculus.finite_difference!(logplus10, [-0.1], [0.133333], :central) => nothing
logplus10([-0.0999939]) => 2.2925353688044074
logplus10([-0.100006]) => 2.2925341454802757
logplus10([-0.1]) => 2.2925347571425285
Calculus.finite_difference!(logplus10, [-0.5], [0.10101], :central) => nothing
logplus10([-0.499994]) => 2.25129243603289
logplus10([-0.500006]) => 2.2512911612003736
logplus10([-0.5]) => 2.251291798616835
Calculus.finite_difference!(logplus10, [-2.5], [0.105263], :central) => nothing
logplus10([-2.49998]) => 2.01490503909053
logplus10([-2.50002]) => 2.0149010021208964
logplus10([-2.5]) => 2.0149030206077505
Calculus.finite_difference!(logplus10, [-12.5], [0.133333], :central) => DomainError()
logplus10([-12.4999]) => DomainError()
#39() => DomainError()
Calculus.finite_difference!(logplus10, [-0.1], [0.133333], :central) => nothing
Calculus.finite_difference!(logplus10, [-0.5], [0.10101], :central) => nothing
Calculus.finite_difference!(logplus10, [-2.5], [0.105263], :central) => nothing
Calculus.finite_difference!(logplus10, [-12.5], [0.133333], :central) => DomainError()
#18() => 5.0
hypothenuse_length(3, 4) => 5.0
TraceCalls.trace_log(; a2=9, b2=16) => nothing
#8() => 1.0
getindex(PyObject, :pi) => 0.9699
getindex(PyObject, \"pi\") => 0.114
convert(PyCall.PyAny, PyObject 3.141592653589793) => 0.7366
PyCall.pytype_query(PyObject 3.141592653589793, PyCall.PyObject) => 0.4832
PyCall.pyint_query(PyObject 3.141592653589793) => 0.1354
PyCall.pyisinstance(PyObject 3.141592653589793, Ptr{PyCall.PyObject_struct} @0x000000011ef9cc98) => 0.0663
PyCall.pyisinstance(PyObject 3.141592653589793, Ptr{PyCall.PyObject_struct} @0x000000011ef9eaa8) => 0.06704
convert(Float64, PyObject 3.141592653589793) => 0.009888
PyCall.asscalar(PyObject 3.141592653589793) => 0.005534
#1() => false
getindex(PyObject, :pi) => false
getindex(PyObject, \"pi\") => true
Base.unsafe_convert(Ptr{PyCall.PyObject_struct}, PyObject) => true
convert(PyCall.PyAny, PyObject 3.141592653589793) => false
PyCall.pytype_query(PyObject 3.141592653589793, PyCall.PyObject) => false
PyCall.pyint_query(PyObject 3.141592653589793) => false
PyCall.pyisinstance(PyObject 3.141592653589793, Ptr{PyCall.PyObject_struct} @0x0000000124956c98) => true
Base.unsafe_convert(Ptr{PyCall.PyObject_struct}, PyObject 3.141592653589793) => true
PyCall.pyisinstance(PyObject 3.141592653589793, Ptr{PyCall.PyObject_struct} @0x0000000124958aa8) => true
Base.unsafe_convert(Ptr{PyCall.PyObject_struct}, PyObject 3.141592653589793) => true
PyCall.pyisinstance(PyObject 3.141592653589793, PyObject NULL) => true
PyCall.pyisinstance(PyObject 3.141592653589793, PyObject NULL) => true
PyCall.pyfloat_query(PyObject 3.141592653589793) => false
PyCall.pyisinstance(PyObject 3.141592653589793, Ptr{PyCall.PyObject_struct} @0x0000000124954998) => true
Base.unsafe_convert(Ptr{PyCall.PyObject_struct}, PyObject 3.141592653589793) => true
convert(Float64, PyObject 3.141592653589793) => true
PyCall.asscalar(PyObject 3.141592653589793) => true
PyCall.pyisinstance(PyObject 3.141592653589793, PyObject NULL) => true
Base.unsafe_convert(Ptr{PyCall.PyObject_struct}, PyObject 3.141592653589793) => true
PyCall.pyerr_check(\"ccall(@pysym(:PyFloat_AsDouble), Cdouble, (PyPtr,), asscalar(po))\", 3.141592653589793) => true
2 calls like convert(PyCall.PyAny, PyObject 3.141592653589793) => TrialEstimate(900.426 ns, 16 bytes)\n", "
1 call like #1() => TrialEstimate(1.355 μs, 224 bytes)\n", "
1 call like getindex(PyObject\n", ", :pi) => TrialEstimate(1.350 μs, 224 bytes)
1 call like PyCall.pytype_query(PyObject 3.141592653589793, PyCall.PyObject) => TrialEstimate(605.153 ns, 0 bytes)\n", "
3 calls like PyCall.pyisinstance(PyObject 3.141592653589793, Ptr{PyCall.PyObject_struct} @0x0000000124956c98) => TrialEstimate(86.650 ns, 0 bytes)\n", "
1 call like getindex(PyObject\n", ", \"pi\") => TrialEstimate(194.738 ns, 16 bytes)
1 call like PyCall.pyint_query(PyObject 3.141592653589793) => TrialEstimate(177.301 ns, 0 bytes)\n", "
3 calls like PyCall.pyisinstance(PyObject 3.141592653589793, PyObject NULL) => TrialEstimate(3.368 ns, 0 bytes)\n", "
5 calls like Base.unsafe_convert(Ptr{PyCall.PyObject_struct}, PyObject\n", ") => TrialEstimate(1.843 ns, 0 bytes)
1 call like PyCall.asscalar(PyObject 3.141592653589793) => TrialEstimate(6.723 ns, 0 bytes)\n", "
1 call like PyCall.pyerr_check(\"ccall(@pysym(:PyFloat_AsDouble), Cdouble, (PyPtr,), asscalar(po))\", 3.141592653589793) => TrialEstimate(5.806 ns, 0 bytes)\n", "
1 call like PyCall.pyfloat_query(PyObject 3.141592653589793) => TrialEstimate(5.797 ns, 0 bytes)\n" ], "text/plain": [ "Benchmark\n", " 2 calls like convert(PyCall.PyAny, PyObject 3.141592653589793) => \u001b[1m\u001b[32mTrialEstimate(900.426 ns, 16 bytes)\u001b[39m\u001b[22m\n", " 1 call like #1() => \u001b[1m\u001b[32mTrialEstimate(1.355 μs, 224 bytes)\u001b[39m\u001b[22m\n", " 1 call like getindex(PyObject
1 call like PyCall.pyerr_check(\"ccall(@pysym(:PyFloat_AsDouble), Cdouble, (PyPtr,), asscalar(po))\", 3.141592653589793) => TrialJudgement(+4.89% => invariant)\n", "
2 calls like convert(PyCall.PyAny, PyObject 3.141592653589793) => TrialJudgement(+0.97% => invariant)\n", "
1 call like PyCall.pytype_query(PyObject 3.141592653589793, PyCall.PyObject) => TrialJudgement(+0.90% => invariant)\n", "
1 call like PyCall.pyint_query(PyObject 3.141592653589793) => TrialJudgement(+0.34% => invariant)\n", "
5 calls like Base.unsafe_convert(Ptr{PyCall.PyObject_struct}, PyObject\n", ") => TrialJudgement(+0.00% => invariant)
1 call like PyCall.pyfloat_query(PyObject 3.141592653589793) => TrialJudgement(+0.00% => invariant)\n", "
3 calls like PyCall.pyisinstance(PyObject 3.141592653589793, PyObject NULL) => TrialJudgement(-0.03% => invariant)\n", "
1 call like PyCall.asscalar(PyObject 3.141592653589793) => TrialJudgement(-0.18% => invariant)\n", "
1 call like getindex(PyObject\n", ", \"pi\") => TrialJudgement(-0.49% => invariant)
1 call like #1() => TrialJudgement(-1.75% => invariant)\n", "
3 calls like PyCall.pyisinstance(PyObject 3.141592653589793, Ptr{PyCall.PyObject_struct} @0x0000000124956c98) => TrialJudgement(-0.97% => invariant)\n", "
1 call like getindex(PyObject\n" ], "text/plain": [ "Benchmark\n", " 1 call like PyCall.pyerr_check(\"ccall(@pysym(:PyFloat_AsDouble), Cdouble, (PyPtr,), asscalar(po))\", 3.141592653589793) => \u001b[1m\u001b[32m\u001b[91m, :pi) => TrialJudgement(-5.19% => improvement)