13

LogActorというakkaアクターを作成しました。LogActorsのreceiveメソッドは、他のアクターからのメッセージを処理し、指定されたログレベルにそれらをログに記録します。

私は2つの方法で異なるレベルを区別することができます。最初の1つ:

import LogLevel._
object LogLevel extends Enumeration {
    type LogLevel = Value
    val Error, Warning, Info, Debug = Value
}
case class LogMessage(level : LogLevel, msg : String) 

2番目:(編集

abstract class LogMessage(msg : String)
case class LogMessageError(msg : String) extends LogMessage(msg)
case class LogMessageWarning(msg : String) extends LogMessage(msg)
case class LogMessageInfo(msg : String) extends LogMessage(msg)
case class LogMessageDebug(msg : String) extends LogMessage(msg)

どちらの方法がより効率的ですか?ケースクラスと一致する、または列挙値と一致するのにかかる時間は短くなりますか?

(私はこの質問を読みましたが、実行時の問題に関する回答はありません)

4

3 に答える 3

27

私はAlexeyとDennisに完全に同意します。これは、開発者ではなくコンパイラの最適化の問題であり、パフォーマンスの違いが顕著になるシナリオを想像できないためです。

気になるのはコードの一貫性です。この意味で、最初の例で正しく記述されている列挙型を使用した古いJava風のアプローチに固執するか、最近人気のある代数的データ型に固執するかを決定する必要があります。 (ADT)パターン。後者は、2番目の例で表現しようとしましたが、いくつかの間違いがあります。

以下は、ADTパターンで問題を正しく解決する方法です。

ADTソリューション#1

// 1. marked `sealed` to make pattern matching exhaustive
// 2. used a trait to avoid double storage of msg` and 
//    make the inheritance easier
sealed trait LogMessage { def msg : String }
// A better solution for isolation than names like "LogMessageError".
// Allows you to either address the members with a namespace like 
// "LogMessage.Error" or do "import LogMessage._" and address them 
// directly
object LogMessage { 
  case class Error (msg : String) extends LogMessage
  case class Warning (msg : String) extends LogMessage
  case class Info (msg : String) extends LogMessage
  case class Debug (msg : String) extends LogMessage
}

ADTソリューション#2

おそらく頭をいじって申し訳ありませんが、同様の状況に対応する代替のADTアプローチも存在することに注意してください。これは、列挙型で頭を動かすのと似ています。

sealed trait LogLevel 
object LogLevel {
  case object Error extends LogLevel
  case object Warning extends LogLevel
  case object Info extends LogLevel
  case object Debug extends LogLevel
}
case class LogMessage ( level : LogLevel, msg : String )
于 2012-11-12T16:50:21.397 に答える
8

「時期尚早に最適化しないでください」が適用されます。アクターにメッセージを渡したり、実際にログに記録したりするのに費やす時間と比較して、それらの違いが問題になる可能性はまったくないと思います。しかし、最高のパフォーマンスはenum、Scalaの代わりにロギングレベル用のJava(Scalaから簡単にアクセスして使用できる)を作成することだと思いますEnumeration

于 2012-11-12T13:29:56.690 に答える
0

ロガーの最も一般的な操作の1つは、現在のログレベルをメッセージのレベルと比較することです。列挙型を使用すると無料で取得できますが、ケースクラスを使用したセットアップでは多少面倒になります。そして、私は@AlexeyRomanovに同意します。ここでのマッチングがボトルネックになることはありません。

編集:パフォーマンスの面では、ケースクラスとの一致はバイトコードでinstanceofを使用しますが、列挙型の場合、私が試したデコンパイラーでは処理できないコードをscalaコンパイラーで生成しました。を使用しているようequalsです。したがって、技術的には列挙型の方が高速かもしれませんが、実際にはパフォーマンスに違いはありません。

于 2012-11-12T13:45:04.523 に答える