SlideShare a Scribd company logo
1 of 100
Download to read offline
ScalaBlitz 
Efficient Collections Framework
What’s a Blitz?
Blitz-chess is a style of 
rapid chess play.
Blitz-chess is a style of 
rapid chess play.
Knights have horses.
Horses run fast.
def mean(xs: Array[Float]): Float = 
xs.par.reduce(_ + _) / xs.length
With Lists, operations 
can only be executed 
from left to right
1 2 4 8
1 2 4 8 
Not your typical list.
Bon app.
Apparently not enough
No amount of 
documentation is 
apparently enough
The reduceLeft 
guarantees operations are 
executed from left to right
Parallel and sequential 
collections sharing operations
There are several 
problems here
How we see users
How users 
see the docs
Bending the truth.
And sometimes we 
were just slow
So, we have a new API now 
def findDoe(names: Array[String]): Option[String] = 
{ 
names.toPar.find(_.endsWith(“Doe”)) 
}
Wait, you renamed a 
method? 
def findDoe(names: Array[String]): Option[String] = 
{ 
names.toPar.find(_.endsWith(“Doe”)) 
}
Yeah, par already exists. 
But, toPar is different. 
def findDoe(names: Array[String]): Option[String] = 
{ 
names.toPar.find(_.endsWith(“Doe”)) 
}
def findDoe(names: Array[String]): Option[String] = { 
names.toPar.find(_.endsWith(“Doe”)) 
} 
implicit class ParOps[Repr](val r: Repr) extends AnyVal { 
def toPar = new Par(r) 
}
def findDoe(names: Array[String]): Option[String] = { 
ParOps(names).toPar.find(_.endsWith(“Doe”)) 
} 
implicit class ParOps[Repr](val r: Repr) extends AnyVal { 
def toPar = new Par(r) 
}
def findDoe(names: Array[String]): Option[String] = { 
ParOps(names).toPar.find(_.endsWith(“Doe”)) 
} 
implicit class ParOps[Repr](val r: Repr) extends AnyVal { 
def toPar = new Par(r) 
} 
class Par[Repr](r: Repr)
def findDoe(names: Array[String]): Option[String] = { 
(new Par(names)).find(_.endsWith(“Doe”)) 
} 
implicit class ParOps[Repr](val r: Repr) extends AnyVal { 
def toPar = new Par(r) 
} 
class Par[Repr](r: Repr)
def findDoe(names: Array[String]): Option[String] = { 
(new Par(names)).find(_.endsWith(“Doe”)) 
} 
class Par[Repr](r: Repr) 
But, Par[Repr] does not 
have the find method!
def findDoe(names: Array[String]): Option[String] = { 
(new Par(names)).find(_.endsWith(“Doe”)) 
} 
class Par[Repr](r: Repr) 
True, but Par[Array[String]] 
does have a find method.
def findDoe(names: Array[String]): Option[String] = { 
(new Par(names)).find(_.endsWith(“Doe”)) 
} 
class Par[Repr](r: Repr) 
implicit class ParArrayOps[T](pa: Par[Array[T]]) { 
... 
def find(p: T => Boolean): Option[T] 
... 
}
More flexible!
More flexible! 
● does not have to implement methods that 
make no sense in parallel
More flexible! 
● does not have to implement methods that 
make no sense in parallel 
● slow conversions explicit
No standard library collections were 
hurt doing this.
More flexible! 
● does not have to implement methods that 
make no sense in parallel 
● slow conversions explicit 
● non-intrusive addition to standard library
More flexible! 
● does not have to implement methods that 
make no sense in parallel 
● slow conversions explicit 
● non-intrusive addition to standard library 
● easy to add new methods and collections
More flexible! 
● does not have to implement methods that 
make no sense in parallel 
● slow conversions explicit 
● non-intrusive addition to standard library 
● easy to add new methods and collections 
● import switches between implementations
def findDoe(names: Seq[String]): Option[String] = { 
names.toPar.find(_.endsWith(“Doe”)) 
}
def findDoe(names: Seq[String]): Option[String] = { 
names.toPar.find(_.endsWith(“Doe”)) 
}
def findDoe(names: Seq[String]): Option[String] = { 
names.toPar.find(_.endsWith(“Doe”)) 
} 
But how do I write generic code?
def findDoe[Repr[_]](names: Par[Repr[String]]) = { 
names.toPar.find(_.endsWith(“Doe”)) 
}
def findDoe[Repr[_]](names: Par[Repr[String]]) = { 
names.toPar.find(_.endsWith(“Doe”)) 
} 
Par[Repr[String]]does not 
have a find
def findDoe[Repr[_]: Ops](names: Par[Repr[String]]) = { 
names.toPar.find(_.endsWith(“Doe”)) 
}
def findDoe[Repr[_]: Ops](names: Par[Repr[String]]) = { 
names.toPar.find(_.endsWith(“Doe”)) 
} 
We don’t do this.
Make everything as simple as 
possible, but not simpler.
def findDoe(names: Reducable[String])= { 
names.find(_.endsWith(“Doe”)) 
}
def findDoe(names: Reducable[String])= { 
names.find(_.endsWith(“Doe”)) 
} 
findDoe(Array(1, 2, 3).toPar)
def findDoe(names: Reducable[String])= { 
names.find(_.endsWith(“Doe”)) 
} 
findDoe(toReducable(Array(1, 2, 3).toPar))
def findDoe(names: Reducable[String])= { 
names.find(_.endsWith(“Doe”)) 
} 
findDoe(toReducable(Array(1, 2, 3).toPar)) 
def arrayIsReducable[T]: IsReducable[T] = { … }
So let’s write a program!
import scala.collection.par._ 
val pixels = new Array[Int](wdt * hgt) 
for (idx <- (0 until (wdt * hgt)).toPar) { 
}
import scala.collection.par._ 
val pixels = new Array[Int](wdt * hgt) 
for (idx <- (0 until (wdt * hgt)).toPar) { 
val x = idx % wdt 
val y = idx / wdt 
}
import scala.collection.par._ 
val pixels = new Array[Int](wdt * hgt) 
for (idx <- (0 until (wdt * hgt)).toPar) { 
val x = idx % wdt 
val y = idx / wdt 
pixels(idx) = computeColor(x, y) 
}
import scala.collection.par._ 
val pixels = new Array[Int](wdt * hgt) 
for (idx <- (0 until (wdt * hgt)).toPar) { 
val x = idx % wdt 
val y = idx / wdt 
pixels(idx) = computeColor(x, y) 
} 
Scheduler not found!
import scala.collection.par._ 
import Scheduler.Implicits.global 
val pixels = new Array[Int](wdt * hgt) 
for (idx <- (0 until (wdt * hgt)).toPar) { 
val x = idx % wdt 
val y = idx / wdt 
pixels(idx) = computeColor(x, y) 
}
import scala.collection.par._ 
import Scheduler.Implicits.global 
val pixels = new Array[Int](wdt * hgt) 
for (idx <- (0 until (wdt * hgt)).toPar) { 
val x = idx % wdt 
val y = idx / wdt 
pixels(idx) = computeColor(x, y) 
}
New parallel collections 
33% faster! 
Now 
103 ms 
Previously 
148 ms
Workstealing tree scheduler 
rocks!
Workstealing tree scheduler 
rocks! 
But, are there other interesting 
workloads?
Fine-grained uniform 
workloads are on the opposite 
side of the spectrum.
def mean(xs: Array[Float]): Float = { 
val sum = xs.toPar.fold(0)(_ + _) 
sum / xs.length 
}
def mean(xs: Array[Float]): Float = { 
val sum = xs.toPar.fold(0)(_ + _) 
sum / xs.length 
} 
Now 
Previously 
15 ms 
565 ms
But how?
def fold[T](a: Iterable[T])(z:T)(op: (T, T) => T) = { 
var it = a.iterator 
var acc = z 
while (it.hasNext) { 
acc = op(acc, it.next) 
} 
acc 
}
def fold[T](a: Iterable[T])(z:T)(op: (T, T) => T) = { 
var it = a.iterator 
var acc = z 
while (it.hasNext) { 
acc = box(op(acc, it.next)) 
} 
acc 
}
def fold[T](a: Iterable[T])(z:T)(op: (T, T) => T) = { 
var it = a.iterator 
var acc = z 
while (it.hasNext) { 
acc = box(op(acc, it.next)) 
} 
acc 
} 
Generic methods cause boxing of primitives
def mean(xs: Array[Float]): Float = { 
val sum = xs.toPar.fold(0)(_ + _) 
sum / xs.length 
}
def mean(xs: Array[Float]): Float = { 
val sum = xs.toPar.fold(0)(_ + _) 
sum / xs.length 
} 
Generic methods hurt performance 
What can we do instead?
def mean(xs: Array[Float]): Float = { 
val sum = xs.toPar.fold(0)(_ + _) 
sum / xs.length 
} 
Generic methods hurt performance 
What can we do instead? 
Inline method body!
def mean(xs: Array[Float]): Float = { 
val sum = { 
var it = xs.iterator 
var acc = 0 
while (it.hasNext) { 
acc = acc + it.next 
} 
acc 
} 
sum / xs.length 
}
def mean(xs: Array[Float]): Float = { 
val sum = { 
var it = xs.iterator 
var acc = 0 
while (it.hasNext) { 
acc = acc + it.next 
} 
acc 
} 
sum / xs.length 
} 
Specific type 
No boxing! 
No memory allocation!
def mean(xs: Array[Float]): Float = { 
val sum = { 
var it = xs.iterator 
var acc = 0 
while (it.hasNext) { 
acc = acc + it.next 
} 
acc 
} 
sum / xs.length 
} 
Specific type 
No boxing! 
No memory allocation! 
565 ms → 281 ms 
2X speedup
def mean(xs: Array[Float]): Float = { 
val sum = { 
var it = xs.iterator 
var acc = 0 
while (it.hasNext) { 
acc = acc + it.next 
} 
acc 
} 
sum / xs.length 
}
def mean(xs: Array[Float]): Float = { 
val sum = { 
var it = xs.iterator 
var acc = 0 
while (it.hasNext) { 
acc = acc + it.next 
} 
acc 
} 
sum / xs.length 
} 
Iterators? For Array? 
We don’t need them!
def mean(xs: Array[Float]): Float = { 
val sum = { 
var i = 0 
val until = xs.size 
var acc = 0 
while (i < until) { 
acc = acc + a(i) 
i = i + 1 
} 
acc 
} 
sum / xs.length 
} 
Use index-based access!
def mean(xs: Array[Float]): Float = { 
val sum = { 
var i = 0 
val until = xs.size 
var acc = 0 
while (i < until) { 
acc = acc + a(i) 
i = i + 1 
} 
acc 
} 
sum / xs.length 
} 
Use index-based access! 
281 ms → 15 ms 
19x speedup
Are those optimizations parallel-collections specific?
Are those optimizations parallel-collections specific? 
No
Are those optimizations parallel-collections specific? 
No 
You can use them on sequential collections
def mean(xs: Array[Float]): Float = { 
val sum = xs.fold(0)(_ + _) 
sum / xs.length 
}
import scala.collections.optimizer._ 
def mean(xs: Array[Float]): Float = optimize{ 
val sum = xs.fold(0)(_ + _) 
sum / xs.length 
}
import scala.collections.optimizer._ 
def mean(xs: Array[Float]): Float = optimize{ 
val sum = xs.fold(0)(_ + _) 
sum / xs.length 
} 
You get 38 times speedup!
Future work
@specialized collections 
● Maps 
● Sets 
● Lists 
● Vectors 
Both faster & 
consuming less 
memory
@specialized collections 
● Maps 
● Sets 
● Lists 
● Vectors 
Both faster & 
consuming less 
memory 
Expect to get this for free inside 
optimize{} block
jdk8-style streams(parallel views) 
● Fast 
● Lightweight 
● Expressive API 
● Optimized 
Lazy data-parallel 
operations made 
easy
Future’s based asynchronous API 
val sum = future{ xs.sum } 
val normalized = sum.andThen(sum => sum/xs.size) 
Boilerplate code, ugly
Future’s based asynchronous API 
val sum = xs.toFuture.sum 
val scaled = xs.map(_ / sum) 
● Simple to use 
● Lightweight 
● Expressive API 
● Optimized 
Asynchronous data-parallel 
operations 
made easy
Current research: operation fusion 
val minMaleAge = people.filter(_.isMale) 
.map(_.age).min 
val minFemaleAge = people.filter(_.isFemale) 
.map(_.age).min
Current research: operation fusion 
val minMaleAge = people.filter(_.isMale) 
.map(_.age).min 
val minFemaleAge = people.filter(_.isFemale) 
.map(_.age).min 
● Requires up to 3 times more memory than original collection 
● Requires 6 traversals of collections
Current research: operation fusion 
val minMaleAge = people.filter(_.isMale) 
.map(_.age).min 
val minFemaleAge = people.filter(_.isFemale) 
.map(_.age).min 
● Requires up to 3 times more memory than original collection 
● Requires 6 traversals of collections 
We aim to reduce this to single traversal with no 
additional memory. 
Without you changing your code

