You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by st...@apache.org on 2021/10/18 14:10:10 UTC

[impala] branch master updated (45fd332 -> dc313b3)

This is an automated email from the ASF dual-hosted git repository.

stigahuang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git.


    from 45fd332  IMPALA-10945: Fix S3 scratch path behavior
     new 1e92c09  IMPALA-10950: Update expr-benchmark.cc
     new dc313b3  IMPALA-10921 Add script to compare TPCDS runs.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 be/src/benchmarks/expr-benchmark.cc                | 945 ++++++++++++++-------
 .../experimental/tpcds_run_comparator.py           | 297 +++++++
 2 files changed, 929 insertions(+), 313 deletions(-)
 create mode 100755 bin/diagnostics/experimental/tpcds_run_comparator.py

[impala] 02/02: IMPALA-10921 Add script to compare TPCDS runs.

Posted by st...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

stigahuang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit dc313b3e4cae3dd57c55cc40e9c2b824082918a7
Author: Amogh Margoor <am...@cloudera.com>
AuthorDate: Tue Sep 14 03:03:08 2021 -0700

    IMPALA-10921 Add script to compare TPCDS runs.
    
    This script compares 2 runs of TPCDS by parsing their respective
    Impala plain text query profiles. It currently outputs the peak
    memory comparision of both runs where:
    1. It compares average per-node peak memory and geo-mean
       per-node peak memory.
    2. It compares max peak memory reduction among Hash operators.
    
    It can be extended to other comparisions in future.
    
    Example usage:
    
     tpcds_run_comparator.py <path to base run profile>
     <path to new run profile> [path to result csv file]
    
    Change-Id: Ib2e9ae1a2919156b0022072f47ff71d7775b20e6
    Reviewed-on: http://gerrit.cloudera.org:8080/17855
    Reviewed-by: Riza Suminto <ri...@cloudera.com>
    Reviewed-by: Zoltan Borok-Nagy <bo...@cloudera.com>
    Tested-by: Zoltan Borok-Nagy <bo...@cloudera.com>
---
 .../experimental/tpcds_run_comparator.py           | 297 +++++++++++++++++++++
 1 file changed, 297 insertions(+)

diff --git a/bin/diagnostics/experimental/tpcds_run_comparator.py b/bin/diagnostics/experimental/tpcds_run_comparator.py
new file mode 100755
index 0000000..3c635cd
--- /dev/null
+++ b/bin/diagnostics/experimental/tpcds_run_comparator.py
@@ -0,0 +1,297 @@
+#!/usr/bin/env python3
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License
+
+import argparse
+import csv
+import math
+import re
+import statistics
+import os
+
+from enum import Enum
+from collections import namedtuple
+
+# This script compares 2 runs of TPCDS by parsing their respective Impala plain text
+# query profiles. It currently outputs the peak memory comparision of both runs where:
+# 1. It compares average per-node peak memory and geo-mean per-node peak memory.
+# 2. It compares max peak memory reduction among Hash operators.
+#
+# It can be extended to other comparisions in future.
+#
+# Example usage:
+#
+#   tpcds_run_comparator.py <path to base run profile> <path to new run profile>
+#                           [path to result csv file]
+#
+
+
+class Task(Enum):
+  DISCARD = 0
+  PARSE_EXEC_SUMM = 3
+  PARSE_PEAK_MEMORY = 4
+
+
+ParseTask = namedtuple('ParseTask', ['task', 'delimiter'])
+ExecSumm = namedtuple('ExecSumm',
+    ['id', 'name', 'num_host', 'num_inst', 'avg_time', 'max_time', 'num_rows',
+      'est_rows', 'peak_mem', 'est_peak_mem', 'detail'])
+
+RE_PEAK_MEM = re.compile("\d+\.\d\d [GMK]?B")
+
+# Defines list of sections in a profile file.
+# Format: (Task Enum, Section Delimeter)
+# Section Delimeter is the first line of next section in the list.
+SECTIONS = [
+    ParseTask(Task.DISCARD,
+      "    ExecSummary:"),
+    ParseTask(Task.PARSE_EXEC_SUMM,
+      "    Errors:"),
+    ParseTask(Task.DISCARD,
+      "    Per Node Peak Memory Usage:"),
+    ParseTask(Task.PARSE_PEAK_MEMORY,
+      "    Per Node Bytes Read:")
+  ]
+
+
+# Other const.
+DEBUG = False
+
+
+def debug(s):
+  if DEBUG:
+    print(s)
+
+
+def geo_mean(bytes):
+  """Compute geo mean"""
+  sum_log = sum([math.log(x) for x in bytes])
+  return math.exp(float(sum_log) / len(bytes))
+
+
+def str_to_byte(line):
+  """Parse byte string into integer."""
+  parts = line.split(' ')
+  byte = float(parts[0])
+  unit = parts[1]
+  if unit == 'B':
+    byte *= 1
+  elif unit == 'KB':
+    byte *= 1024
+  elif unit == 'MB':
+    byte *= 1024**2
+  elif unit == 'GB':
+    byte *= 1024**3
+  else:
+    raise ValueError("Invalid unit for byte string: {}".format(byte))
+  return math.trunc(byte)
+
+
+class ProfileParser:
+  """Class that parses Impala plain text query profile"""
+
+  def __init__(self):
+    # execution summary
+    self.exec_summ_ct = 0
+    self.exec_summ_map = {}
+    # peak memory
+    self.peak_mem_ct = 0
+    self.peak_mem = []
+    # result
+    self.ht_mem_res = []
+    self.op_mem_res = []
+
+  def parse_peak_mem(self, line):
+    """Parses the peak memory"""
+    debug('Parsing Peak memory')
+    if self.peak_mem_ct > 1:
+      return
+    self.peak_mem_ct += 1
+    mems = RE_PEAK_MEM.findall(line)
+    self.peak_mem = [str_to_byte(i) for i in mems]
+    debug('Peak memories: ' + ",".join([str(i) for i in self.peak_mem]))
+
+  def parse_exec_summ(self, line):
+    """Parse execution summary section.
+    This section begins with 'ExecSummary:' line in query profile."""
+    self.exec_summ_ct += 1
+    if self.exec_summ_ct <= 3:
+      return
+
+    parts = list(
+        map(lambda x: x.strip(),
+          filter(None,
+            line.strip().replace("|", " ").replace("--", "  ").split("  "))))
+
+    # 3 columns in ExecSummary are optional and may be empty for few operators.
+    # These are #Rows, Est. #Rows and Detail.
+    # Normalize all the entries to 10 parts below.
+    if len(parts) == 7:
+      parts.insert(5, "-")
+      parts.insert(6, "-")
+    assert len(parts) >= 9
+    if len(parts) == 9:
+      parts.append("-")
+    assert len(parts) == 10
+
+    # split id and name from parts[0].
+    tok = parts[0].split(':')
+    parts[0] = tok[1]
+    parts.insert(0, tok[0])
+    assert len(parts) == 11
+
+    es = ExecSumm._make(parts)
+    debug(es)
+    self.exec_summ_map[es.id] = es
+
+  def parse(self, inf):
+    """Walk through impala query plan and parse each section accordingly.
+    A section ends when delimiter of that section is found."""
+    i = 0
+    for line in inf:
+      if (line.rstrip().startswith(SECTIONS[i].delimiter) or
+            (not SECTIONS[i].delimiter and not line.rstrip())):
+        debug('Found delimiter ' + SECTIONS[i].delimiter + ' in ' + line)
+        i += 1
+      if i == len(SECTIONS):
+        break
+      if SECTIONS[i].task == Task.DISCARD:
+        continue
+      elif SECTIONS[i].task == Task.PARSE_EXEC_SUMM:
+        self.parse_exec_summ(line)
+      elif SECTIONS[i].task == Task.PARSE_PEAK_MEMORY:
+        self.parse_peak_mem(line)
+
+  def filter_exec_join(self, op):
+    filter_set = {'HASH JOIN', 'JOIN BUILD', 'AGGREGATE'}
+    return op.name in filter_set
+
+  def compare_hash_table_mem(self, pp, path, ht_mem_res):
+    join_list1 = filter(self.filter_exec_join, self.exec_summ_map.values())
+    result = [os.path.basename(path), '0.0', '0.0', '0.0']
+    max_hash_percent = 0.0
+    for j in join_list1:
+      bytes1 = str_to_byte(j.peak_mem)
+      bytes2 = str_to_byte(pp.exec_summ_map[j.id].peak_mem)
+      # Checks the percent reduction for operators greater than 10 MB.
+      if bytes1 > 10 * 1024 * 1024 and bytes2 != bytes1:
+        percent = float(bytes1 - bytes2) / bytes1 * 100
+        if abs(percent) > max_hash_percent:
+          result = []
+          result = [os.path.basename(path), str(round(bytes1 / float(1024 * 1024))),
+            str(round(bytes2 / float(1024 * 1024))),
+            str(round(percent, 1))]
+          max_hash_percent = percent
+    ht_mem_res.append(result)
+
+  def compare_peak_mem(self, pp, path, op_mem_res):
+    avg1 = statistics.mean(self.peak_mem)
+    debug('average1=' + str(avg1))
+    avg2 = statistics.mean(pp.peak_mem)
+    debug('average2=' + str(avg2))
+    geo_mean1 = geo_mean(self.peak_mem)
+    debug('geomean1=' + str(geo_mean1))
+    geo_mean2 = geo_mean(pp.peak_mem)
+    debug('geomean2=' + str(geo_mean2))
+    max1 = max(self.peak_mem)
+    max2 = max(pp.peak_mem)
+    reduction_avg = float(avg1 - avg2) / avg1 * 100
+    reduction_geomean = float(geo_mean1 - geo_mean2) / geo_mean1 * 100
+    reduction_max = float(max1 - max2) / max1 * 100
+    res = [avg1 / (1024 * 1024), avg2 / (1024 * 1024), reduction_avg,
+      geo_mean1 / (1024 * 1024), geo_mean2 / (1024 * 1024), reduction_geomean,
+      reduction_max]
+    fres = [str(round(i, 1)) for i in res]
+    fres.insert(0, os.path.basename(path))
+    op_mem_res.append(fres)
+    debug(",".join(fres))
+
+
+def print_results(ht_mem_res, op_mem_res):
+  print("Peak Memory Comparision")
+  print("-----------------------")
+  print("")
+  print("1. Maximum Reduction in Per-operator Peak Memory")
+  print("""TPCDS query profile, base peak memory, new peak memory""")
+  print("")
+  for ht in ht_mem_res:
+    print(",".join(ht))
+  print("")
+  print("2. Reduction in Per-Node Peak Memory")
+  print("""TPCDS query profile, base avg (MB), new avg (MB), avg reduction %,
+    base geomean (MB), new geomean (MB), geomean reduction % """)
+  for mem in op_mem_res:
+    print(",".join(mem))
+
+
+def results_to_csv(ht_mem_res, op_mem_res, csv_path):
+  with open(csv_path, 'w') as csv_f:
+    writer = csv.writer(csv_f)
+    header1 = ['TPCDS query profile', 'base peak memory', 'new peak memory']
+    writer.writerow(header1)
+    writer.writerows(ht_mem_res)
+    header2 = ['TPCDS query profile', 'base avg (MB)', 'new avg (MB)',
+      'avg reduction %', 'base geomean (MB)', 'new geomean (MB)', 'geomean reduction %']
+    writer.writerow(header2)
+    writer.writerows(op_mem_res)
+
+
+def is_dir(path):
+  if os.path.isdir(path):
+    return path
+  else:
+    raise argparse.ArgumentTypeError("{} is not a valid path".format(path))
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description="""This script reads Impala plain text query profiles of two TPCDS
+        runs and compare peak memories""")
+  parser.add_argument("basedir", type=is_dir,
+      help='Impala baseline query profiles directory.')
+  parser.add_argument("newdir", type=is_dir,
+      help='Impala new query profiles directory to be compared with baseline.')
+  parser.add_argument("result", nargs='?', default=None,
+      help="""Specify output CSV file path to be used to write results,
+        else it would be printed out to stdout""")
+  args = parser.parse_args()
+  op_mem_res = []
+  ht_mem_res = []
+  basefiles = [f for f in os.listdir(args.basedir)
+    if os.path.isfile(os.path.join(args.basedir, f))]
+  for filename in basefiles:
+    path1 = os.path.join(args.basedir, filename)
+    path2 = os.path.join(args.newdir, filename)
+    if os.path.isfile(path1) and os.path.isfile(path2):
+      debug("{} is being parsed ".format(path1))
+      with open(path1, "r") as f1:
+        with open(path2, "r") as f2:
+          pp1 = ProfileParser()
+          pp1.parse(f1)
+          pp2 = ProfileParser()
+          pp2.parse(f2)
+          pp1.compare_hash_table_mem(pp2, path1, ht_mem_res)
+          pp1.compare_peak_mem(pp2, path1, op_mem_res)
+  if args.result is None:
+    print_results(ht_mem_res, op_mem_res)
+  else:
+    results_to_csv(ht_mem_res, op_mem_res, args.result)
+
+
+if __name__ == "__main__":
+  main()

