Furyu
[フリュー公式]

Tech Blog

フリュー株式会社の技術ブログです

2015年11月16日

sakata

JavaOne 2015 サンフランシスコに参加しました!(2日目パート2)

Hello World! コンテンツ・メディア第1事業部の、jyukutyoこと阪田です。JavaOneは一番最初のセッションが始まるのは8:30、最後のセッションが終わるのは21:45です。お昼休みはありませんのでセッション間で昼食を済ませつつ、ずっとセッションを聴き続けるため、期間中はかなりハードです。観光などする時間はなく、お土産を買う時間を捻出するのもかなり大変でした。

Introduction to Modular Development

キーノートでもあった「Project Jigsaw」の紹介セッションです。構文はキーノートのレポートを参照してください。 今後java.lang.Objectなどはプラットフォームが提供するjava.baseモジュールにまとめられ、暗黙的に依存することとなります。モジュールのアクセシビリティは、モジュール内の公開されたパッケージのpublicなものだけです。公開されていないパッケージのpublicにはアクセスできないため、publicであるだけではアクセシビリティはありません。 モジュールはmodule-info.javaに記述し、コンパイルに含める必要があります。他のモジュールを使うときはjava -modulepath dir1:dir2のようにします。モジュールのmain()メソッドを実行するときはjava -m モジュール名/モジュールの完全修飾名で実行します。このあたりのことはProject Jigsawのクイックスタートページがわかりやすいです。-Xdiag:resolverオプションをつけると、依存関係の解決をログに出力することができるようです。

invokedynamic for Mere Mortals

JVM命令の1つであるinvokedynamic(indy)についてです。 JVMはもちろんJavaのために設計されたものですが、近年複数のプログラミング言語がJVM上で動作するようになりました。いまやどんな種類のプログラミング言語にとってもすばらしいプラットフォームとなっています。 Java以外の言語にとっての要求は、例えばcontinuationsやdyanmic invocation、tail recursion、interface injectionなどです。dyanmic invocation(動的呼び出し)をするために動的型付けがあるわけですが、動的型付けでは、呼び出しを実行するその瞬間までその型がいったい何なのか知ることができません。動的型付けは型妨害ではないし、弱い型付けでもありません。動的型付け言語は完全な型情報がなく、より実行時のチェックが求められます。indyができるまではこういった言語をJVMで動作させるためにはリフレクションを使うしかありませんでした。ただし、リフレクションにすると動作が遅く、引数がすべてObjectであったりとさまざまな問題がありました。リフレクションではインライン化できず最適化できませんでした。


JSR-292でjava.lang.invokeのAPIが追加されましたが、これはよりよいリフレクションと言えるかもしれません。そしてinvokedynamic命令が追加されました。これはリンケージのためにディスパッチするものです。indyはJVM命令セットができてから初めて追加された命令で、そして初めてJava以外の言語をターゲットにした命令です。メソッドハンドルとコールサイト、そしてブートストラップメソッド(bsm)という概念があります。メソッドハンドルはメソッドを指し示すものです。関数ポインタ的な考えでよいと思います。メソッドハンドルのパフォーマンスですが、リフレクションよりはかなり早くなります。indyとは独立して使うことができます。コールサイトがメソッドハンドルを使ってメソッド呼び出しをします。動的という意味では、コールサイトは変わらずメソッドハンドルを変えることで呼び出すメソッドを換えれられます。つまり、コールサイトがメソッドハンドルを保持しています。


次にブートストラップのステップです。indyを使ったコードを実行するとき、ブートストラップメソッド(bsm)を呼び出します。bsmはコールサイトを返すメソッドであるため、コールサイトを通じてメソッドハンドルへ、メソッドハンドルからメソッドを呼び出すというステップです。2回目以降の実行は、bsmは呼び出さずにコールサイトを通じて呼び出すだけです。リンケージは呼び出しではなく、リンケージは一度だけ実行する必要があるもので、またコストの高い処理でもあります。一方呼び出しは何度も実行するもので、jmp/callを必要とします。indyによってリンケージが変えました。java.lang.invokeのAPIはindyなしでもよく使われます。JVMはどの言語にとってもすばらしいプラットフォームと言えるでしょう。

Compact Strings: A Memory-Efficient Internal Representation for Strings

