0

プログラムによって入力される単純な単一のキー値 Map(K,V) myDictionaryがあり、最後にそれを JSON 形式の文字列としてテキスト ファイルに書き込みます。後で解析する必要があるためです。

私は以前にこのコードを使用していましたが、

Some(new PrintWriter(outputDir+"/myDictionary.json")).foreach{p => p.write(compact(render(decompose(myDictionary)))); p.close}

入力サイズが大きくなるにつれて遅くなることがわかりました。後で、この var out = new を使用しました

var out = new PrintWriter(outputDir+"/myDictionary.json");
out.println(scala.util.parsing.json.JSONObject(myDictionary.toMap).toString())

これは少し速いことが証明されています。

サンプル入力用にこれを実行したところ、以前のアプローチよりも高速であることがわかりました。入力マップのサイズが少なくとも100 万の値 (>1GB テキスト ファイル) (K,V) に達すると想定しているため、Map シリアル化プロセスの高速でメモリ効率の高いアプローチに従うようにしたいと考えています。これを最適化するために調査できることをお勧めします。

4

1 に答える 1

4

標準の Scala ライブラリでの JSON サポートは、おそらく最良の選択ではありません。残念ながら、Scala の JSON ライブラリの状況は少し混乱しています。多くの代替手段(Lift JSON、Play JSON、Spray JSON、Twitter JSON、Argonaut など) があり、基本的に曜日ごとに 1 つのライブラリがあります...少なくともこれらを見て、使いやすく、パフォーマンスが高いものがあるかどうかを確認することをお勧めします。


これは、特定の理由 (マクロでフォーマットを生成できる) で選択した Play JSON を使用した例です。

object JsonTest extends App {
  import play.api.libs.json._

  type MyDict = Map[String, Int]

  implicit object MyDictFormat extends Format[MyDict] {
    def reads(json: JsValue): JsResult[MyDict] = json match {
      case JsObject(fields) =>
        val b = Map.newBuilder[String, Int]
        fields.foreach {
          case (k, JsNumber(v)) => b += k -> v.toInt
          case other => return JsError(s"Not a (string, number) pair: $other")
        }
        JsSuccess(b.result())

      case _ => JsError(s"Not an object: $json")
    }

    def writes(m: MyDict): JsValue = {
      val fields: Seq[(String, JsValue)] = m.map {
        case (k, v) => k -> JsNumber(v)
      } (collection.breakOut)

      JsObject(fields)
    }
  }

  val m       = Map("hallo" -> 12, "gallo" -> 34)
  val serial  = Json.toJson(m)
  val text    = Json.stringify(serial)
  println(text)
  val back    = Json.fromJson[MyDict](serial)
  assert(back == JsSuccess(m), s"Failed: $back")
}

直接構築および分解できますがJsValues、主なアイデアは、データ構造の型であるFormat[A]whereを使用することです。Aこれにより、標準の Scala-Library JSON よりもタイプ セーフが強調されます。より冗長に見えますが、最終的にはそれがより良いアプローチだと思います。

必要な型の暗黙的な形式を探すユーティリティ メソッドがありJson.toJsonます。Json.fromJson

一方、すべてをメモリ内に構築し、データ構造を複製します (マップ内のエントリごとに別の tuple が(String, JsValue)あるため)。 GBの大きさで動作しています...


Jerkson は、Java JSON ライブラリ Jackson の Scala ラッパーです。後者には明らかにデータをストリーミングする機能があります。ストリーミングサポートを追加するというこのプロジェクトを見つけました。Play JSON は Jerkson に基づいているため、おそらくそれを使用してオブジェクトをストリーミングする方法を理解することさえできます。この質問も参照してください。

于 2013-10-18T09:21:08.300 に答える