[impala] 01/02: IMPALA-10950: Update expr-benchmark.cc

Posted by st...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

stigahuang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit 1e92c097d97dd4c688b8994e3ea63e8de80e35ec
Author: Riza Suminto <ri...@cloudera.com>
AuthorDate: Fri Oct 1 14:21:53 2021 -0700

    IMPALA-10950: Update expr-benchmark.cc
    
    With the introduction of PlanRootSink by IMPALA-2905, query planner has
    moved the scalar expression's thrift definition from
    'fragments[0].output_sink.output_exprs' to
    'fragments[0].plan.nodes[0].union_node.const_expr_lists[0]' for a
    constant query. This patch adjusts expr-benchmark.cc to generate the
    ScalarExpr from the right thrift location and also modify the helper
    class to ensure proper resource cleanup at the end of the benchmark. We
    explicitly set ENABLE_EXPR_REWRITES=0 to prevent expression rewrite by
    FoldConstantsRule.java.
    
    The benchmark used to run without codegen. This patch modifies the
    benchmark to run a benchmark suite both with and without codegen.
    
    Testing:
    - Run and verify that expr-benchmark does not crash.
    
    Change-Id: I5b17434d85e32a58622bffb64a697b062a8bf43f
    Reviewed-on: http://gerrit.cloudera.org:8080/17894
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 be/src/benchmarks/expr-benchmark.cc | 945 ++++++++++++++++++++++++------------
 1 file changed, 632 insertions(+), 313 deletions(-)

diff --git a/be/src/benchmarks/expr-benchmark.cc b/be/src/benchmarks/expr-benchmark.cc
index f915096..0ece02f 100644
--- a/be/src/benchmarks/expr-benchmark.cc
+++ b/be/src/benchmarks/expr-benchmark.cc
@@ -18,156 +18,209 @@
 #include <stdio.h>
 #include <iostream>
 
-#include <jni.h>
-#include <thrift/Thrift.h>
-#include <thrift/protocol/TDebugProtocol.h>
-
 #include "runtime/exec-env.h"
 #include "runtime/runtime-state.h"
 
-#include "exprs/scalar-expr.h"
 #include "exprs/scalar-expr-evaluator.h"
-#include "util/backend-gflag-util.h"
+#include "exprs/scalar-expr.h"
+#include "exprs/timezone_db.h"
 #include "util/benchmark.h"
-#include "util/cpu-info.h"
-#include "util/debug-util.h"
-#include "util/jni-util.h"
-#include "rpc/jni-thrift-util.h"
 
-#include "gen-cpp/Types_types.h"
-#include "gen-cpp/ImpalaService.h"
-#include "gen-cpp/DataSinks_types.h"
-#include "gen-cpp/Types_types.h"
-#include "gen-cpp/ImpalaService.h"
-#include "gen-cpp/ImpalaService_types.h"
-#include "gen-cpp/Frontend_types.h"
-#include "gen-cpp/ImpalaService.h"
-#include "gen-cpp/Frontend_types.h"
-#include "rpc/thrift-server.h"
 #include "codegen/llvm-codegen.h"
 #include "common/init.h"
 #include "common/object-pool.h"
 #include "common/status.h"
+#include "common/thread-debug-info.h"
+#include "gen-cpp/DataSinks_types.h"
+#include "gen-cpp/Frontend_types.h"
+#include "gen-cpp/Types_types.h"
 #include "runtime/fragment-state.h"
 #include "runtime/mem-pool.h"
 #include "runtime/mem-tracker.h"
-#include "runtime/query-state.h"
 #include "service/fe-support.h"
 #include "service/frontend.h"
 #include "service/impala-server.h"
 
 #include "common/names.h"
 
+DECLARE_string(hdfs_zone_info_zip);
+
 using namespace apache::thrift;
 using namespace impala;
 