More Related Content

What's hot

Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kirill Rozov
 
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...PROIDEA
 
Scala for Java Developers - Intro
Scala for Java Developers - IntroScala for Java Developers - Intro
Scala for Java Developers - IntroDavid Copeland
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceAlexey Raga
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Jonas Bonér
 
Switching from java to groovy
Switching from java to groovySwitching from java to groovy
Switching from java to groovyPaul Woods
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kirill Rozov
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Leonardo Borges
 

What's hot (16)

A bit about Scala
A bit about ScalaA bit about Scala
A bit about Scala
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
 
Scala for Java Developers - Intro
Scala for Java Developers - IntroScala for Java Developers - Intro
Scala for Java Developers - Intro
 
Type classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritanceType classes 101 - classification beyond inheritance
Type classes 101 - classification beyond inheritance
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
 
Switching from java to groovy
Switching from java to groovySwitching from java to groovy
Switching from java to groovy
 
20170509 rand db_lesugent
20170509 rand db_lesugent20170509 rand db_lesugent
20170509 rand db_lesugent
 
Kotlin standard
Kotlin standardKotlin standard
Kotlin standard
 
Scala collection
Scala collectionScala collection
Scala collection
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
 
Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012Continuation Passing Style and Macros in Clojure - Jan 2012
Continuation Passing Style and Macros in Clojure - Jan 2012
 
