5

パーサー用の新しいコンビネーターを scala で作成しました。

位置情報を渡す ^^ コンビネータのバリエーションです。しかし、入力要素の位置情報にアクセスすることは、本当にコスト パフォーマンスが高くなります。

私の場合、大きな例を解析するには、位置情報なしで約 3 秒必要で、30 秒以上必要です。

位置にアクセスすると、ランタイムが約 50% 増加する実行可能な例を作成しました。

何故ですか?ランタイムを改善するにはどうすればよいですか?

例:

import scala.util.parsing.combinator.RegexParsers
import scala.util.parsing.combinator.Parsers
import scala.util.matching.Regex
import scala.language.implicitConversions
object FooParser extends RegexParsers with Parsers {
  var withPosInfo = false
  def b: Parser[String] = regexB("""[a-z]+""".r)  ^^@ { case (b, x) => b + " ::" + x.toString }
  def regexB(p: Regex): BParser[String] = new BParser(regex(p))
  class BParser[T](p: Parser[T]) {
    def ^^@[U](f: ((Int, Int), T) => U): Parser[U] = Parser { in =>
      val source = in.source
      val offset = in.offset
      val start = handleWhiteSpace(source, offset)
      val inwo = in.drop(start - offset)
      p(inwo) match {
        case Success(t, in1) =>
          {
            var a = 3
            var b = 4
            if(withPosInfo)
            { // takes a lot of time
              a = inwo.pos.line
              b = inwo.pos.column
            }            
            Success(f((a, b), t), in1)
          }
        case ns: NoSuccess => ns
      }
    }
  }
  def main(args: Array[String]) = {
    val r = "foo"*50000000
    var now = System.nanoTime

    parseAll(b, r) 
    var us = (System.nanoTime - now) / 1000
    println("without: %d us".format(us))
    withPosInfo = true
    now = System.nanoTime
    parseAll(b, r)
    us = (System.nanoTime - now) / 1000
    println("with   : %d us".format(us))
  }
}

出力:

なし: 2952496 us

と : 4591070 私たち

4

1 に答える 1

4

残念ながら、同じアプローチを使用できるとは思いません。問題は、行番号が実装されて、作成されるたびscala.util.parsing.input.OffsetPositionにすべての改行のリストが作成されることです。したがって、文字列入力で終わる場合は、へのすべての呼び出しですべてを解析します(例では2回)。詳細については、 CharSequenceReaderおよびOffsetPositionのコードを参照してください。pos

これをスピードアップするためにできる簡単なことが1つあります。

val ip = inwo.pos
a = ip.line
b = ip.column

少なくともpos2回作成することは避けてください。しかし、それでも多くの冗長な作業が残ります。OffsetPosition自分のようにインデックスを作成し、それを参照し続ける必要があるという問題を本当に解決することを恐れています。

バグレポートを提出したり、拡張リクエストを行ったりすることもできます。これは、機能を実装するためのあまり良い方法ではありません。

于 2013-02-05T12:44:53.193 に答える