Optimizing Speculative Execution in Spark Heterogeneous Environments