P3 2017 python_regexes
P3 2017 python_regexesP3 2017 python_regexes
P3 2017 python_regexes
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
Scala - en bedre Java?
Scala - en bedre Java?Scala - en bedre Java?
Scala - en bedre Java?
 

Similar to ScalaBlitz

(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?Tomasz Wrobel
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
Scala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereldScala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereldWerner Hofstra
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Philip Schwarz
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meetMario Fusco
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksSeniorDevOnly
 
Scala Refactoring for Fun and Profit
Scala Refactoring for Fun and ProfitScala Refactoring for Fun and Profit
Scala Refactoring for Fun and ProfitTomer Gabel
 
Functional programming with_scala
Functional programming with_scalaFunctional programming with_scala
Functional programming with_scalaRaymond Tay
 
Monadologie
MonadologieMonadologie
Monadologieleague
 
Scala Back to Basics: Type Classes
Scala Back to Basics: Type ClassesScala Back to Basics: Type Classes
Scala Back to Basics: Type ClassesTomer Gabel
 

Similar to ScalaBlitz (20)

(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?(How) can we benefit from adopting scala?
(How) can we benefit from adopting scala?
 
Scala
ScalaScala
Scala
 
Meet scala
Meet scalaMeet scala
Meet scala
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Scala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereldScala: Functioneel programmeren in een object georiënteerde wereld
Scala: Functioneel programmeren in een object georiënteerde wereld
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
Quicksort - a whistle-stop tour of the algorithm in five languages and four p...
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risks
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
Scala Refactoring for Fun and Profit
Scala Refactoring for Fun and ProfitScala Refactoring for Fun and Profit
Scala Refactoring for Fun and Profit
 
Functional programming with_scala
Functional programming with_scalaFunctional programming with_scala
Functional programming with_scala
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 
Monadologie
MonadologieMonadologie
Monadologie
 
Java Cheat Sheet
Java Cheat SheetJava Cheat Sheet
Java Cheat Sheet
 
Scala Back to Basics: Type Classes
Scala Back to Basics: Type ClassesScala Back to Basics: Type Classes
Scala Back to Basics: Type Classes
 

Recently uploaded

Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfproinshot.com
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...masabamasaba
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 

Recently uploaded (20)

Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 

ScalaBlitz