JEP(JDK Enhancement Proposals) 254: Compact Stringsについてです。Stringの内部表現でもっと効果的にリソースを使うようにしようというものです。個人的にはこれが2日目で一番興味深かったセッションですね。JDK9でのリリースが予定されています。 JavaはUTF-16をサポートしており、2バイト文字を使います。より効果的にリソースを使うようにしつつも、完全な後方互換性を保つようにします。どんな使用状況でも以前のスループットパフォーマンスは維持します。JDK6で失敗したCompressed Stringsの置き換えです。さまざまなアプリケーションから統計をとったところ、Stringの大部分は小さいもので、75%以上は35文字未満でした。また、x64でcompressd referenceを使わないと2倍メモリを使うことになります。


新しいStringクラスのデザインは次のようになります。後方互換性を維持しつつも、内部表現は変更します。UTF-16だけで表現するのではなく、 UTF-16またはISO-8859-1/Latin-1を使うようにします。1バイト文字はISO-8859-1/Latin-1で、2バイト文字はUTF-16とし、char配列ではなくbyte配列で表現するようにします。さらにencodingというbyteのフィールドを追加し、何のエンコーディングか示唆するようにします。なぜUTF-8ではないのかというと、UTF-8は文字幅が可変なためです。StringのAPIは文字シーケンスにランダムアクセスするものがたくさんあります。Stringクラスはこう変わるイメージです。JDK8ではStringクラスはこうでした。

JEP 254ではこうなります。

さきほどJDK6での失敗と言いましたが、具体的に見てみます。JDK6のCompressed Stringsがないときはこうでした。

Compressed Stringsでこうなりました。

valueがObjectであり、byte[]かchar[]かを判断する必要がありました。そのためCompressed StringsではStringクラスの2つの実装があることとなります。メンテナンスのコストもかかります。JREでのサポートに限界もありました。JEP 254ではbyte[]のみとなります。encodingフィールドも追加します。JREでcompressed stringsへのサポートも拡張できるでしょう。


JMH(Javaのマイクロベンチマークツール)でのベンチマークでは、すべてのケースで処理が早くなっています。メモリ使用量は21%削減できました。スループットも5%増加してよくなっています。

jyukutyoコメント

2日目に出たセッションからいくつかをピックアップしてレポートしました。これでまだ2日目!あと3日分あります。長いレポートになりますが、ぜひ最後までお付き合いください。


2015年11月12日

sakata

JavaOne 2015 サンフランシスコに参加しました!(2日目パート1)

Hello World! コンテンツ・メディア第1事業部の、jyukutyoこと阪田です。 2日目からいよいよ本格的なセッションが始まります。すべてのセッションについては書けないので、いくつかを抜粋して書いていきます。私の興味はJVMにあり、Javaの新しい言語仕様よりもGCやパフォーマンスチューニングのセッションに多く出ました。

GC Tuning Confessions of a Performance Engineer

パフォーマンスエンジニアによるGCのチューニングについてのお話です。やはり日本で英語スピーカーが話すときとまったく話すスピードが違います。すべてを理解しようとせず、ヒアリングと資料の内容を照らし合わせながら必死に理解を進めました。

GCにおけるメトリクスには、たとえば次のようなものがあります。

  • GCのイベント数
  • 最小/最大実行時間
  • 平均実行時間
  • 99%平均実行時間

GCの内部に迫っていくと、GCがあるからといってメモリリークがなくなるわけでないということです。そしてGCにはトレードオフがあります。今のアプリケーションはどんどんヒープ領域が大きくなっていますが、それゆえにフルGCは怖いものとなっています。GCのチューニングの観点からは、登場人物が2人います。スループットとレイテンシです。GCには世代別や並列などの種類がありますが、OpenJDKではすべてのGCは世代別GCです。 アプリケーションがレイテンシを重視しているか、GCを並列にするかどうか、さらにGCでコンパクションするかどうかでCMS(Concurrent Mark-Sweep)かG1GCにするかを選択します。

GCアルゴリズム

