diff --git a/benchmarks/basic_commands.py b/benchmarks/basic_commands.py
index e2838803db6e61d4f3cc54adff6954f448f83c03_YmVuY2htYXJrcy9iYXNpY19jb21tYW5kcy5weQ==..32ef8d6caa53b8d2a564b772fad2f192bd251c94_YmVuY2htYXJrcy9iYXNpY19jb21tYW5kcy5weQ== 100644
--- a/benchmarks/basic_commands.py
+++ b/benchmarks/basic_commands.py
@@ -1,4 +1,5 @@
+import contextlib
 import os
 import os.path
 import time
 import timeit
@@ -1,7 +2,10 @@
 import os
 import os.path
 import time
 import timeit
+import tempfile
+import shutil
+import subprocess
 
 from .utils import (BaseNChangesetsTestSuite, BaseTimeTestSuite,
                     BaseTrackTestSuite, median)
@@ -130,3 +134,58 @@
 
     def time_bundle(self, repo, n):
         self._execute("bundle", "--base", ":(-%d)" % (n+1), "/tmp/bundle.bundle")
+
+
+class ExchangeTrackSuite(BaseTrackTestSuite):
+    param_names = BaseTrackTestSuite.param_names + ['single_rev']
+    params = BaseTrackTestSuite.params + [[True, False]]
+
+    @contextlib.contextmanager
+    def clone(self, revset=None):
+        tempdir = tempfile.mkdtemp(dir=os.environ.get('ASVTEMPDIR'))
+        try:
+            clone_path = os.path.join(tempdir, 'clone')
+            cmd = [self.hgpath, '--cwd', self.repo_path,
+                   'clone', '--noupdate', '.', clone_path]
+            if revset is not None:
+                rev = subprocess.check_output([
+                    self.hgpath, '--cwd', self.repo_path, 'log', '-T',
+                    '{node}', '-r', revset, '--limit', '1'], env=self.environ)
+                cmd.extend(['-r', rev])
+            clone_time = self._single_execute(cmd)
+            yield clone_path, clone_time
+        finally:
+            shutil.rmtree(tempdir)
+
+    def track_incoming(self, repo_name, single_rev):
+        with self.clone(revset='default~10') as (clone_path, _):
+            cmd = [self.hgpath, '--cwd', clone_path, 'incoming']
+            if single_rev:
+                cmd.extend(['-r', 'default'])
+            return self._timeit(self._single_execute, (cmd,))
+
+    def track_outgoing(self, repo_name, single_rev):
+        with self.clone(revset='default~10') as (clone_path, _):
+            cmd = [self.hgpath, '--cwd', self.repo_path, 'outgoing',
+                   clone_path]
+            if single_rev:
+                cmd.extend(['-r', 'default'])
+            return self._timeit(self._single_execute, (cmd,))
+
+    def track_push(self, repo_name, single_rev):
+        def clone_and_push():
+            with self.clone(revset='default~10') as (clone_path, _):
+                cmd = [self.hgpath, '--cwd', self.repo_path, 'push', '-f',
+                       clone_path]
+                if single_rev:
+                    cmd.extend(['-r', 'default'])
+                return self._single_execute(cmd)
+        return self._timeit(clone_and_push)
+
+    def track_clone(self, repo_name, single_rev):
+        revset = 'default' if single_rev else None
+
+        def clone():
+            with self.clone(revset=revset) as (_, clone_time):
+                return clone_time
+        return self._timeit(clone)