This dissertation addresses challenges in balancing performance and power/energy consumption in computing systems. Systems are often underutilized, meaning applications do not require all of a system's resources in order to achieve desired behavior, e.g., an application performance goal or reasonable system energy consumption. Modern systems expose knobs for tuning resources, like processor frequency or core allocation, which have a quantifiable impact on application performance and system power consumption. The result is a tradeoff space that can be navigated by resource schedulers to achieve desired behavior, sacrificing one dimension in favor of another, e.g., increased performance at the cost of increased power or energy consumption. The optimal knob settings required to achieve desired behavior depend on both the application and system, even changing during the course of execution as applications progress through different processing phases. The challenge in designing general and portable solutions to these problems arises from the diversity in both hardware and software systems.,We first address the problem of meeting application performance goals while minimizing energy consumption with two projects---POET and CoPPer. Both projects use control theory, which provides a formal framework for reasoning about dynamic systems, including convergence guarantees and robustness to model inaccuracies. In contrast, commonly used heuristic techniques cannot provide these guarantees, nor are they always portable. POET is a general solution that is portable between applications and systems---it is independent of different knob types and their allowable settings. POET produces resource schedules to exactly meet performance goals while achieving optimal energy consumption. CoPPer leverages recent power capping technology in place of software-managed Dynamic Voltage and Frequency Scaling (DVFS), which is being deprecated by hardware vendors. CoPPer overcomes challenges presented by the non-linear relationship between performance and power to meet performance goals while leaving the energy optimization to hardware, which responds more rapidly to changes in application resource requirements than software.,Finally, we address the problem of optimizing energy efficiency to minimize the execution cost of running applications with the CEES project. CEES uses machine learning classifiers, driven by low-level hardware performance counters, to predict the most energy-efficient knob settings at runtime based on current application resource utilization. By using performance counters, no application modifications are necessary. We evaluate this approach in the High Performance Computing (HPC) domain, more aggressively trading performance for energy savings than has historically been done, reducing the cost of scientific insight. Extrapolating from empirical single-node performance and power results, scaling the solution to hardware over-provisioned, power-constrained clusters could increase total cluster throughput by up to 24%.,The three projects presented in this dissertation dynamically adapt to changing application and system behavior at runtime, and are thus able to provide more optimal results than commonly used static resource scheduling techniques. Furthermore, the project designs are independent of particular applications and systems, making them portable to a wide range of computing platforms.