ここからはGCアルゴリズムの復習です。まずヒープ領域はEden、Survivor0、Survivor1を合わせたYoung領域と、残りのOld領域に分けられます。Young領域とOld領域では、GCのアルゴリズムを別々にできます。 シリアルコレクタであれば、YoungもOldも両方シングルスレッドでGCします。スループットコレクタ(パラレルコレクタ)はYoungもOldもマルチスレッドでGCし、コンパクションもします。CMSはYoungはことごとくGCし、Oldはmostly concurrent(”ほぼ”並列)にGCします。 プロモーション(昇格)とはYoungからOldへの昇格を指します。CMSはOldへのプロモーションが早くなります。またCMSではフリーリストを使って領域を管理しています。もし割り当てられる領域がなかったら、GCはfailureとなります。コンカレントのサイクルが終わる前にOldがいっぱいになることがあり、そのときはスペースを空けます。CMSはフラグメンテーションが発生します。

G1GC

G1はリージョナルヒープです。リージョンごとに世代があります。GC時に特定のリージョンにオブジェクトを集めます。クリーンアップフェーズでリージョンが空になれば、別の世代のリージョン(同じでもよいが)として再利用します。G1にはYoungもOldもすべてGCするmixed collectionがあります。もしすべてのリージョンがいっぱいになってしまえば、evacuation failureとなります。evacuation failureになってしまうととても高コストな処理となり、すぐにフルGCが走ります。 GCのチューニングについてのアドバイスは「あまりチューンしない」ということです。サイズと希望停止時間(pause time goal)ぐらいを指定するだけでよいです。あとは、初期ヒープ占有の閾値が問題を起こすかもしれません。マーキングサイクルが長い場合に並列マークスレッドを増やすくらいでよいでしょう。YoungのTo領域がevacuation failureを引き起こしている場合は、-XX:G1ReservePercentの値を増やす方がいいです。 G1にもフラグメンテーションがあります。デフォルトでは5%ほどです。さらに巨大オブジェクトの問題もあります。巨大なオブジェクトをヒープに割り当てるとき、そのサイズがリージョンの50%未満なら単純に割り当てるだけです。50%以上でも割り当てられますが、もしサイズがリージョンより大きい場合はどうなるでしょうか?隣接した複数のリージョンを使います。そうすると、フラグメンテーションは発生してしまいます。ただし、巨大オブジェクトは数は少なく生存期間が短いことが多いので、問題にならないでしょう。もし数が多く生存期間が長ければ、evacuation failureを引き起こすかもしれません。Oldの占有率を増やしているでしょうから。 G1のGCログを見たとき、remarkポーズ時間が長く、Ref Procがあるならオプションをつけた方がよいでしょう(何のオプションか不明)。

セッションのまとめ

