16

Scalaの学習を始めたばかりで、人生最高の時間を過ごしています。今日、Android 用の Scala についても聞いたばかりで、完全にはまってしまいました。

ただし、Scala は Java++ であるという点で Java のスーパーセットのようなものであることを考えると (つまり、より多くのものが含まれている Java を意味します)、Scala コードが Android でどのように機能するのか正確に疑問に思っています。

また、Scala で作成した場合、Android アプリケーションのパフォーマンスは影響を受けますか? つまり、Scala コードを解釈するために追加の作業が必要な場合です。

4

4 に答える 4

41

@Aneesh の回答を少し説明すると、はい、Java バイトコードとまったく同じビットとピースであるため、Scala バイトコードを解釈するための余分な作業はありません。

ここに画像の説明を入力してください

Android でコードを実行する場合、Java バイトコード => Dalvikバイトコード ステップもあることに注意してください。

しかし、同じレンガを使用して、一方が自転車置き場を建設し、もう一方がタウンホールを建設することができます。たとえば、言語は不変性を助長するという事実のために、Scala は多くの短い生きたオブジェクトを生成します。HotSpotのような成熟した JVM の場合、約 10 年間は大したことではありません。しかし、Dalvikの場合、これは問題です(最近のバージョンより前のオブジェクト プーリングと、作成済みのオブジェクトの厳密な再利用は、Java でも最も一般的なパフォーマンスのヒントの 1 つでした)。

次に、 val を書くことは を書くことと同じではありませんfinal Foo bar = ...。内部的には、このコードはフィールド + ゲッターとして表されます (private [this]通常の最終フィールドに変換される val のプレフィックスを付けない限り)。varフィールド+ゲッター+セッターに変換されます。どうしてそれが重要ですか?

古いバージョンの Android (2.2 より前) には JIT がまったくないため、直接フィールド アクセスに比べて約 3 倍から 7 倍のペナルティが発生します。そして最後に、Google は内部クラスを避け、代わりにパッケージを優先するように指示していますが、Scala はそう書かなくても多くの内部クラスを作成します。次のコードを検討してください。

object Foo extends App {
    List(1,2,3,4)
      .map(x => x * 2)
      .filter(x => x % 3 == 0)
      .foreach(print)
}

内部クラスはいくつ作成されますか? 何も言わないこともできますが、scalac を実行すると次のように表示されます。

Foo$$anonfun$1.class       // Map
Foo$$anonfun$2.class       // Filter
Foo$$anonfun$3.class       // Foreach
Foo$.class                 // Companion object class, because you've used `object`
Foo$delayedInit$body.class // Delayed init functionality that is used by App trait
Foo.class                  // Actual class

そのため、不変性とシンタックス シュガーを多く使って慣用的な Scala コードを書く場合は特に、多少のペナルティが発生します。問題は、展開 (より新しいデバイスをターゲットにしていますか?) と実際のコード パターン (いつでも Java に戻るか、少なくともパフォーマンスの重要な場所で慣用的なコードを少なく書くことができます) に大きく依存し、そこで言及されている問題のいくつかは、次のバージョンでは、言語自体 (最後のもの) によって対処されます。

元の画像ソースは Wikipediaでした。

スタック オーバーフローの質問も参照してください。Android で Scala を使用する価値はありますか? オーバーヘッドは多いですか?問題?開発中に発生する可能性のある問題について。

于 2013-09-30T12:59:57.330 に答える
5

2 つの言語間のベンチマークを示すこの論文を見つけました。

http://cse.aalto.fi/en/midcom-serveattachmentguid-1e3619151995344619111e3935b577b50548b758b75/denti_ngmast.pdf

私は記事全体を読んだわけではありませんが、最終的にはJavaにポイントを与えるようです:

結論として、Scala は、デバイスのエネルギー消費を低く抑えることが重要であるため、将来のモバイル アプリケーション開発において主要な役割を果たすことはないと考えています。Scala 言語の強みは、そのコンポーネントのスケーリング方法です。これは、アプリケーションがまったくスケーリングされず、小さいままであるモバイル デバイスではそれほど重要ではありません。

アールト大学の Mattia Denti と Jukka K. Nurminen の功績によるものです。

于 2013-09-30T13:39:00.863 に答える
5

Scala は Java と同じようにバイト コードにコンパイルされるため、「問題なく動作します」が、考慮すべきパフォーマンスの問題があります。慣用的な Scala コードは、より多くの一時オブジェクトを作成する傾向があり、Dalvik VM はこれらにあまり親切ではありません。

Android で Scala を使用する場合は、次の点に注意してください。

  • ベクトルは無駄になる可能性があるため (1 つのアイテムしか保持していない場合でも、常に 32 個のアイテムの配列を使用します)
  • コレクションのメソッド チェーン - 冗長なコレクションの作成を避けるために、可能な限り .view を使用する必要があります。
  • Boxing - Scala は、Generics の使用、Option[Int] の使用、いくつかの無名関数など、さまざまなケースでプリミティブをボックス化します。
  • for ループはメモリを浪費する可能性があるため、重要なセクションでは while ループに置き換えることを検討してください
  • 暗黙の変換 - like の呼び出しはstr.indexWhere(...)、文字列にラッパー オブジェクトを割り当てます。無駄になる可能性があります。
  • Scala の Map は、キーにアクセスするたびに Option[V] を割り当てます。場合によっては、Java の HashMap に置き換える必要がありました。

もちろん、プロファイラーを使用した後にボトルネックとなる場所のみを最適化する必要があります。

上記の提案について詳しくは、次のブログ投稿をご覧ください: http://blogs.microsoft.co.il/dorony/2014/10/07/scala-performance-tips-on-android/

于 2014-10-07T21:14:46.317 に答える
2

Scala コンパイラは JVM バイト コードを作成します。つまり、基本的に下位レベルでは、Java を実行しているようなものです。したがって、パフォーマンスは Java と同等になります。

ただし、Scala コンパイラがバイト コードを作成する方法は、パフォーマンスに影響を与える可能性があります。Scala は新しく、バイト コード生成が非効率的である可能性があるため、Scala は Android では Java よりも少し遅くなりますが、それほどではありません。

于 2013-09-30T11:46:56.240 に答える