+// Struct holding reference to RuntimeState, FragmentState, ScalarExpr, and
+// ScalarExprEvaluator for a specific expression.
+// This ExprTestData should be obtained through Planner::PrepareScalarExpression() that
+// will populate all the objects and open the ScalarExprEvaluator.
+struct ExprTestData {
+  ExprTestData(RuntimeState* state, FragmentState* fragment_state, ScalarExpr* expr,
+      ScalarExprEvaluator* eval)
+    : state_(state),
+      fragment_state_(fragment_state),
+      expr_(expr),
+      eval_(eval),
+      dummy_result_(0) {}
+
+  ~ExprTestData() {
+    eval_->Close(state_);
+    expr_->Close();
+    fragment_state_->ReleaseResources();
+    state_->ReleaseResources();
+  }
+
+  RuntimeState* state_;
+  FragmentState* fragment_state_;
+  ScalarExpr* expr_;
+  ScalarExprEvaluator* eval_;
+  int64_t dummy_result_;
+};
+
 // Utility class to take (ascii) sql and return the plan.  This does minimal
 // error handling.
 class Planner {
  public:
-  Planner() {
+  Planner() : mem_pool_(&tracker_) {
     frontend_.SetCatalogIsReady();
     ABORT_IF_ERROR(exec_env_.InitForFeSupport());
+    query_options_.enable_expr_rewrites = false;
   }
 
-  ~Planner() {
-    if (fragment_state_ != nullptr) fragment_state_->ReleaseResources();
-  }
+  // Tell planner to enable/disable codegen on PrepareScalarExpression.
+  void EnableCodegen(bool enable) { query_options_.__set_disable_codegen(!enable); }
 
-  Status GeneratePlan(const string& stmt, TExecRequest* result) {
+  // Create ExprTestData for a given query.
+  // Returned *test_data contains valid ExprTestData* in which eval_ is already opened.
+  // Assumes 'query' is a constant query.
+  Status PrepareScalarExpression(const string& query, ExprTestData** test_data) {
+    TExecRequest request;
     TQueryCtx query_ctx;
-    query_ctx.client_request.stmt = stmt;
-    query_ctx.client_request.query_options = query_options_;
     query_ctx.__set_session(session_state_);
+    query_ctx.client_request.__set_stmt(query);
+    query_ctx.client_request.__set_query_options(query_options_);
     string dummy_hostname = "";
     TNetworkAddress dummy_addr;
     ImpalaServer::PrepareQueryContext(dummy_hostname, dummy_addr, &query_ctx);
-    runtime_state_.reset(new RuntimeState(query_ctx, &exec_env_));
-    TPlanFragment* fragment = runtime_state_->obj_pool()->Add(new TPlanFragment());
-    PlanFragmentCtxPB* fragment_ctx =
-        runtime_state_->obj_pool()->Add(new PlanFragmentCtxPB());
-    fragment_state_ = runtime_state_->obj_pool()->Add(
-        new FragmentState(runtime_state_->query_state(), *fragment, *fragment_ctx));
-
-    return frontend_.GetExecRequest(query_ctx, result);
-  }
 
-  RuntimeState* GetRuntimeState() { return runtime_state_.get(); }
+    RuntimeState* state = pool_.Add(new RuntimeState(query_ctx, &exec_env_));
+    TPlanFragment* fragment = state->obj_pool()->Add(new TPlanFragment());
+    PlanFragmentCtxPB* fragment_ctx = state->obj_pool()->Add(new PlanFragmentCtxPB());
+
+    FragmentState* fragment_state = state->obj_pool()->Add(
+        new FragmentState(state->query_state(), *fragment, *fragment_ctx));
+    RETURN_IF_ERROR(frontend_.GetExecRequest(query_ctx, &request));
+
+    // For query "select 1 + 1", planner will return query plan:
+    //
+    // F00:PLAN FRAGMENT [UNPARTITIONED] hosts=1 instances=1
+    // |  Per-Host Resources: mem-estimate=4.00MB mem-reservation=4.00MB thread-reservation=1
+    // PLAN-ROOT SINK
+    // |  output exprs: 1 + 1
+    // |  mem-estimate=4.00MB mem-reservation=4.00MB spill-buffer=2.00MB thread-reservation=0
+    // |
+    // 00:UNION
+    //    constant-operands=1
+    //    mem-estimate=0B mem-reservation=0B thread-reservation=0
+    //    tuple-ids=0 row-size=2B cardinality=1
+    //
+    // However, the TExpr for the scalar expression is not in the output_sink's
+    // output_exprs. Instead, it is in the union node's const_expr_lists.
+    const TQueryExecRequest& query_request = request.query_exec_request;
+    TUnionNode union_node =
+        query_request.plan_exec_info[0].fragments[0].plan.nodes[0].union_node;
+    vector<TExpr> texprs = union_node.const_expr_lists[0];
+    DCHECK_EQ(texprs.size(), 1);
+
+    ScalarExpr* expr;
+    RETURN_IF_ERROR(
+        ScalarExpr::Create(texprs[0], RowDescriptor(), fragment_state, &expr));
+    ScalarExprEvaluator* eval;
+    RETURN_IF_ERROR(
+        ScalarExprEvaluator::Create(*expr, state, &pool_, &mem_pool_, &mem_pool_, &eval));
+
+    // UDFs which cannot be interpreted need to be handled by codegen.
+    // This follow examples from fe-support.cc
+    if (fragment_state->ScalarExprNeedsCodegen()) {
+      RETURN_IF_ERROR(fragment_state->CreateCodegen());
+      LlvmCodeGen* codegen = fragment_state->codegen();
+      DCHECK(codegen != NULL);
+      RETURN_IF_ERROR(fragment_state->CodegenScalarExprs());
+      codegen->EnableOptimizations(true);
+      RETURN_IF_ERROR(codegen->FinalizeModule());
+    }
+    RETURN_IF_ERROR(eval->Open(state));
 
-  FragmentState* GetFragmentState() { return fragment_state_; }
+    *test_data = pool_.Add(new ExprTestData(state, fragment_state, expr, eval));
+    return Status::OK();
+  }
 
  private:
   Frontend frontend_;
   ExecEnv exec_env_;
-  scoped_ptr<RuntimeState> runtime_state_;
-  FragmentState* fragment_state_;
 
   TQueryOptions query_options_;
   TSessionState session_state_;
-};
 
-struct TestData {
-  ScalarExprEvaluator* eval;
-  int64_t dummy_result;
+  ObjectPool pool_;
+  MemTracker tracker_;
+  MemPool mem_pool_;
 };
 
 Planner* planner;
-ObjectPool pool;
-MemTracker tracker;
-MemPool mem_pool(&tracker);
-
-// Utility function to get prepare select list for exprs.  Assumes this is a
-// constant query.
-static Status PrepareSelectList(
-    const TExecRequest& request, ScalarExprEvaluator** eval) {
-  const TQueryExecRequest& query_request = request.query_exec_request;
-  vector<TExpr> texprs = query_request.plan_exec_info[0].fragments[0].output_sink.output_exprs;
-  DCHECK_EQ(texprs.size(), 1);
-  RuntimeState* state = planner->GetRuntimeState();
-  ScalarExpr* expr;
-  RETURN_IF_ERROR(
-      ScalarExpr::Create(texprs[0], RowDescriptor(), planner->GetFragmentState(), &expr));
-  RETURN_IF_ERROR(
-      ScalarExprEvaluator::Create(*expr, state, &pool, &mem_pool, &mem_pool, eval));
-  return Status::OK();
+
+static string BenchmarkName(const string& name, bool codegen) {
+  if (!codegen) {
+    return name;
+  } else {
+    return name + "Codegen";
+  }
 }
 
-// TODO: handle codegen.  Codegen needs a new driver that is also codegen'd.
-static TestData* GenerateBenchmarkExprs(const string& query, bool codegen) {
+static ExprTestData* GenerateBenchmarkExprs(const string& query) {
   stringstream ss;
   ss << "select " << query;
-  TestData* test_data = new TestData;
-  TExecRequest request;
-  ABORT_IF_ERROR(planner->GeneratePlan(ss.str(), &request));
-  ABORT_IF_ERROR(PrepareSelectList(request, &test_data->eval));
-  return test_data;
+  ExprTestData* test_data = nullptr;
+  ABORT_IF_ERROR(planner->PrepareScalarExpression(ss.str(), &test_data));
+  if (test_data == nullptr) {
+    ABORT_WITH_ERROR("Failed to prepare ExprTestData for query '" + ss.str() + "'");
+  } else {
+    return test_data;
+  }
 }
 
 const int ITERATIONS = 256;
 
 // Benchmark driver to run expr multiple times.
 void BenchmarkQueryFn(int batch_size, void* d) {
-  TestData* data = reinterpret_cast<TestData*>(d);
+  ExprTestData* data = reinterpret_cast<ExprTestData*>(d);
   for (int i = 0; i < batch_size; ++i) {
     for (int n = 0; n < ITERATIONS; ++n) {
-      void* value = data->eval->GetValue(NULL);
+      void* value = data->eval_->GetValue(NULL);
       // Dummy result to prevent this from being optimized away
-      data->dummy_result += reinterpret_cast<int64_t>(value);
+      data->dummy_result_ += reinterpret_cast<int64_t>(value);
     }
   }
 }
 
-#define BENCHMARK(name, stmt)\
-  suite->AddBenchmark(name, BenchmarkQueryFn, GenerateBenchmarkExprs(stmt, false))
-// Machine Info: Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
-// Literals:             Function                Rate          Comparison
-// ----------------------------------------------------------------------
-//                            int                2154                  1X
-//                          float                2155              1.001X
-//                         double                2179              1.011X
-//                         string                2179              1.011X
-Benchmark* BenchmarkLiterals() {
-  Benchmark* suite = new Benchmark("Literals");
+#define BENCHMARK(name, stmt) \
+  suite->AddBenchmark(name, BenchmarkQueryFn, GenerateBenchmarkExprs(stmt))
+// Machine Info: Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
+// Literals:                  Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                                 int                700      706      710         1X         1X         1X
+//                               float                397      400      402     0.567X     0.566X     0.567X
+//                              double                396      401      403     0.566X     0.568X     0.568X
+//                              string                668      674      676     0.954X     0.954X     0.952X
+//
+// LiteralsCodegen:           Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                                 int                780      786      790         1X         1X         1X
+//                               float                610      615      617     0.783X     0.783X     0.781X
+//                              double                610      616      619     0.782X     0.784X     0.783X
+//                              string                780      786      790         1X         1X         1X
+Benchmark* BenchmarkLiterals(bool codegen) {
+  Benchmark* suite = new Benchmark(BenchmarkName("Literals", codegen));
   BENCHMARK("int", "1");
   BENCHMARK("float", "1.1f");
   BENCHMARK("double", "1.1");
@@ -175,29 +228,47 @@ Benchmark* BenchmarkLiterals() {
   return suite;
 }
 
-// Arithmetic:           Function                Rate          Comparison
-// ----------------------------------------------------------------------
-//                        int-add               527.5                  1X
-//                     double-add                 528              1.001X
-Benchmark* BenchmarkArithmetic() {
-  Benchmark* suite = new Benchmark("Arithmetic");
+// Arithmetic:                Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                             int-add                319      323      324         1X         1X         1X
+//                          double-add                 40     40.3     40.5     0.125X     0.125X     0.125X
+//
+// ArithmeticCodegen:         Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                             int-add                781      787      791         1X         1X         1X
+//                          double-add                610      617      619     0.781X     0.784X     0.783X
+Benchmark* BenchmarkArithmetic(bool codegen) {
+  Benchmark* suite = new Benchmark(BenchmarkName("Arithmetic", codegen));
   BENCHMARK("int-add", "1 + 2");
   BENCHMARK("double-add", "1.1 + 2.2");
   return suite;
 }
 
-// Machine Info: Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
-// Like:                 Function                Rate          Comparison
-// ----------------------------------------------------------------------
-//                         equals               203.9                  1X
-//                     not equals               426.4              2.091X
-//                         strstr               142.8             0.7001X
-//                       strncmp1               269.7              1.323X
-//                       strncmp2               294.1              1.442X
-//                       strncmp3               775.7              3.804X
-//                          regex                19.7             0.0966X
-Benchmark* BenchmarkLike() {
-  Benchmark* suite = new Benchmark("Like");
+// Like:                      Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                              equals                254      255      257         1X         1X         1X
+//                          not equals                320      322      324      1.26X      1.26X      1.26X
+//                              strstr                106      107      107     0.419X     0.419X     0.418X
+//                            strncmp1                215      216      217     0.848X     0.847X     0.845X
+//                            strncmp2                209      211      211     0.825X     0.825X     0.822X
+//                            strncmp3                254      256      257         1X         1X         1X
+//                               regex               28.1     28.2     28.3     0.111X      0.11X      0.11X
+//
+// LikeCodegen:               Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                              equals                820      827      830         1X         1X         1X
+//                          not equals                824      829      836         1X         1X      1.01X
+//                              strstr                130      131      131     0.158X     0.158X     0.158X
+//                            strncmp1                334      337      339     0.407X     0.408X     0.408X
+//                            strncmp2                355      359      360     0.433X     0.434X     0.434X
+//                            strncmp3                468      472      474     0.571X     0.571X     0.572X
+//                               regex               29.3     29.5     29.6    0.0357X    0.0357X    0.0357X
+Benchmark* BenchmarkLike(bool codegen) {
+  Benchmark* suite = new Benchmark(BenchmarkName("Like", codegen));
   BENCHMARK("equals", "'abcdefghijklmnopqrstuvwxyz' = 'abcdefghijklmnopqrstuvwxyz'");
   BENCHMARK("not equals", "'abcdefghijklmnopqrstuvwxyz' = 'lmnopqrstuvwxyz'");
   BENCHMARK("strstr", "'abcdefghijklmnopqrstuvwxyz' LIKE '%lmnopq%'");
@@ -208,20 +279,35 @@ Benchmark* BenchmarkLike() {
   return suite;
 }
 
-// Cast:                 Function                Rate          Comparison
-// ----------------------------------------------------------------------
-//                     int_to_int                 824                  1X
-//                    int_to_bool                 878              1.066X
-//                  int_to_double               775.4              0.941X
-//                  int_to_string               32.47            0.03941X
-//              double_to_boolean               823.5             0.9994X
-//               double_to_bigint               775.4              0.941X
-//               double_to_string               4.682           0.005682X
-//                  string_to_int               402.6             0.4886X
-//                string_to_float               145.8             0.1769X
-//            string_to_timestamp               83.76             0.1017X
-Benchmark* BenchmarkCast() {
-  Benchmark* suite = new Benchmark("Cast");
+// Cast:                      Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                          int_to_int                334      337      340         1X         1X         1X
+//                         int_to_bool                332      335      338     0.995X     0.994X     0.992X
+//                       int_to_double                700      707      711       2.1X       2.1X      2.09X
+//                       int_to_string                125      126      127     0.374X     0.375X     0.374X
+//                   double_to_boolean                155      156      157     0.464X     0.463X     0.463X
+//                    double_to_bigint                 90     90.6     90.8     0.269X     0.269X     0.267X
+//                    double_to_string                 68     68.8     69.3     0.204X     0.204X     0.204X
+//                       string_to_int                229      231      232     0.684X     0.685X     0.682X
+//                     string_to_float                103      104      105     0.309X     0.308X     0.308X
+//                 string_to_timestamp               39.9     40.1     40.5     0.119X     0.119X     0.119X
+//
+// CastCodegen:               Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                          int_to_int                824      830      837         1X         1X         1X
+//                         int_to_bool                815      821      828     0.989X     0.989X     0.989X
+//                       int_to_double                778      783      789     0.944X     0.943X     0.943X
+//                       int_to_string                167      169      171     0.203X     0.203X     0.204X
+//                   double_to_boolean                819      826      833     0.994X     0.994X     0.995X
+//                    double_to_bigint                777      783      792     0.943X     0.943X     0.946X
+//                    double_to_string                139      140      141     0.168X     0.168X     0.168X
+//                       string_to_int                369      372      375     0.448X     0.448X     0.448X
+//                     string_to_float                123      124      125      0.15X      0.15X      0.15X
+//                 string_to_timestamp               44.8     45.1     45.4    0.0544X    0.0543X    0.0542X
+Benchmark* BenchmarkCast(bool codegen) {
+  Benchmark* suite = new Benchmark(BenchmarkName("Cast", codegen));
   BENCHMARK("int_to_int", "cast(1 as INT)");
   BENCHMARK("int_to_bool", "cast(1 as BOOLEAN)");
   BENCHMARK("int_to_double", "cast(1 as DOUBLE)");
@@ -235,72 +321,178 @@ Benchmark* BenchmarkCast() {
   return suite;
 }
 
-Benchmark* BenchmarkDecimalCast() {
-  Benchmark* suite = new Benchmark("Decimal Casts");
-  BENCHMARK("int_to_decimal4", "cast 12345678 as DECIMAL(9,2)");
-  BENCHMARK("decimal4_to_decimal4", "cast 12345678.5 as DECIMAL(9,2)");
-  BENCHMARK("decimal8_to_decimal4", "cast 12345678.345 as DECIMAL(9,2)");
-  BENCHMARK("decimal16_to_decimal4", "cast 12345678.123456783456789 as DECIMAL(9,2)");
-  BENCHMARK("double_to_decimal4", "cast e() as DECIMAL(9,7)");
-  BENCHMARK("string_to_decimal4", "cast '12345678.123456783456789' as DECIMAL(9,2)");
-  BENCHMARK("int_to_decimal8", "cast 12345678 as DECIMAL(18,2)");
-  BENCHMARK("decimal4_to_decimal8", "cast 12345678.5 as DECIMAL(18,2)");
-  BENCHMARK("decimal8_to_decimal8", "cast 12345678.345 as DECIMAL(18,2)");
-  BENCHMARK("decimal16_to_decimal8", "cast 12345678.123456783456789 as DECIMAL(18,2)");
-  BENCHMARK("double_to_decimal8", "cast e() as DECIMAL(18,7)");
-  BENCHMARK("string_to_decimal8", "cast '12345678.123456783456789' as DECIMAL(18,7)");
-  BENCHMARK("int_to_decimal16", "cast 12345678 as DECIMAL(28,2)");
-  BENCHMARK("decimal4_to_decimal16", "cast 12345678.5 as DECIMAL(28,2)");
-  BENCHMARK("decimal8_to_decimal16", "cast 12345678.345 as DECIMAL(28,2)");
-  BENCHMARK("decimal16_to_decimal16", "cast 12345678.123456783456789 as DECIMAL(28,2)");
-  BENCHMARK("double_to_decimal16", "cast e() as DECIMAL(28,7)");
-  BENCHMARK("string_to_decimal16", "cast '12345678.123456783456789' as DECIMAL(28,7)");
-  BENCHMARK("decimal4_to_tinyint", "cast 78.5 as TINYINT");
-  BENCHMARK("decimal8_to_tinyint", "cast 0.12345678345 as TINYINT");
-  BENCHMARK("decimal16_to_tinyint", "cast 78.12345678123456783456789 as TINYINT");
-  BENCHMARK("decimal4_to_smallint", "cast 78.5 as SMALLINT");
-  BENCHMARK("decimal8_to_smallint", "cast 0.12345678345 as SMALLINT");
-  BENCHMARK("decimal16_to_smallint", "cast 78.12345678123456783456789 as SMALLINT");
-  BENCHMARK("decimal4_to_int", "cast 12345678.5 as INT");
-  BENCHMARK("decimal8_to_int", "cast 12345678.345 as INT");
-  BENCHMARK("decimal16_to_int", "cast 12345678.123456783456789 as INT");
-  BENCHMARK("decimal4_to_bigint", "cast 12345678.5 as BIGINT");
-  BENCHMARK("decimal8_to_bigint", "cast 12345678.345 as BIGINT");
-  BENCHMARK("decimal16_to_bigint", "cast 12345678.123456783456789 as BIGINT");
-  BENCHMARK("decimal4_to_float", "cast 12345678.5 as FLOAT");
-  BENCHMARK("decimal8_to_float", "cast 12345678.345 as FLOAT");
-  BENCHMARK("decimal16_to_float", "cast 12345678.123456783456789 as FLOAT");
-  BENCHMARK("decimal4_to_double", "cast 12345678.5 as DOUBLE");
-  BENCHMARK("decimal8_to_double", "cast 12345678.345 as DOUBLE");
-  BENCHMARK("decimal16_to_double", "cast 12345678.123456783456789 as DOUBLE");
-  BENCHMARK("decimal4_to_string", "cast 12345678.5 as STRING");
-  BENCHMARK("decimal8_to_string", "cast 12345678.345 as STRING");
-  BENCHMARK("decimal16_to_string", "cast 12345678.123456783456789 as STRING");
+// DecimalCasts:              Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                     int_to_decimal4                104      105      105         1X         1X         1X
+//                decimal4_to_decimal4                396      399      402       3.8X       3.8X      3.82X
+//                decimal8_to_decimal4                 44       44     44.4     0.422X      0.42X     0.421X
+//               decimal16_to_decimal4               31.3     31.6     31.7       0.3X     0.301X     0.301X
+//                  double_to_decimal4               58.4     58.9     59.5      0.56X     0.562X     0.565X
+//                  string_to_decimal4               50.9     51.1     51.4     0.488X     0.488X     0.488X
+//                     int_to_decimal8                114      115      116      1.09X       1.1X       1.1X
+//                decimal4_to_decimal8               51.3     51.6     52.1     0.492X     0.492X     0.494X
+//                decimal8_to_decimal8                 44     44.4     44.6     0.422X     0.423X     0.423X
+//               decimal16_to_decimal8               31.6     31.9       32     0.303X     0.304X     0.303X
+//                  double_to_decimal8               60.6     60.8     61.1     0.582X     0.581X      0.58X
+//                  string_to_decimal8               43.1     43.6       44     0.414X     0.416X     0.417X
+//                    int_to_decimal16                110      112      113      1.06X      1.07X      1.07X
+//               decimal4_to_decimal16               36.9       37     37.3     0.353X     0.353X     0.353X
+//               decimal8_to_decimal16               43.1     43.5     43.8     0.414X     0.415X     0.415X
+//              decimal16_to_decimal16               31.7     31.8     31.9     0.304X     0.303X     0.303X
+//                 double_to_decimal16               54.2     54.5     54.7      0.52X      0.52X     0.519X
+//                 string_to_decimal16               27.2     27.2     27.4     0.261X      0.26X      0.26X
+//                 decimal4_to_tinyint               89.6     90.3       91      0.86X     0.862X     0.864X
+//                 decimal8_to_tinyint               75.9     76.1     76.3     0.728X     0.726X     0.724X
+//                decimal16_to_tinyint               50.1     50.1     50.5      0.48X     0.478X     0.479X
+//                decimal4_to_smallint               85.6     85.9     86.4     0.821X      0.82X     0.819X
+//                decimal8_to_smallint               77.2     77.6     77.8      0.74X      0.74X     0.738X
+//               decimal16_to_smallint               50.5     50.6     50.9     0.484X     0.483X     0.482X
+//                     decimal4_to_int               86.3     86.6     87.7     0.828X     0.826X     0.832X
+//                     decimal8_to_int               76.9     77.1     77.5     0.738X     0.736X     0.735X
+//                    decimal16_to_int               56.2     56.4     56.6     0.539X     0.538X     0.537X
+//                  decimal4_to_bigint               89.6     89.8     90.4      0.86X     0.857X     0.857X
+//                  decimal8_to_bigint               74.7     74.9     75.3     0.717X     0.715X     0.714X
+//                 decimal16_to_bigint               57.2     57.2     57.5     0.549X     0.546X     0.546X
+//                   decimal4_to_float                700      705      712      6.71X      6.73X      6.75X
+//                   decimal8_to_float                700      704      711      6.72X      6.72X      6.74X
+//                  decimal16_to_float                703      704      711      6.74X      6.72X      6.74X
+//                  decimal4_to_double                700      709      712      6.72X      6.76X      6.75X
+//                  decimal8_to_double                701      708      715      6.72X      6.76X      6.78X
+//                 decimal16_to_double                702      705      712      6.73X      6.73X      6.75X
+//                  decimal4_to_string               54.5       55     55.4     0.523X     0.525X     0.525X
+//                  decimal8_to_string               53.3       54     54.4     0.512X     0.515X     0.516X
+//                 decimal16_to_string               5.81     5.87     5.87    0.0557X     0.056X    0.0556X
+//
+// DecimalCastsCodegen:       Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                     int_to_decimal4                610      614      618         1X         1X         1X
+//                decimal4_to_decimal4                608      615      618     0.996X         1X         1X
+//                decimal8_to_decimal4                610      616      619         1X         1X         1X
+//               decimal16_to_decimal4                610      613      617         1X     0.999X     0.998X
+//                  double_to_decimal4                608      613      617     0.997X     0.998X     0.998X
+//                  string_to_decimal4               83.2     83.5     84.1     0.136X     0.136X     0.136X
+//                     int_to_decimal8                638      645      647      1.05X      1.05X      1.05X
+//                decimal4_to_decimal8                638      642      648      1.05X      1.05X      1.05X
+//                decimal8_to_decimal8                636      645      647      1.04X      1.05X      1.05X
+//               decimal16_to_decimal8                639      642      645      1.05X      1.04X      1.04X
+//                  double_to_decimal8                637      642      647      1.04X      1.05X      1.05X
+//                  string_to_decimal8               79.9     82.5       83     0.131X     0.134X     0.134X
+//                    int_to_decimal16                427      430      434       0.7X       0.7X     0.702X
+//               decimal4_to_decimal16                426      431      433     0.698X     0.702X     0.701X
+//               decimal8_to_decimal16                428      430      434     0.702X     0.701X     0.702X
+//              decimal16_to_decimal16                426      431      435     0.698X     0.702X     0.703X
+//                 double_to_decimal16                427      431      434       0.7X     0.702X     0.702X
+//                 string_to_decimal16               36.7     36.9     37.1    0.0601X      0.06X      0.06X
+//                 decimal4_to_tinyint                777      782      790      1.27X      1.27X      1.28X
+//                 decimal8_to_tinyint                777      785      791      1.27X      1.28X      1.28X
+//                decimal16_to_tinyint                778      784      788      1.28X      1.28X      1.27X
+//                decimal4_to_smallint                776      781      790      1.27X      1.27X      1.28X
+//                decimal8_to_smallint                778      787      790      1.28X      1.28X      1.28X
+//               decimal16_to_smallint                777      783      791      1.27X      1.28X      1.28X
+//                     decimal4_to_int                824      832      836      1.35X      1.35X      1.35X
+//                     decimal8_to_int                823      831      837      1.35X      1.35X      1.35X
+//                    decimal16_to_int                819      825      832      1.34X      1.34X      1.35X
+//                  decimal4_to_bigint                777      783      790      1.27X      1.28X      1.28X
+//                  decimal8_to_bigint                778      786      789      1.28X      1.28X      1.28X
+//                 decimal16_to_bigint                780      783      791      1.28X      1.28X      1.28X
+//                   decimal4_to_float                778      784      790      1.28X      1.28X      1.28X
+//                   decimal8_to_float                778      782      791      1.28X      1.27X      1.28X
+//                  decimal16_to_float                778      785      790      1.28X      1.28X      1.28X
+//                  decimal4_to_double                777      784      789      1.27X      1.28X      1.28X
+//                  decimal8_to_double                777      784      791      1.27X      1.28X      1.28X
+//                 decimal16_to_double                778      784      790      1.28X      1.28X      1.28X
+//                  decimal4_to_string                121      122      124     0.199X     0.199X       0.2X
+//                  decimal8_to_string                121      122      123     0.198X     0.198X     0.199X
+//                 decimal16_to_string               8.42     8.49     8.49    0.0138X    0.0138X    0.0137X
+Benchmark* BenchmarkDecimalCast(bool codegen) {
+  Benchmark* suite = new Benchmark(BenchmarkName("DecimalCasts", codegen));
+  BENCHMARK("int_to_decimal4", "cast(12345678 as DECIMAL(9,1))");
+  BENCHMARK("decimal4_to_decimal4", "cast(12345678.5 as DECIMAL(9,1))");
+  BENCHMARK("decimal8_to_decimal4", "cast(12345678.345 as DECIMAL(9,1))");
+  BENCHMARK("decimal16_to_decimal4", "cast(12345678.123456783456789 as DECIMAL(9,1))");
+  BENCHMARK("double_to_decimal4", "cast(e() as DECIMAL(9,7))");
+  BENCHMARK("string_to_decimal4", "cast('12345678.123456783456789' as DECIMAL(9,1))");
+  BENCHMARK("int_to_decimal8", "cast(12345678 as DECIMAL(18,2))");
+  BENCHMARK("decimal4_to_decimal8", "cast(12345678.5 as DECIMAL(18,2))");
+  BENCHMARK("decimal8_to_decimal8", "cast(12345678.345 as DECIMAL(18,2))");
+  BENCHMARK("decimal16_to_decimal8", "cast(12345678.123456783456789 as DECIMAL(18,2))");
+  BENCHMARK("double_to_decimal8", "cast(e() as DECIMAL(18,7))");
+  BENCHMARK("string_to_decimal8", "cast('12345678.123456783456789' as DECIMAL(18,7))");
+  BENCHMARK("int_to_decimal16", "cast(12345678 as DECIMAL(28,2))");
+  BENCHMARK("decimal4_to_decimal16", "cast(12345678.5 as DECIMAL(28,2))");
+  BENCHMARK("decimal8_to_decimal16", "cast(12345678.345 as DECIMAL(28,2))");
+  BENCHMARK("decimal16_to_decimal16", "cast(12345678.123456783456789 as DECIMAL(28,2))");
+  BENCHMARK("double_to_decimal16", "cast(e() as DECIMAL(28,7))");
+  BENCHMARK("string_to_decimal16", "cast('12345678.123456783456789' as DECIMAL(28,7))");
+  BENCHMARK("decimal4_to_tinyint", "cast(78.5 as TINYINT)");
+  BENCHMARK("decimal8_to_tinyint", "cast(0.12345678345 as TINYINT)");
+  BENCHMARK("decimal16_to_tinyint", "cast(78.12345678123456783456789 as TINYINT)");
+  BENCHMARK("decimal4_to_smallint", "cast(78.5 as SMALLINT)");
+  BENCHMARK("decimal8_to_smallint", "cast(0.12345678345 as SMALLINT)");
+  BENCHMARK("decimal16_to_smallint", "cast(78.12345678123456783456789 as SMALLINT)");
+  BENCHMARK("decimal4_to_int", "cast(12345678.5 as INT)");
+  BENCHMARK("decimal8_to_int", "cast(12345678.345 as INT)");
+  BENCHMARK("decimal16_to_int", "cast(12345678.123456783456789 as INT)");
+  BENCHMARK("decimal4_to_bigint", "cast(12345678.5 as BIGINT)");
+  BENCHMARK("decimal8_to_bigint", "cast(12345678.345 as BIGINT)");
+  BENCHMARK("decimal16_to_bigint", "cast(12345678.123456783456789 as BIGINT)");
+  BENCHMARK("decimal4_to_float", "cast(12345678.5 as FLOAT)");
+  BENCHMARK("decimal8_to_float", "cast(12345678.345 as FLOAT)");
+  BENCHMARK("decimal16_to_float", "cast(12345678.123456783456789 as FLOAT)");
+  BENCHMARK("decimal4_to_double", "cast(12345678.5 as DOUBLE)");
+  BENCHMARK("decimal8_to_double", "cast(12345678.345 as DOUBLE)");
+  BENCHMARK("decimal16_to_double", "cast(12345678.123456783456789 as DOUBLE)");
+  BENCHMARK("decimal4_to_string", "cast(12345678.5 as STRING)");
+  BENCHMARK("decimal8_to_string", "cast(12345678.345 as STRING)");
+  BENCHMARK("decimal16_to_string", "cast(12345678.123456783456789 as STRING)");
   return suite;
 }
 
-// ConditionalFunctions: Function                Rate          Comparison
-// ----------------------------------------------------------------------
-//                       not_null               877.8                  1X
-//                        is null               938.3              1.069X
-//                       compound               240.2             0.2736X
-//                    int_between                 191             0.2176X
-//              timestamp_between                18.5            0.02108X
-//                 string_between               93.94              0.107X
-//                        bool_in               356.6             0.4063X
-//                         int_in               209.7             0.2389X
-//                       float_in               216.4             0.2465X
-//                      string_in               120.1             0.1368X
-//                   timestamp_in               19.79            0.02255X
-//                         if_int               506.8             0.5773X
-//                      if_string               470.6             0.5361X
-//                   if_timestamp               70.19            0.07996X
-//                  coalesce_bool               194.2             0.2213X
-//                       case_int                 259             0.2951X
-Benchmark* BenchmarkConditionalFunctions() {
-// TODO: expand these cases when the parser issues are fixed (see corresponding tests
-// in expr-test).
-  Benchmark* suite = new Benchmark("ConditionalFunctions");
+// ConditionalFn:             Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                            not_null                353      357      359         1X         1X         1X
+//                             is null                334      337      340     0.946X     0.944X     0.947X
+//                            compound                300      303      305     0.851X     0.849X      0.85X
+//                         int_between                154      155      156     0.437X     0.435X     0.436X
+//                   timestamp_between               8.79     8.87     8.87    0.0249X    0.0248X    0.0247X
+//                      string_between                128      129      130     0.364X     0.361X     0.362X
+//                             bool_in                249      251      253     0.706X     0.703X     0.705X
+//                              int_in                247      248      249     0.699X     0.695X     0.695X
+//                            float_in                227      228      230     0.643X     0.638X      0.64X
+//                           string_in                161      162      163     0.456X     0.453X     0.455X
+//                        timestamp_in               9.35     9.35     9.35    0.0265X    0.0262X    0.0261X
+//                              if_int                401      404      407      1.14X      1.13X      1.13X
+//                           if_string                363      366      369      1.03X      1.03X      1.03X
+//                        if_timestamp               37.9     38.2     38.3     0.107X     0.107X     0.107X
+//                       coalesce_bool                201      202      204     0.569X     0.567X     0.568X
+//                            case_int                104      105      106     0.295X     0.294X     0.295X
+//
+// ConditionalFnCodegen:      Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                            not_null                822      828      835         1X         1X         1X
+//                             is null                819      824      829     0.996X     0.995X     0.993X
+//                            compound                820      827      832     0.997X     0.998X     0.997X
+//                         int_between                819      826      832     0.996X     0.997X     0.997X
+//                   timestamp_between               11.4     11.4     11.5    0.0138X    0.0138X    0.0137X
+//                      string_between                825      831      836         1X         1X         1X
+//                             bool_in                474      477      482     0.577X     0.576X     0.577X
+//                              int_in                561      566      570     0.682X     0.684X     0.682X
+//                            float_in                563      565      569     0.684X     0.683X     0.682X
+//                           string_in                352      355      357     0.428X     0.429X     0.428X
+//                        timestamp_in               11.9       12       12    0.0144X    0.0145X    0.0144X
+//                              if_int                777      783      789     0.945X     0.945X     0.945X
+//                           if_string                778      783      789     0.947X     0.946X     0.945X
+//                        if_timestamp                 45     45.2     45.4    0.0547X    0.0546X    0.0544X
+//                       coalesce_bool                823      828      835         1X         1X         1X
+//                            case_int                771      776      781     0.937X     0.937X     0.935X
+Benchmark* BenchmarkConditionalFunctions(bool codegen) {
+  // TODO: expand these cases when the parser issues are fixed (see corresponding tests
+  // in expr-test).
+  Benchmark* suite = new Benchmark(BenchmarkName("ConditionalFn", codegen));
   BENCHMARK("not_null", "!NULL");
   BENCHMARK("is null", "5 IS NOT NULL");
   BENCHMARK("compound", "(TRUE && TRUE) || FALSE");
@@ -326,36 +518,67 @@ Benchmark* BenchmarkConditionalFunctions() {
   return suite;
 }
 
-// StringFunctions:      Function                Rate          Comparison
-// ----------------------------------------------------------------------
-//                         length               920.2                  1X
-//                     substring1               351.4             0.3819X
-//                     substring2               327.9             0.3563X
-//                           left               508.6             0.5527X
-//                          right               508.2             0.5522X
-//                          lower               103.9             0.1129X
-//                          upper               103.2             0.1121X
-//                        reverse               324.9             0.3531X
-//                           trim               421.2             0.4578X
-//                          ltrim               526.6             0.5723X
-//                          rtrim               566.5             0.6156X
-//                          space               94.63             0.1028X
-//                          ascii                1048              1.139X
-//                          instr               175.6             0.1909X
-//                         locate               184.7             0.2007X
-//                        locate2               175.8             0.1911X
-//                         concat               109.5              0.119X
-//                        concat2               75.83            0.08241X
-//                       concatws               143.4             0.1559X
-//                      concatws2               70.38            0.07649X
-//                         repeat               98.54             0.1071X
-//                           lpad               154.7             0.1681X
-//                           rpad               145.6             0.1582X
-//                    find_in_set               83.38            0.09061X
-//                 regexp_extract                6.42           0.006977X
-//                 regexp_replace              0.7435           0.000808X
-Benchmark* BenchmarkStringFunctions() {
-  Benchmark* suite = new Benchmark("StringFunctions");
+// StringFn:                  Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                              length                209      210      212         1X         1X         1X
+//                          substring1                153      153      154      0.73X     0.729X     0.727X
+//                          substring2                173      174      176     0.827X     0.826X      0.83X
+//                                left                159      160      161     0.763X     0.762X     0.758X
+//                               right                160      160      161     0.764X     0.763X     0.758X
+//                               lower               74.9     75.6     76.3     0.358X      0.36X      0.36X
+//                               upper               76.5     77.4       78     0.366X     0.369X     0.368X
+//                             reverse                108      109      110     0.515X     0.519X      0.52X
+//                                trim                194      195      197      0.93X      0.93X     0.929X
+//                               ltrim                217      218      221      1.04X      1.04X      1.04X
+//                               rtrim                217      220      221      1.04X      1.05X      1.04X
+//                               space                147      148      149     0.702X     0.704X     0.703X
+//                               ascii                294      296      298      1.41X      1.41X      1.41X
+//                               instr               95.1     95.5     96.5     0.455X     0.455X     0.455X
+//                              locate               93.7     94.1     94.6     0.448X     0.448X     0.446X
+//                             locate2               98.8       99     99.5     0.473X     0.471X     0.469X
+//                              concat                129      130      131     0.616X     0.618X     0.618X
+//                             concat2               99.4      100      102     0.475X     0.478X     0.479X
+//                            concatws                262      264      267      1.25X      1.26X      1.26X
+//                           concatws2               97.5     98.4     99.2     0.467X     0.468X     0.468X
+//                              repeat               83.8     84.9     85.6     0.401X     0.404X     0.403X
+//                                lpad                 81     81.7     82.2     0.387X     0.389X     0.388X
+//                                rpad               81.5     82.4     82.7      0.39X     0.392X      0.39X
+//                         find_in_set                140      142      143      0.67X     0.674X     0.673X
+//                      regexp_extract               19.9     20.1     20.1    0.0953X    0.0957X    0.0949X
+//                      regexp_replace               1.43     1.44     1.44   0.00686X   0.00687X    0.0068X
+//
+// StringFnCodegen:           Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                              length                826      834      836         1X         1X         1X
+//                          substring1                297      300      302      0.36X      0.36X     0.362X
+//                          substring2                777      785      790     0.941X     0.942X     0.945X
+//                                left                296      299      301     0.359X     0.359X      0.36X
+//                               right                297      300      303      0.36X     0.359X     0.362X
+//                               lower                102      103      104     0.123X     0.123X     0.125X
+//                               upper                105      106      107     0.127X     0.127X     0.128X
+//                             reverse                161      165      168     0.194X     0.198X       0.2X
+//                                trim                425      427      432     0.514X     0.513X     0.517X
+//                               ltrim                561      564      569     0.679X     0.677X     0.681X
+//                               rtrim                584      587      594     0.707X     0.705X     0.711X
+//                               space                213      215      217     0.258X     0.258X      0.26X
+//                               ascii                822      829      836     0.996X     0.994X         1X
+//                               instr                215      217      219     0.261X      0.26X     0.262X
+//                              locate                214      217      218     0.259X      0.26X     0.261X
+//                             locate2                226      228      230     0.274X     0.274X     0.275X
+//                              concat                210      214      216     0.254X     0.257X     0.258X
+//                             concat2                189      191      193     0.229X      0.23X     0.231X
+//                            concatws                777      784      790     0.941X     0.941X     0.945X
+//                           concatws2                160      162      163     0.194X     0.194X     0.196X
+//                              repeat                159      161      164     0.193X     0.194X     0.196X
+//                                lpad                212      214      216     0.257X     0.257X     0.258X
+//                                rpad                212      214      216     0.257X     0.257X     0.259X
+//                         find_in_set                276      278      280     0.334X     0.333X     0.335X
+//                      regexp_extract               20.4     20.5     20.8    0.0247X    0.0246X    0.0248X
+//                      regexp_replace               1.43     1.47     1.47   0.00174X   0.00176X   0.00176X
+Benchmark* BenchmarkStringFunctions(bool codegen) {
+  Benchmark* suite = new Benchmark(BenchmarkName("StringFn", codegen));
   BENCHMARK("length", "length('Hello World!')");
   BENCHMARK("substring1", "substring('Hello World!', 5)");
   BENCHMARK("substring2", "substring('Hello World!', 5, 5)");
@@ -385,18 +608,31 @@ Benchmark* BenchmarkStringFunctions() {
   return suite;
 }
 
-// UrlFunctions:         Function                Rate          Comparison
-// ----------------------------------------------------------------------
-//                      authority               118.1                  1X
-//                           file               95.52              0.809X
-//                           host               94.52             0.8005X
-//                           path               98.63             0.8353X
-//                       protocol               36.29             0.3073X
-//                           user               121.1              1.026X
-//                      user_info               121.4              1.029X
-//                     query_name               41.34             0.3501X
-Benchmark* BenchmarkUrlFunctions() {
-  Benchmark* suite = new Benchmark("UrlFunctions");
+// UrlFn:                     Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                           authority                113      114      114         1X         1X         1X
+//                                file               93.7     94.3     94.6     0.829X     0.828X     0.827X
+//                                host               90.2     90.6       91     0.798X     0.797X     0.796X
+//                                path                104      105      106     0.924X     0.924X     0.923X
+//                            protocol                112      112      113     0.989X     0.988X     0.986X
+//                                user                105      105      106     0.925X     0.924X     0.923X
+//                           user_info               93.2     93.8     94.2     0.825X     0.825X     0.823X
+//                          query_name               44.4     44.5     44.8     0.393X     0.391X     0.392X
+//
+// UrlFnCodegen:              Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                           authority                158      159      160         1X         1X         1X
+//                                file                123      124      125      0.78X      0.78X     0.781X
+//                                host                132      133      133     0.832X     0.834X     0.835X
+//                                path                142      143      144     0.899X     0.899X     0.899X
+//                            protocol                159      160      160      1.01X         1X         1X
+//                                user                138      139      139     0.871X     0.871X     0.871X
+//                           user_info                143      144      144     0.902X     0.902X     0.901X
+//                          query_name               49.9     50.1     50.3     0.316X     0.315X     0.315X
+Benchmark* BenchmarkUrlFunctions(bool codegen) {
+  Benchmark* suite = new Benchmark(BenchmarkName("UrlFn", codegen));
   BENCHMARK("authority", "parse_url('http://user:pass@example.com:80/docs/books/tutorial/"
       "index.html?name=networking#DOWNLOADING', 'AUTHORITY')");
   BENCHMARK("file", "parse_url('http://example.com/docs/books/tutorial/"
@@ -405,7 +641,8 @@ Benchmark* BenchmarkUrlFunctions() {
       "index.html?name=networking#DOWNLOADING', 'HOST')");
   BENCHMARK("path", "parse_url('http://user:pass@example.com/docs/books/tutorial/"
       "index.html?name=networking#DOWNLOADING', 'PATH')");
-  BENCHMARK("protocol", "parse_url('user:pass@example.com/docs/books/tutorial/"
+  BENCHMARK("protocol",
+      "parse_url('http://user:pass@example.com/docs/books/tutorial/"
       "index.html?name=networking#DOWNLOADING', 'PROTOCOL')");
   BENCHMARK("user", "parse_url('http://user@example.com/docs/books/tutorial/"
         "index.html?name=networking#DOWNLOADING', 'USERINFO')");
@@ -416,42 +653,79 @@ Benchmark* BenchmarkUrlFunctions() {
   return suite;
 }
 
-// MathFunctions:        Function                Rate          Comparison
-// ----------------------------------------------------------------------
-//                             pi                1642                  1X
-//                              e                1546             0.9416X
-//                            abs                 877             0.5342X
-//                             ln               110.7            0.06744X
-//                          log10               88.48             0.0539X
-//                           log2               108.3            0.06597X
-//                            log               55.61            0.03387X
-//                            pow               53.93            0.03285X
-//                           sqrt               629.6             0.3835X
-//                           sign                 732             0.4459X
-//                            sin               176.3             0.1074X
-//                           asin               169.6             0.1033X
-//                            cos               156.3             0.0952X
-//                           acos               167.5              0.102X
-//                            tan               176.3             0.1074X
-//                           atan               153.8            0.09371X
-//                        radians               601.5             0.3664X
-//                        degrees               601.5             0.3664X
-//                            bin                  45            0.02741X
-//                       pmod_int               147.3            0.08976X
-//                     pmod_float               172.9             0.1053X
-//                       positive                 877             0.5342X
-//                       negative               936.9             0.5707X
-//                           ceil               466.7             0.2843X
-//                          floor               390.9             0.2381X
-//                          round               820.5             0.4998X
-//                         round2               220.2             0.1341X
-//                        hex_int               5.745             0.0035X
-//                     hex_string               4.441           0.002705X
-//                          unhex               3.394           0.002067X
-//                       conv_int               33.15            0.02019X
-//                    conv_string                36.6            0.02229X
-Benchmark* BenchmarkMathFunctions() {
-  Benchmark* suite = new Benchmark("MathFunctions");
+// MathFn:                    Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                                  pi                329      330      334         1X         1X         1X
+//                                   e                339      343      346      1.03X      1.04X      1.04X
+//                                 abs                144      145      146     0.438X     0.438X     0.437X
+//                                  ln                126      127      128     0.383X     0.385X     0.384X
+//                               log10                116      116      118     0.352X     0.351X     0.352X
+//                                log2                131      131      132     0.397X     0.397X     0.394X
+//                                 log               85.6     85.9     86.2      0.26X      0.26X     0.258X
+//                                 pow               62.7     62.9     63.2     0.191X      0.19X     0.189X
+//                                sqrt                315      318      320     0.957X     0.962X     0.958X
+//                                sign                320      324      325     0.972X     0.981X     0.973X
+//                                 sin                146      147      148     0.443X     0.444X     0.444X
+//                                asin                244      247      250     0.741X     0.747X     0.748X
+//                                 cos                134      135      136     0.407X     0.407X     0.407X
+//                                acos                250      251      255     0.759X      0.76X     0.762X
+//                                 tan                151      152      154     0.459X     0.459X      0.46X
+//                                atan                136      137      138     0.414X     0.415X     0.413X
+//                             radians                331      334      336         1X      1.01X         1X
+//                             degrees                310      312      315     0.942X     0.943X     0.943X
+//                                 bin               94.7     95.7     96.1     0.288X      0.29X     0.288X
+//                            pmod_int                118      118      120     0.359X     0.358X     0.359X
+//                          pmod_float                121      121      122     0.367X     0.367X     0.366X
+//                            positive                308      310      313     0.937X     0.938X     0.936X
+//                            negative                322      326      328     0.978X     0.986X     0.981X
+//                                ceil               62.1     62.3       63     0.189X     0.189X     0.189X
+//                               floor               58.3     58.6     58.9     0.177X     0.177X     0.176X
+//                               round               60.6     61.1     61.4     0.184X     0.185X     0.184X
+//                              round2               57.7     58.4     58.7     0.175X     0.177X     0.176X
+//                             hex_int                8.6     8.68     8.68    0.0262X    0.0263X     0.026X
+//                          hex_string               6.42     6.42     6.52    0.0195X    0.0194X    0.0195X
+//                               unhex               4.81     4.81     4.81    0.0146X    0.0146X    0.0144X
+//                            conv_int               57.8     58.2     58.5     0.176X     0.176X     0.175X
+//                         conv_string               58.4     58.9     59.3     0.177X     0.178X     0.178X
+//
+// MathFnCodegen:             Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                                  pi                777      786      791         1X         1X         1X
+//                                   e                778      783      791         1X     0.996X         1X
+//                                 abs                609      615      620     0.784X     0.782X     0.783X
+//                                  ln                778      785      789         1X     0.999X     0.998X
+//                               log10                778      783      793         1X     0.996X         1X
+//                                log2                778      782      790         1X     0.995X     0.999X
+//                                 log                777      785      787         1X     0.998X     0.995X
+//                                 pow                777      784      790     0.999X     0.997X     0.999X
+//                                sqrt                779      783      791         1X     0.996X         1X
+//                                sign                777      786      791         1X         1X         1X
+//                                 sin                778      784      790         1X     0.997X     0.999X
+//                                asin                379      382      386     0.487X     0.487X     0.488X
+//                                 cos                778      784      791         1X     0.998X         1X
+//                                acos                391      393      397     0.503X       0.5X     0.502X
+//                                 tan                778      785      790         1X     0.999X     0.999X
+//                                atan                216      218      219     0.278X     0.277X     0.277X
+//                             radians                777      784      790     0.999X     0.998X     0.998X
+//                             degrees                779      784      789         1X     0.997X     0.998X
+//                                 bin                166      168      170     0.214X     0.214X     0.215X
+//                            pmod_int                777      784      789         1X     0.997X     0.997X
+//                          pmod_float                778      783      792         1X     0.996X         1X
+//                            positive                778      783      792         1X     0.996X         1X
+//                            negative                778      782      790         1X     0.995X     0.999X
+//                                ceil                609      614      620     0.784X     0.781X     0.783X
+//                               floor                608      614      619     0.782X     0.781X     0.782X
+//                               round                610      612      617     0.785X     0.778X      0.78X
+//                              round2                608      613      619     0.782X     0.781X     0.782X
+//                             hex_int               8.79     8.87     8.87    0.0113X    0.0113X    0.0112X
+//                          hex_string               6.74     6.79     6.79   0.00868X   0.00864X   0.00859X
+//                               unhex                  5        5        5   0.00643X   0.00636X   0.00632X
+//                            conv_int                170      171      173     0.219X     0.218X     0.219X
+//                         conv_string                189      191      193     0.243X     0.243X     0.244X
+Benchmark* BenchmarkMathFunctions(bool codegen) {
+  Benchmark* suite = new Benchmark(BenchmarkName("MathFn", codegen));
   BENCHMARK("pi", "pi()");
   BENCHMARK("e", "e()");
   BENCHMARK("abs", "abs(-1.0)");
@@ -487,37 +761,77 @@ Benchmark* BenchmarkMathFunctions() {
   return suite;
 }
 
-// TimestampFunctions:   Function                Rate          Comparison
-// ----------------------------------------------------------------------
-//                        literal               68.18                  1X
-//                      to_string               1.131            0.01659X
-//                       add_year               34.57              0.507X
-//                      sub_month               33.04             0.4846X
-//                      add_weeks               56.15             0.8236X
-//                       sub_days               57.21             0.8391X
-//                            add               55.85             0.8191X
-//                      sub_hours               44.44             0.6519X
-//                    add_minutes               43.96             0.6448X
-//                    sub_seconds               42.78             0.6274X
-//                      add_milli               43.43             0.6371X
-//                      sub_micro               43.88             0.6436X
-//                       add_nano               41.83             0.6135X
-//                unix_timestamp1               32.74             0.4803X
-//                unix_timestamp2               39.39             0.5778X
-//                     from_unix1               1.192            0.01748X
-//                     from_unix2               1.602             0.0235X
-//                           year                73.4              1.077X
-//                          month               72.53              1.064X
-//                   day of month               71.98              1.056X
-//                    day of year               56.67             0.8312X
-//                   week of year               50.68             0.7433X
-//                           hour               100.1              1.468X
-//                         minute               97.18              1.425X
-//                         second                96.7              1.418X
-//                        to date               3.075            0.04511X
-//                      date diff               39.54             0.5799X
-Benchmark* BenchmarkTimestampFunctions() {
-  Benchmark* suite = new Benchmark("TimestampFunctions");
+// TimestampFn:               Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                             literal               34.4     34.6     34.8         1X         1X         1X
+//                           to_string               2.09     2.12     2.12    0.0609X    0.0611X    0.0607X
+//                            add_year               16.7     16.7     16.8     0.485X     0.481X     0.482X
+//                           sub_month               16.5     16.5     16.6      0.48X     0.476X     0.477X
+//                           add_weeks               20.9     20.9     21.1     0.609X     0.604X     0.605X
+//                            sub_days               19.7     19.7     19.8     0.574X      0.57X     0.569X
+//                                 add               20.7     20.9     21.1     0.604X     0.604X     0.605X
+//                           sub_hours               19.4     19.5     19.6     0.563X     0.564X     0.563X
+//                         add_minutes               19.9     19.9       20      0.58X     0.575X     0.575X
+//                         sub_seconds               19.9     19.9       20      0.58X     0.575X     0.574X
+//                           add_milli               18.3     18.3     18.5     0.534X     0.529X      0.53X
+//                           sub_micro               18.3     18.3     18.5     0.534X     0.529X      0.53X
+//                            add_nano               18.7     18.9       19     0.544X     0.545X     0.546X
+//                     unix_timestamp1               38.7     38.9     39.1      1.13X      1.12X      1.12X
+//                     unix_timestamp2                 53     53.3     53.5      1.54X      1.54X      1.54X
+//                          from_unix1               6.11     6.11     6.19     0.178X     0.176X     0.178X
+//                          from_unix2               10.7     10.9     11.2     0.312X     0.316X     0.321X
+//                                year               38.9     39.1     39.3      1.13X      1.13X      1.13X
+//                               month               39.1     39.3     39.5      1.14X      1.13X      1.13X
+//                        day of month               38.7     38.7     38.9      1.13X      1.12X      1.12X
+//                         day of year               34.6     34.8     34.8      1.01X      1.01X         1X
+//                        week of year               33.3     33.6     33.8      0.97X     0.971X      0.97X
+//                                hour               76.7     77.4     78.4      2.23X      2.24X      2.25X
+//                              minute               76.5       77     78.1      2.23X      2.22X      2.24X
+//                              second               74.6     75.4     76.4      2.17X      2.18X      2.19X
+//                             to date                 19     19.1     19.2     0.554X     0.551X     0.552X
+//                           date diff               17.5     17.5     17.6     0.509X     0.505X     0.505X
+//                            from utc               22.1     22.4     22.4     0.644X     0.646X     0.644X
+//                              to utc               18.9     18.9       19      0.55X     0.545X     0.546X
+//                                 now                290      293      295      8.44X      8.47X      8.48X
+//                      unix_timestamp                209      211      213      6.09X      6.08X      6.11X
+//
+// TimestampFnCodegen:        Function  iters/ms   10%ile   50%ile   90%ile     10%ile     50%ile     90%ile
+//                                                                          (relative) (relative) (relative)
+// ---------------------------------------------------------------------------------------------------------
+//                             literal               37.2     37.4     37.5         1X         1X         1X
+//                           to_string               2.14     2.16     2.16    0.0576X    0.0577X    0.0575X
+//                            add_year               18.5     18.5     18.7     0.498X     0.495X     0.497X
+//                           sub_month               18.3     18.3     18.5     0.493X      0.49X     0.492X
+//                           add_weeks               23.9       24     24.1     0.641X     0.641X     0.641X
+//                            sub_days               22.1     22.1     22.3     0.595X     0.592X     0.593X
+//                                 add               23.6     23.6     23.8     0.634X     0.631X     0.634X
+//                           sub_hours               21.9     21.9       22      0.59X     0.587X     0.587X
+//                         add_minutes               22.4     22.6     22.7     0.602X     0.604X     0.606X
+//                         sub_seconds               22.4     22.4     22.6     0.602X     0.599X     0.602X
+//                           add_milli               20.6     20.6     20.7     0.552X      0.55X     0.552X
+//                           sub_micro               20.6     20.7     20.9     0.552X     0.554X     0.556X
+//                            add_nano               21.1     21.3     21.4     0.567X     0.568X      0.57X
+//                     unix_timestamp1               46.9     46.9     47.1      1.26X      1.25X      1.25X
+//                     unix_timestamp2               64.2     64.4     64.7      1.72X      1.72X      1.72X
+//                          from_unix1                6.3      6.3     6.37     0.169X     0.168X      0.17X
+//                          from_unix2               11.3     11.6     11.8     0.305X     0.309X     0.315X
+//                                year               59.3     59.4     59.8      1.59X      1.59X      1.59X
+//                               month               59.3     59.4     59.7      1.59X      1.59X      1.59X
+//                        day of month               58.8     59.3     59.6      1.58X      1.58X      1.59X
+//                         day of year               53.4     53.5     53.8      1.44X      1.43X      1.43X
+//                        week of year               50.4     50.6     51.2      1.35X      1.35X      1.36X
+//                                hour                126      127      129      3.38X       3.4X      3.44X
+//                              minute                126      126      129      3.38X      3.38X      3.43X
+//                              second                126      127      128      3.38X       3.4X      3.42X
+//                             to date               23.1     23.1     23.4     0.622X     0.619X     0.623X
+//                           date diff               22.4     22.4     22.6     0.602X     0.599X     0.601X
+//                            from utc               38.9     39.4     39.6      1.05X      1.05X      1.06X
+//                              to utc               21.8     21.8     21.9     0.585X     0.582X     0.582X
+//                                 now                517      522      527      13.9X        14X        14X
+//                      unix_timestamp                378      381      384      10.2X      10.2X      10.2X
+Benchmark* BenchmarkTimestampFunctions(bool codegen) {
+  Benchmark* suite = new Benchmark(BenchmarkName("TimestampFn", codegen));
   BENCHMARK("literal", "cast('2012-01-01 09:10:11.123456789' as timestamp)");
   BENCHMARK("to_string",
       "cast(cast('2012-01-01 09:10:11.123456789' as timestamp) as string)");
@@ -561,50 +875,55 @@ Benchmark* BenchmarkTimestampFunctions() {
       "to_date(cast('2011-12-22 09:10:11.12345678' as timestamp))");
   BENCHMARK("date diff", "datediff(cast('2011-12-22 09:10:11.12345678' as timestamp), "
       "cast('2012-12-22' as timestamp))");
-#if 0
-  // TODO: need to create a valid runtime state for these functions
   BENCHMARK("from utc",
       "from_utc_timestamp(cast(1.3041352164485E9 as timestamp), 'PST')");
   BENCHMARK("to utc",
       "to_utc_timestamp(cast('2011-01-01 01:01:01' as timestamp), 'PST')");
   BENCHMARK("now", "now()");
   BENCHMARK("unix_timestamp", "unix_timestamp()");
-#endif
   return suite;
 }
 
+typedef Benchmark* (*SingleBenchmark)(bool);
+
 int main(int argc, char** argv) {
   impala::InitCommonRuntime(argc, argv, true, impala::TestInfo::BE_TEST);
   impala::InitFeSupport(false);
   ABORT_IF_ERROR(impala::LlvmCodeGen::InitializeLlvm());
+  ThreadDebugInfo debugInfo;
+
+  // The host running this test might have an out-of-date tzdata package installed.
+  // To avoid tzdata related issues, we will load time-zone db from the testdata
+  // directory.
+  FLAGS_hdfs_zone_info_zip =
+      Substitute("file://$0/testdata/tzdb/2017c.zip", getenv("IMPALA_HOME"));
+  ABORT_IF_ERROR(TimezoneDatabase::Initialize());
 
   // Dynamically construct at runtime as the planner initialization depends on
   // static objects being initialized in other compilation modules.
   planner = new Planner();
 
-  // Generate all the tests first (this does the planning)
-  Benchmark* literals = BenchmarkLiterals();
-  Benchmark* arithmetics = BenchmarkArithmetic();
-  Benchmark* like = BenchmarkLike();
-  Benchmark* cast = BenchmarkCast();
-  Benchmark* decimal_cast = BenchmarkDecimalCast();
-  Benchmark* conditional_fns = BenchmarkConditionalFunctions();
-  Benchmark* string_fns = BenchmarkStringFunctions();
-  Benchmark* url_fns = BenchmarkUrlFunctions();
-  Benchmark* math_fns = BenchmarkMathFunctions();
-  Benchmark* timestamp_fns = BenchmarkTimestampFunctions();
+  // List benchmark functions that will be exercised.
+  vector<SingleBenchmark> benchmarks;
+  benchmarks.push_back(&BenchmarkLiterals);
+  benchmarks.push_back(&BenchmarkArithmetic);
+  benchmarks.push_back(&BenchmarkLike);
+  benchmarks.push_back(&BenchmarkCast);
+  benchmarks.push_back(&BenchmarkDecimalCast);
+  benchmarks.push_back(&BenchmarkConditionalFunctions);
+  benchmarks.push_back(&BenchmarkStringFunctions);
+  benchmarks.push_back(&BenchmarkUrlFunctions);
+  benchmarks.push_back(&BenchmarkMathFunctions);
+  benchmarks.push_back(&BenchmarkTimestampFunctions);
 
   cout << Benchmark::GetMachineInfo() << endl;
-  cout << literals->Measure() << endl;
-  cout << arithmetics->Measure() << endl;
-  cout << like->Measure() << endl;
-  cout << cast->Measure() << endl;
-  cout << decimal_cast->Measure() << endl;
-  cout << conditional_fns->Measure() << endl;
-  cout << string_fns->Measure() << endl;
-  cout << url_fns->Measure() << endl;
-  cout << math_fns->Measure() << endl;
-  cout << timestamp_fns->Measure() << endl;
+  for (auto& benchmark : benchmarks) {
+    for (int codegen = 0; codegen <= 1; codegen++) {
+      planner->EnableCodegen(codegen);
+      Benchmark* suite = (*benchmark)(codegen);
+      cout << suite->Measure() << endl;
+    }
+  }
 
   return 0;
 }