  Developing efficient and maintainable software systems is both hard and time
consuming. In particular, non-functional performance requirements involve many
design and implementation decisions that can be difficult to take early during
system development. Choices -- such as selection of data structures or where
and how to parallelize code -- typically require extensive manual tuning that
is both time consuming and error-prone. Although various auto-tuning approaches
exist, they are either specialized for certain domains or require extensive
code rewriting to work for different contexts in the code. In this paper, we
introduce a new methodology for writing programs with holes, that is, decision
variables explicitly stated in the program code that enable developers to
postpone decisions during development. We introduce and evaluate two novel
ideas: (i) context-sensitive holes that are expanded by the compiler into sets
of decision variables for automatic tuning, and (ii) dependency-aware tuning,
where static analysis reduces the search space by finding the set of decision
variables that can be tuned independently of each other. We evaluate the two
new concepts in a system called Miking, where we show how the general
methodology can be used for automatic algorithm selection, data structure
decisions, and parallelization choices.
