diff --git a/daffodil-cli/src/main/scala/edu/illinois/ncsa/daffodil/Main.scala b/daffodil-cli/src/main/scala/edu/illinois/ncsa/daffodil/Main.scala
index a218f17..969190d 100644
--- a/daffodil-cli/src/main/scala/edu/illinois/ncsa/daffodil/Main.scala
+++ b/daffodil-cli/src/main/scala/edu/illinois/ncsa/daffodil/Main.scala
@@ -36,6 +36,7 @@ import java.io.FileOutputStream
 import java.io.BufferedWriter
 import java.io.OutputStreamWriter
 import java.io.FileInputStream
+import java.io.ByteArrayInputStream
 import java.io.File
 import scala.xml.SAXParseException
 import org.rogach.scallop
@@ -60,6 +61,8 @@ import edu.illinois.ncsa.daffodil.externalvars.Binding
 import edu.illinois.ncsa.daffodil.externalvars.ExternalVariablesLoader
 import edu.illinois.ncsa.daffodil.configuration.ConfigurationLoader
 import edu.illinois.ncsa.daffodil.api.ValidationMode
+import scala.actors.Futures._
+import scala.actors._
 
 class CommandLineXMLLoaderErrorHandler() extends org.xml.sax.ErrorHandler with Logging {
 
@@ -287,6 +290,51 @@ class CLIConf(arguments: Array[String]) extends scallop.ScallopConf(arguments)
     }
 
   }
+  
+  // Performance Subcommand Options
+  val performance = new scallop.Subcommand("performance") {
+    banner("""|Usage: daffodil performance (-s <schema>... [-r <root> [-n <namespace>]] [-p <path>] |
+              |                       -P <parser>)
+              |                      [--validate [mode]]
+              |                      [-D[{namespace}]<variable>=<value>...] [-o <output>]
+              |                      [-c <file>] [infile]
+              |
+              |Run a performance test, using either a DFDL schema or a saved parser
+              |
+              |Performance Options:""".stripMargin)
+
+    descr("run performanc tests")
+    helpWidth(76)
+
+    val schemas = opt[List[String]]("schema", argName = "file", descr = "the annotated DFDL schema to use to create the parser. May be supplied multiple times for multi-schema support.")(singleListArgConverter[String](a => a))
+    val root = opt[String](argName = "node", descr = "the root element of the XML file to use. This needs to be one of the top-level elements of the DFDL schema defined with --schema. Requires --schema. If not supplied uses the first element of the first schema")
+    val namespace = opt[String](argName = "ns", descr = "the namespace of the root element. Requires --root.")
+    val path = opt[String](argName = "path", descr = "path to the node to create parser.")
+    val parser = opt[String](short = 'P', argName = "file", descr = "use a previously saved parser.")
+    val output = opt[String](argName = "file", descr = "write output to a given file. If not given or is -, output is written to stdout.")
+    val validate = opt[ValidationMode.Type](short = 'V', default = Some(ValidationMode.Off), argName = "mode", descr = "the validation mode. 'on', 'limited' or 'off'. Defaults to 'on' if mode is not supplied.")(optionalValueConverter[ValidationMode.Type](a => validateConverter(a)).map {
+      case None => ValidationMode.Full
+      case Some(mode) => mode
+    })
+    val vars = props[String]('D', keyName = "variable", valueName = "value", descr = "variables to be used when parsing. An option namespace may be provided.")
+    val config = opt[String](short = 'c', argName = "file", descr = "path to file containing configuration items.")
+    val infile = trailArg[String](required = false, descr = "input file to parse. If not specified, or a value of -, reads from stdin.")
+
+    validateOpt(debug, infile) {
+      case (Some(None), Some("-")) | (Some(None), None) => Left("Input must not be stdin during interactive debugging")
+      case _ => Right(Unit)
+    }
+
+    validateOpt(schemas, parser, root, namespace) {
+      case (Some(Nil), None, _, _) => Left("One of --schema or --parser must be defined")
+      case (Some(_ :: _), Some(_), _, _) => Left("Only one of --parser and --schema may be defined")
+      case (Some(_ :: _), None, None, Some(_)) => Left("--root must be defined if --namespace is defined")
+      case (None, Some(_), Some(_), _) => Left("--root cannot be defined with --parser")
+      case (None, Some(_), _, Some(_)) => Left("--namespace cannot be defined with --parser")
+      case _ => Right(Unit)
+    }
+
+  }
 
   // Unparse Subcommand Options
   val unparse = new scallop.Subcommand("unparse") {
@@ -643,6 +691,93 @@ object Main extends Logging {
         }
         rc
       }
