This document discusses and compares Neptune and JanusGraph graph databases. It provides an overview of Neptune's features like multi-AZ deployment and storage in S3. It also describes how to access Neptune using Gremlin and SPARQL query languages. The document then introduces JanusGraph and notes some key differences when using Gremlin APIs with Neptune versus JanusGraph. It shares the results of a performance test loading Amazon product graph data into both systems. Finally, it discusses options for loading and querying data between Neptune, Athena, Kinesis and other AWS services.
This document discusses and compares Neptune and JanusGraph graph databases. It provides an overview of Neptune's features like multi-AZ deployment and storage in S3. It also describes how to access Neptune using Gremlin and SPARQL query languages. The document then introduces JanusGraph and notes some key differences when using Gremlin APIs with Neptune versus JanusGraph. It shares the results of a performance test loading Amazon product graph data into both systems. Finally, it discusses options for loading and querying data between Neptune, Athena, Kinesis and other AWS services.
Scala Refactoring for Fun and Profit (Japanese subtitles)Tomer Gabel
A talk given at Scala Matsuri 2016 in Tokyo, Japan.
New Scala practitioners often experience the uncomfortable feeling of "not quite getting it." If you've studied the syntax and written tests, maybe production code; if you're becoming comfortable with the language and libraries, but keep worrying that there's "a better way", or that your code isn't "idiomatic enough" - this session is for you.
By refactoring a real, live codebase, this talk will provide you with new tools and increased confidence. Between the provided examples and the ensuing discussion, you will walk away with a better feel for Scala and how to employ it in the real world.
- The document discusses how Scala code is compiled to Java Virtual Machine (JVM) bytecodes. It begins with an introduction to Koichi Sakata, the presenter, and an overview that the session will look at JVM bytecodes for beginners.
- The presentation then asks if attendees know what happens when Scala code is compiled. It is explained that Scala code, like code from other JVM languages, is compiled to class files that contain JVM bytecodes.
- An example Java class file is opened in a binary editor to show the JVM bytecode format. It is explained that class files have a defined format with elements like magic number, version, and bytecode instructions.
This document contains the slides from a talk given by Konrad Malawski on the "Tao/Zen of Programming" using Akka. Some of the key points discussed include:
- Actors are meant to work together and each actor should focus on a single responsibility. Having only one actor limits its capabilities.
- Actors should be structured in a hierarchy with parent-child relationships to allow for supervision. Actors should also be named meaningfully based on their purpose.
- Blocking operations can starve other actors by monopolizing shared resources. Blocking code needs to be isolated on dedicated dispatchers.
- Messages should be processed asynchronously using for/flatMap instead of awaiting futures to avoid blocking
This document discusses Scala and related topics. It includes sections on Scala programming, functional programming concepts in Scala using streams and filters, and data visualization tools that can be used with Scala including Apache Zeppelin, Google Data Studio, and Tableau. It also lists several open source streaming and messaging systems that can be used with Scala such as Apache Kafka, Apache Pulsar, and Amazon Kinesis.
Vector and ListBuffer have similar performance for random reads. Benchmarking showed no significant difference in throughput, average time, or sample times between reading randomly from a Vector versus a ListBuffer. Vectors are generally faster than Lists for random access due to Vectors being implemented as arrays under the hood.
12. • しかし、JVM環境でのMemory Mapped Fileは2GBまでしか
マッピングできません。
http://stackoverflow.com/questions/8076472/why-does-
filechannel-map-take-up-to-integer-max-value-of-data
• Apache Spark MLlib開発責任者のReynold XinさんがGistに
ByteBufferシリーズのパフォーマンス計測を記述していま
す。
これはScalaで書かれていてとても参考になります。
https://gist.github.com/rxin/5087680
more information
MMF can map only map up to 2GB file on JVM.
13. 爆速 No.1
Memory Mapped Fileで
高速ファイル操作が可能に!
No.1 using MMF, you can operate on files at high speed!
19. • for内包表記 と flatMap & map は論理的に同じです。
• 下記はデコンパイルしたコードですが全く同じです。
Why are they the same speed?
for comprehension and flatMap&map are logically same.
public Option<String> forComprehension()
{
data().flatMap(new AbstractFunction1()
{
public static final long serialVersionUID = 0L;
public final Option<String> apply(Some<String> a)
{
a.map(new AbstractFunction1()
{
public static final long serialVersionUID = 0L;
public final String apply(String b)
{
return b;
}
});
}
});
}
public Option<String> flatMapAndMap()
{
data().flatMap(new AbstractFunction1()
{
public static final long serialVersionUID = 0L;
public final Option<String> apply(Some<String> a)
{
a.map(new AbstractFunction1()
{
public static final long serialVersionUID = 0L;
public final String apply(String b)
{
return b;
}
});
}
});
}
for comprehension flatMap & map
20. 爆速 No.2
for内包表記 と flatMap & map は
バイト・コードのレベルで同じです。
No.2 for comprehension and flatMap&map are same.
28. Why is ArrayBuffer faster than Vector?
新しく要素を追加するときのコードを比較してみます。
These processes are absolutely different.
新しいインスタンスに既存の
要素をコピーしてから新しい
要素を追加します。
インスタンスのリサイズを行っ
てから末尾の要素を新要素で
更新します。
var Vector val ArrayBuffer
val b = bf(repr)
b ++= thisCollection
b += elem
b.result()
ensureSize(size0 + 1)
array(size0) =
elem.asInstanceOf[AnyRef]
size0 += 1
this
Vector と ArrayBuffer でプロセスが全く異なります。
29. Q3-2
可変な “var xs: List”
と
不変な “val xs: ListBuffer”
先頭挿入が速いのはどちらでしょう?
When inserting into List or ListBuffer, which is faster?
32. benchmark
List の方が ListBuffer よりも速いです。
List is faster than ListBuffer.
n回先頭挿入したときのThroughput
上記のグラフはN個の要素を先頭に追加したときのスループットを表しています。
例えばtypeがList, timesが1kの場合では、1,000個の要素を空のListの先頭に挿
入していったときのスループットを意味しています。
34. Why is List faster than the others?
要素を先頭挿入するときのコードを比較してみます。
List calculate a little, in case of inserting.
Listは先頭とその他の要素を
別管理しているため、新しい
要素をすぐに作れます。
ListBufferはListとほとんど
一緒なのですが内部変数の再
代入が行われます。
var List val ListBuffer
new
scala.collection.immutable
.::(x, this)
if (exported) copy()
val newElem = new :: (x, start)
if (isEmpty) last0 = newElem
start = newElem
len += 1
this
List ではほとんど計算せずに先頭挿入が行えます。
35. 爆速 No.3
末尾追加のときは ArrayBuffer や
ListBuffer を使うと効率が良いです。
しかし先頭挿入のときは List を使うと
良いパフォーマンスが得られます。
No.3 appending => **Buffer, inserting => List are nice.
37. Q4
可変な “var xs: List”
と
不変な “val xs: ListBuffer”
削除が速いのはどちらでしょう?
When removing from List or ListBuffer, which is faster?
38. var List
A
val ListBuffer
B
code
var xs: List val xs: ListBuffer
var xs =
List( 1 to n: _* )
// head
xs = xs.tail
// tail
xs = xs.dropRight(0)
var xs =
ListBuffer( 1 to n: _* )
// head
xs.remove(0)
// tail
xs.remove(xs.size - 1)
40. benchmark
ListBuffer は List よりも相当速いです。
ListBuffer is much faster than List.
n回削除したときのThroughput
上記のグラフはN個の要素をサイズNのコレクションから削除したときのスループットを
表しています。
例えば、Benchmark:removeTail, type:List, times:1kの場合では サイズ1,000のList
の末尾から1,000回要素削除を行ったときのスループットを意味します。
42. Why is ListBuffer faster than List?
要素を削除するときのコードを比較してみます。
The operation dropRight of List takes time O(n).
ListのdropRightの操作はO(n)
の時間がかかります。
ListBufferのremove操作は定
数時間です。
var List val ListBuffer
def dropRight(n: Int): Repr = {
val b = newBuilder
var these = this
var lead = this drop n
while (!lead.isEmpty) {
b += these.head
these = these.tail
lead = lead.tail
}
b.result()
}
def remove(n: Int): A = {
:
var cursor = start
var i = 1
while (i < n) {
cursor = cursor.tail
i += 1
}
old = cursor.tail.head
if (last0 eq cursor.tail) last0 =
cursor.asInstanceOf[::[A]]
cursor.asInstanceOf[::[A]].tl
= cursor.tail.tail
43. benchmark of List’s dropRight
このベンチマークは10倍づつサイズを増やしているので、ス
ループットも底10で対数表示します。
Throughput is just only lowered to linear.
スループットはただ線形に下降しているだけです。
操作時間線形増加の恐怖です。
Q3で出てきたVectorの末尾追加も線形増加なのですが、同じ線形増加でも削除のほうが
増加率が大きいので、パフォーマンスがすごく落ちているように感じます。
List - dropRightのlog(Throughput)
44. reference benchmark
Comparing dropRight with take.
dropRight(1) と take(n-1) で同じ機能を実現できる
ので、dropRight と take を比較しました。
take は dropRight より少しだけ速いです。
Throughput of List’ dropRight and take
45. 爆速 No.4
たくさんの要素を削除するときは
ListBuffer や ArrayBuffer を使うと
効率が良いです。
No.4 When removing element, **Buffer are good.
削除に限らずなんですが、基本的にはimmutableなオブジェクトよりもmutableな
Buffer系の方が書き込み操作は速いです。
48. Vector
A
ListBuffer
B
code
val data =
Vector( 1 to n: _* )
( 1 to data.size ) map { _ =>
data( Random.nextInt( n ) )
}
val data =
ListBuffer( 1 to n: _* )
( 1 to data.size ) map { _ =>
data( Random.nextInt( n ) )
}
56. Stream
A
Array
B
* 再帰的に計算します。
* 計算量O(n)のロジック
です。
code
def fibonacci(
h: Int = 1,
n: Int = 1 ): Stream[Int] =
h #:: fibonacci( n, h + n )
val fibo = fibonacci().take( n )
def fibonacci( n: Int = 1 ): Array[Int] =
if ( n == 0 ) {
Array.empty[Int]
} else {
val b = new Array[Int](n)
b(0) = 1
for ( i <- 0 until n - 1 ) {
val n1 = if ( i == 0 ) 0 else b( i - 1 )
val n2 = b( i )
b( i + 1 ) = n1 + n2
}
b
}
val fibo = fibonacci( n )
59. Why is Stream so much faster?
Stream implements lazy list evaluated when needed.
• Stream は遅延評価リストを実装しているので必要なときに
だけ計算されます。
• 実際fibonacciメソッド(前ページ)を呼び出した時点ではフィ
ボナッチ数列はまだ計算されていません。
• これが遅延評価の力です。
• しかし数列が具現化されるときにはそれなりの計算時間を
必要とします。
→ 次ページをごらんください。
60. Why is Stream so much faster?
if the sequence is materialized, it takes calculating time.
Stream の toList を実行したときのベンチマークです。
Stream で toList を実行すると、Array が最も速いです。
これは Array で使っている計算ロジックが再帰による計算
よりも速いことを示します。
長さnのフィボナッチ数列をつくったときのスループット
63. Showing the benchmark of w+w
正規表現はCPUリソースをたくさん消費します。
特に、“ww..w”のようなバック・トラッキングが発生
する表現では計算量O(n^2)となります。
Regular Expression consumes CPU resource a lot.
下のグラフは正規表現のパフォーマンスです。
各正規表現1,000回実行時のスループット
65. 同じ
A
findPrefixOf
B
code
val re = """(?<=w+)/.+""" r
val ms = re findAllIn data
if ( ms.isEmpty ) None
else Some( ms.next )
val re = “""w+/""" r
re findPrefixMatchOf data map(
_.after.toString
)
findAllIn と 肯定的後読み findPrefixOf と 量指定子
69. benchmark of various regular expressions
Even if given same regex, findPrefixOf is fastest.
同じ正規表現を実行しても findPrefixOf が一番速いです。
findPrefixOf と 肯定的後読みの組み合わせは良いパフォーマンスが
得られます。
1,000回実行時のスループット
70. findPrefixOf usage in famous library
ルーティング・ツリーはURIパスの先頭から構築するので、
findAllIn よりも findPrefixOf が適しています。
findPrefixOf is used in spray-routing.
implicit def regex2PathMatcher(regex: Regex): PathMatcher1[String] =
regex.groupCount match {
case 0 ⇒ new PathMatcher1[String] {
def apply(path: Path) = path match {
case Path.Segment(segment, tail) ⇒ regex findPrefixOf segment match {
case Some(m) ⇒ Matched(segment.substring(m.length) :: tail, m :: HNil)
case None ⇒ Unmatched
}
case _ ⇒ Unmatched
}
}
:
https://github.com/spray/spray/blob/master/spray-routing/src/main/scala/spray/routing/PathMatcher.scala
PathMatcher.scala line:211
下記は spray-routing のコードを一部抜粋したものです。