diff --git a/.arcconfig b/.arcconfig
--- a/.arcconfig
+++ b/.arcconfig
@@ -1,3 +1,5 @@
 {
-  "phabricator.uri": "https://secure.phabricator.com/"
+  "phabricator.uri": "https://secure.phabricator.com/",
+  "load": ["support/libxhprof"],
+  "unit.engine": "XHProfExtensionUnitTestEngine"
 }
diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,5 @@
 extension/tests/*.diff
 extension/tests/*.log
 extension/tests/*.php
+
+support/libxhprof/.phutil_module_cache
diff --git a/support/libxhprof/__phutil_library_init__.php b/support/libxhprof/__phutil_library_init__.php
new file mode 100644
--- /dev/null
+++ b/support/libxhprof/__phutil_library_init__.php
@@ -0,0 +1,3 @@
+<?php
+
+phutil_register_library('libxhprof', __FILE__);
diff --git a/support/libxhprof/__phutil_library_map__.php b/support/libxhprof/__phutil_library_map__.php
new file mode 100644
--- /dev/null
+++ b/support/libxhprof/__phutil_library_map__.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * This file is automatically generated. Use 'arc liberate' to rebuild it.
+ *
+ * @generated
+ * @phutil-library-version 2
+ */
+phutil_register_library_map(array(
+  '__library_version__' => 2,
+  'class' => array(
+    'XHProfExtensionUnitTestEngine' => 'unit/XHProfUnitTestEngine.php',
+  ),
+  'function' => array(),
+  'xmap' => array(
+    'XHProfExtensionUnitTestEngine' => 'ArcanistUnitTestEngine',
+  ),
+));
diff --git a/support/libxhprof/unit/XHProfUnitTestEngine.php b/support/libxhprof/unit/XHProfUnitTestEngine.php
new file mode 100644
--- /dev/null
+++ b/support/libxhprof/unit/XHProfUnitTestEngine.php
@@ -0,0 +1,53 @@
+<?php
+
+final class XHProfExtensionUnitTestEngine extends ArcanistUnitTestEngine {
+
+  public function run() {
+    $root = $this->getWorkingCopy()->getProjectRoot().'/extension/';
+
+    $start_time = microtime(true);
+
+    id(new ExecFuture('phpize && ./configure && make -j4'))
+      ->setCWD($root)
+      ->resolvex();
+
+    $out = id(new ExecFuture('make -f Makefile.local test_with_exit_status'))
+      ->setCWD($root)
+      ->setEnv(
+        array(
+          'TEST_PHP_ARGS' => '-q',
+        ))
+      ->resolvex();
+
+    // NOTE: REPORT_EXIT_STATUS doesn't seem to work properly in some versions
+    // of PHP. Just "parse" stdout to approximate the results.
+
+    list($stdout) = $out;
+
+    $tests = array();
+
+    foreach (phutil_split_lines($stdout) as $line) {
+      $matches = null;
+
+      // NOTE: The test script writes the name of the test originally, then
+      // uses "\r" to erase it and write the result. This splits as a single
+      // line.
+      if (preg_match('/^TEST .*\r(PASS|FAIL) (.*)/', $line, $matches)) {
+        if ($matches[1] == 'PASS') {
+          $result = ArcanistUnitTestResult::RESULT_PASS;
+        } else {
+          $result = ArcanistUnitTestResult::RESULT_FAIL;
+        }
+
+        $name = trim($matches[2]);
+
+        $tests[] = id(new ArcanistUnitTestResult())
+          ->setName($name)
+          ->setResult($result)
+          ->setDuration(microtime(true) - $start_time);
+      }
+    }
+
+    return $tests;
+  }
+}