+      
+      case Some(conf.performance) => {
+        val performanceOpts = conf.performance
+
+        val validate = performanceOpts.validate.get.get
+
+        val cfgFileNode = performanceOpts.config.get match {
+          case None => None
+          case Some(pathToConfig) => Some(this.loadConfigurationFile(pathToConfig))
+        }
+        val extVarsBindings = retrieveExternalVariables(performanceOpts.vars, cfgFileNode)
+
+        val processor = {
+          if (performanceOpts.parser.isDefined) {
+            createProcessorFromParser(performanceOpts.parser(), performanceOpts.path.get, validate)
+          } else {
+            val files: List[File] = performanceOpts.schemas().map(s => new File(s))
+            createProcessorFromSchemas(files, performanceOpts.root.get, performanceOpts.namespace.get, performanceOpts.path.get, extVarsBindings, validate)
+          }
+        }
+
+        def displayDiagnostics(lvl: LogLevel.Type, pr: WithDiagnostics) {
+          pr.getDiagnostics.foreach { d =>
+            log(lvl, "%s", d.getMessage())
+          }
+        }
+
+        val rc = processor match {
+          case Some(processor) if (processor.canProceed) => {
+            val (input, optDataSize) = {
+                val f = new File(performanceOpts.infile())
+                (new FileInputStream(f), f.length())
+            }
+            
+            //create byte array to clone in each "thread"
+            var fileContent:Array[Byte] = new Array[Byte](optDataSize.toInt)
+            input.read(fileContent)
+           
+            processor.setValidationMode(validate)
+
+            //this is the processor.parse we need to put in a thread
+            val tasks = for (i <- 1 to 2) yield future {
+                val newArr:Array[Byte] = fileContent.clone()
+                val s:String = new String(newArr)
+                println("--------------------")
+                println(i + ": byte array: " + newArr)
+                println(i + ": newArr: " + s)
+                println("--------------------")
+
+                val bais:ByteArrayInputStream = new ByteArrayInputStream(newArr)
+                val inChannel = java.nio.channels.Channels.newChannel(bais);
+                val parseResult = Timer.getResult("parsing", 
+                  processor.parse(inChannel, optDataSize * 8))
+
+                val loc = parseResult.resultState.currentLocation
+                if (parseResult.isError) {
+                  displayDiagnostics(LogLevel.Error, parseResult)
+                  1
+                } else {
+                  displayDiagnostics(LogLevel.Warning, parseResult) // displays any warnings (should be no errors)
+                  val output = performanceOpts.output.get match {
+                    case Some("-") | None => System.out
+                    case Some(file) => new FileOutputStream(file)
+                  }
+                  // check for left over data (if we know the size up front, like for a file)
+                  val hasLeftOverData = {
+                      if (!loc.isAtEnd) {
+                        log(LogLevel.Error, "Left over data. %s bytes available. Location: %s", optDataSize, loc)
+                        true
+                      } else false
+                    }
+                  val writer: BufferedWriter = new BufferedWriter(new OutputStreamWriter(output));
+                  val pp = new scala.xml.PrettyPrinter(80, 2)
+                  Timer.getResult("writing", writer.write(pp.format(parseResult.result) + "\n"))
+                  writer.flush()
+                  if (hasLeftOverData) 1 else 0
+                }
+              //Thread.sleep(i + 3000L)
+            }
+            awaitAll(20000L, tasks: _*)
+            0
+          }
+          case Some(processor) => 1
+          case None => 1
+        }
+        rc
+      }
 
       case Some(conf.unparse) => {
         val unparseOpts = conf.unparse
