  Gradual typing enables programmers to combine static and dynamic typing in
the same language. However, ensuring a sound interaction between the static and
dynamic parts can incur significant runtime cost. In this paper, we perform a
detailed performance analysis of the transient gradual typing approach
implemented in Reticulated Python, a gradually typed variant of Python. The
transient approach inserts lightweight checks throughout a program rather than
installing proxies on higher order values. We show that, when running
Reticulated Python and the transient approach on CPython, performance decreases
as programs evolve from dynamic to static types, up to a 6x slowdown compared
to equivalent Python programs.
  To reduce this overhead, we design a static analysis and optimization that
removes redundant runtime checks. The optimization employs a static type
inference algorithm that solves traditional subtyping constraints and also a
new kind of check constraint. We evaluate the resulting performance and find
that for many programs, the efficiency of partially typed programs is close to
their untyped counterparts, removing most of the slowdown of transient checks.
Finally, we measure the efficiency of Reticulated Python programs when running
on PyPy, a tracing JIT. We find that combining PyPy with our type inference
algorithm reduces the overall overhead to zero.