デフォルトのGCであれば、TenuringThresholdで世代サイズを設定しましょう。-XX:+UseAdaptiveSizePolicyも必要です。スループットにはYoung領域のサイズが重要です。 CMSであれば、Fractionと-XX:+UseCMSInitiatingOccupancyOnlyがマーキングの閾値を設定する助けになります。閾値はOld領域の占有率のパーセンテージで表現されます。CMSではプロモーションが早く、それがフラグメンテーションを発生させる原因ともなっています。 G1は、最大希望停止時間(max pause time goal)が重要です。あとはデフォルト値をしっかり知ることが大切です。G1はヒープ領域を2048のリージョンにわけ、各リージョンのサイズは1MBから32MBの間になります。アグレッシブな停止時間は設定しないこと!オーバーヘッドが増えるだけです。 最後はJavaパフォーマンス(http://www.amazon.co.jp/dp/4873117186/)読もうね!で終わりました。

jyukutyoコメント

JDK9ではG1がデフォルトになる予定のようです。ただ、CMSとG1のどちらを使うかという判断基準が私にはまだわかっていません。OpenJDKでのトラブルシューティングをされている方に話をうかがったところ、ヒープが8GBを超えるようならG1、それ以下であればリージョンが小さくなるためCMSでよい、と教えていただきました。ただし、CMSでフラグメンテーションが問題となるようなときは8GB未満でもG1でよいかもしれません。
ヒープが8GB未満であればG1を選択するメリットがないので、CMSでよい。8GB以上でレスポンスタイムを一定以下に抑えたいならG1、全体的なスループットを上げたいならCMSだがフラグメンテーションが起きるならG1にする。8GB以下でフラグメンテーションが起きるなら Parallelを選ぶのが基本戦略と改めて教えていただきました!ありがとうございます!


2015年11月10日

sakata

JavaOne 2015 サンフランシスコに参加しました!(1日目)

Hello World! コンテンツ・メディア第1事業部の、jyukutyoこと阪田です。

JavaOneとは

みなさんはJavaOneというイベント、カンファレンスをご存知でしょうか? JavaOneは、オラクル社(以前はサン・マイクロシステムズ)が1996年から毎年開催している、Javaに関する最大級のカンファレンスです。サンフランシスコで5日間、400以上のセッションがあります。朝から晩までJavaに浸っていられる、夢のような内容となっています。

私は今回海外出張としてJavaOneに”初”参加しました。このブログでその様子をレポートします。 まずこのエントリでは、サンフランシスコ国際空港に到着してから、1日目を終えるまでをレポートします。

移動について

日本からサンフランシスコは、関西国際空港からだと行きは飛行機で9時間で到着します。時差は16時間あるため、日本を夕方に出発しても、サンフランシスコに到着するとその日の午前中に逆戻りします。

CIMG1729

9時間のフライトとはいえ、離着陸や食事の時間があるため、それほど長時間眠ることはできず、到着すると疲労と睡魔を感じます。空港からJavaOneの会場となるユニオンスクエア近辺までは、電車に1本乗るだけで行けます。

CIMG1730

BARTと呼ばれるものです。「Powell St. Station」が直近の駅で、片道8ドルほどかかります。BARTのチケットを購入するのは少し難しいので、初めての方はサンフランシスコの高速鉄道BART(バート) [サンフランシスコ] All About などを参考に、事前に予習しておいた方がよいでしょう。ちなみに、私は予習していても少し詰まりました。

到着日はJavaOne開催日の前日でしたが、前日からRegistration(登録)できます。モスコーン・センターまたはヒルトン・サンフランシスコ・ユニオンスクエアで登録できます。私はヒルトンで登録しました。

CIMG1755

事前にメールで送られてくるQRコードを読み取り、パスとノベルティとして定番のJavaOneリュック、Duke Tシャツなどに加えて、水筒がもらえました。

CSH5pRWUwAAtmf9.jpg-largeCSH7yRKUcAAxWpM.jpg-large

キーノートレポート!

1日目はキーノート(基調講演)とユーザグループのセッションが主にあります。この日だけ、モスコーン・センターでの開催となります。 モスコーンはまさにお祭りのよう!長い通りがすべてカンファレンス施設で埋められています。実は、JavaOneと同時開催でOracle OpenWorld(OOW)というイベントも開催されており、モスコーンはOOWの方が主に使用するため、オラクル社の赤で統一されています。

CIMG1739

キーノートの会場は日本では考えられないくらい広く、軽く数千人は入る規模です。

CIMG1744

キーノートでの技術的な話題としては、「Project Jigsaw」と「Project Valhalla」、「Project Panama」です。と言っても、もう数年間ずっとこれしか出ていないわけですが、とくに劇的な進捗があるようにも見えませんでした。 Project Jigsawは、Javaのモジュール化のためのものです。新たなキーワードとして”module”を導入し、モジュールの依存関係と公開するパッケージを指定できます。たとえば、CommonsのライブラリBeanUtilsだと、以下のような感じになります。

BeanUtilsはcommons.loggingに依存していて、org.apache.commons.beanutilsパッケージを外部に公開していることになります。公開していないパッケージは、たとえpubclicなクラスが含まれていてもアクセスできないようになります。moduleはパッケージよりも上位の概念となります。こうして、JARが利用する外部パッケージと、JARが外部に公開するパッケージをそれぞれ決められるようになります。 Project ValhallaではValue Typesという新しい型が導入されます。以下のようなクラスがあるとします。

その配列”Point[]”を扱うとき、各要素は参照を経由していました。この場合、データへのアクセスにオーバーヘッドがあります。データをまとめて扱うようにしてCPUのキャッシュにおけば、キャッシュミスが減りパフォーマンスが向上します。そのようなときのために新たなキーワード”value”が導入されます。

こうすることで、Value Typeとして扱われるようになります。イミュータブルに限定されることに注意してください。 もう1つ、Project Valhallaでは”Specialized Generics”があります。ご存知の通り、Javaのジェネリクスではプリミティブ型は指定できず、代わりにラッパークラスを指定していました。

Specialized Genericsでプリミティブ型を直接指定できるようになります。

IntStreamなんていらなかったんや…そしてProject Panamaはあまり詳しい話はなかったように思います。 このあと、サン・マイクロソフト創業者のスコット・マクニーリがビデオで登場し、「Javaプログラマにとって最悪な12のこと」を読み上げ、盛り上がりは最高潮を迎えました。

ユーザグループセッションレポート!

ユーザグループのセッションでは、ウクライナのJUG(Java User Group)である「JUG.ua」の取り組みが非常に興味深かったです。 JUG.uaではAdopt a JSR(Java Specification Requests:Java仕様リクエスト)の活動として、どのJSRをサポートするかグループ内で話し合い、JSON-B仕様をサポートすることに決めました。そこから仕様のメーリングリストに入り、実装のサンドボックスをGitHubに作り、公開された質問や提案をグループ内で共有しました。それからグループからの質問やコメント、提案を出していきました。結果として60以上の提案やコメントを出し、そのうち30は組み込まれたそうです。 私も関西Javaエンジニアの会(KansaiJUG)というJUGを運営し、昨年JCPメンバーとなっています。今後のAdopt a JSRへの参画に、よいヒントをもらえたと考えています。

Java Lounge @ Oracle Welcome Reception

1日目の夜はウェルカムレセプションがあり、楽しい雰囲気で終わりました。

CIMG1748

1日目までのレポートは以上です。2日目以降のレポートもお楽しみに!


2014年09月25日

kunihira

ScalaMatsuriでEnjoy.Scala!の裏側

こんにちは。 Scalaで女性を幸せにするエンジニアの国平です。

前回の記事では、ScalaMatsuriの表側として参加レポートを書きました。

今回の記事では、スタッフやスポンサーとして参加して見えた裏側の話を少ししてみようと思います。

アンカンファレンス

アンカンファレンスは国内ではあまり事例のないイベントですが、今回翻訳チームとしても、登壇者としても活躍されていた横田さんの提案で導入されました。 スタッフ内でもアンカンファレンス経験者がほとんどいなかったため、本当に手探りで準備を進めていきました。 特に、アンカンファレンスは当日の参加者に委ねられる部分が大きいので、何を準備すればいいのかというところから議論を重ねて、事前にリハーサルをしたり、アンカンファレンスの説明文を何度も遂行したりしました。

結果的に、Odersky先生によるCodeClinicやパネルディスカッションなど、その場に集まった方々の発想が相互作用して素晴らしいセッションをつくり上げることが出来ました。

セッションスケジュールを調整している時、「これはすごいことになってきた!」という発言がありました。 この瞬間に私はアンカンファレンスが成功したと感じました。

翻訳チームの貢献

ScalaMatsuriは日本が誇る国際的なScalaカンファレンスで、海外からの招待講演者を始め英語のセッションが多く用意されていました。 とはいえ、そのまま英語オンリーでは、参加者のハードルが高くなってしまいます。 ScalaMatsuriでは、その問題を解消するためにScalaMatsuriスタッフのうち、英語が堪能なメンバーがセッション中同時翻訳で、英語<->日本語で翻訳を行い、IRCに投稿、それを表示するという事を行っていました。

この翻訳作業、複数人のチームワークで行われていたのですが、ScalaMatsuriは朝から夜まで、しかも2日間に渡って続くイベントですので、本当にセッション中ずっと翻訳作業をしてくださっていました。

私自身、カンファレンスのスクール形式で英語を聞き取るのはかなり難しかったので、非常にありがたかったですし、逆に海外から参加して頂いた方に対して、日本のScala界隈の情報を発信出来たのではないかと思います。

スポンサーCM

今回セッション間の休憩中にスポンサー各社のCMを放映しました。 放映させて頂いたフリューのCMがこちらです。

FuRyuScalaMatsuriCM from Kuchitama on Vimeo.

はい、しょぼいですね。 なんせこれ、私が片手間で作ったムービーなので…

ただ、他のスポンサー各社はかなり力を入れられていました。 他のCM動画を公開できなくて残念ですが、日本のScala利用企業のパワフルさが発揮されてるように思いました。 来年は弊社ももっと力をいれたCMを作りたいです

スタッフとして活動してみて

私は、たまたまScalaMatsuriがボランティアスタッフを募集していることを知り、参加することにしました。

関西在住なのでリモートでのミーティング参加でした。 最初は、リモート参加することに不安がありました。 しかし、ミーティング以外でのやりとりの大半はco-meetingを使ってオンライン上で行われていましたし、ミーティング時もco-meetingに発言した内容を適宜拾ってもらえたので、問題なく意見交換をすることが出来ました。

タスクも、リモートでも作業可能な内容のものも多くありました。今回は、アンカンファレンスの説明用のチラシ作成のみ担当しましたが、まだまだリモートでも作業できることはあると思っています。

まとめ

2回にわたって、ScalaMatsuri2014の参加レポートを報告させて頂きました。 ScalaMatsuriというイベントがあったこと、その場の雰囲気、盛り上がりを少しでも知って頂けたら幸いです。 2日目が終わって、撤収作業を進めているときに、すでに「来年」の話題になっていました。 今も、次回に向けて少しずつ準備しています。 もし、Scalaが大好きで日本のScalaコミュニティに貢献したいという方がいらっしゃれば、私と一緒にボランティアに申し込んでイベントを盛り上げましょう。

Let’s Enjoy.Scala !!


2014年09月12日

kasuya

#ScalaMatsuri 参加の所感

粕谷です。

国平がボランティアスタッフとしての視点から参加レポートを投稿していたScalaMatsuri。僕は去年のScala Conference 2013に続いての参加となります。

そこで、去年と比べてScalaコミュニティにどのような変化があったか、と言った視点を交えつつ参加レポートを書きたいと思います。

導入企業の増加

去年のScala Conferenceは、コミュニティのコアなメンバーが集まっていた濃い雰囲気がありましたが、今年はそれに比べて段違いにオープンな雰囲気になっていました。要因としては、参加人数の増加が考えられると思いますが、その中でも「Scalaを実際に導入して活用している企業」が大幅に増えている印象が強いです。

カンファレンス内でも各企業が導入・活用事例を紹介していましたが、それらも単なる活用事例というよりも、実際の運用ノウハウの共有などといった、一歩踏み込んだ内容が多かったです。

Scalaの導入事例で面白かったのは、弊社のようにJavaからの移行、という例はむしろ少なくて、RubyやPHPのような動的言語からの移行事例が多いようです。特にスピード感が求められるWeb開発において、運用中のシステム改修の安定化という観点で、静的言語を用いて改修の影響範囲をコンパイル時に検知したい、というニーズが強まり、その中でScalaが採用候補として選ばれるパターンが多いようです。

このあたりは我々がScalaを用いてソーシャルゲームの開発・運用をする際に重視している観点とも共通しています。特にソーシャルゲーム開発は短い開発期間でコードの広い範囲に手をいれるケースも多く、現状の我々の運用方法を考えると動的言語の採用は少し難しいところです。

求人数の増加

Scala導入企業の増加に伴い、当然の流れとして求人数も増加しています。各社ともスポンサーLTでは積極的に採用情報をお話されていました。中には人事部の人と一緒に参加された企業もありました。

ちなみにScalaMatsuri参加企業は東京を拠点とするところが多かったですが、弊社は京都にてScalaを用いた開発を行っておりますので、関西でScala導入企業を探しておられるエンジニアの皆さんはお気軽にご相談ください。弊社のキャリア採用ページはこちらになります。

アンカンファレンスでDDDを学ぶ

弊社では現在、始業前の30分間を利用して、週2日DDD本の読書会を開催しています。
2日目のアンカンファレンスではかとうじゅんいちさんがDDDのセッションを立ちあげられたので、そこに参加してきました。

ScalaとDDDは非常に相性が良い、というのはかとうさん以前からのお考えで、そういった事もあってScalaMatsuriにおけるDDDセッションは盛況でした。
我々も、素人の集まりの読書会ではなかなか議論をしていても明確な答えにたどり着けないものもあったりしますので、有識者と直接対話する機会を得たことは大きかったです。普段の読書会で頻繁に議論になる問題について、直接質問して知見をいただく事ができました。

Scalaという言語の裾野が拡がっている

今年のScalaMatsuriに参加して思ったことは、Scalaという言語が結構な勢いで裾野を拡げているな、ということです。
もちろん、まだ「メジャー言語」と呼ばれるほどの位置づけではありませんが、前述した動的言語からの移行事例などを聴いていると、今後もさらなる普及の可能性があるように感じます。

まだまだフロンティアな世界でもあるScalaの世界。我々と一緒に開拓していきませんか?