-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3a20685
commit c974f9e
Showing
22 changed files
with
339 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package benchmark.bench | ||
|
||
trait Bench { | ||
val RecordCount: Int = 1_000_000 | ||
val StreamIterations: Int = 1 | ||
val SearchIterations: Int = 1 | ||
|
||
val tasks: List[Task] = List( | ||
Task("Insert Records", RecordCount, insertRecords), | ||
Task("Stream Records", StreamIterations, streamRecords), | ||
Task("Search Each Record", StreamIterations * RecordCount, searchEachRecord), | ||
Task("Search All Records", StreamIterations, searchAllRecords) | ||
) | ||
|
||
def init(): Unit | ||
|
||
protected def insertRecords(status: StatusCallback): Unit | ||
|
||
protected def streamRecords(status: StatusCallback): Unit | ||
|
||
protected def searchEachRecord(status: StatusCallback): Unit | ||
|
||
protected def searchAllRecords(status: StatusCallback): Unit | ||
|
||
def dispose(): Unit | ||
} |
9 changes: 9 additions & 0 deletions
9
benchmark/src/main/scala/benchmark/bench/BenchmarkReport.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package benchmark.bench | ||
|
||
import fabric.rw.RW | ||
|
||
case class BenchmarkReport(name: String, maxProgress: Double, logs: List[StatusLog]) | ||
|
||
object BenchmarkReport { | ||
implicit val rw: RW[BenchmarkReport] = RW.gen | ||
} |
7 changes: 7 additions & 0 deletions
7
benchmark/src/main/scala/benchmark/bench/ReportGenerator.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package benchmark.bench | ||
|
||
object ReportGenerator { | ||
def main(args: Array[String]): Unit = { | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package benchmark.bench | ||
|
||
import benchmark.bench.impl.LightDBBench | ||
import fabric.io.JsonFormatter | ||
import fabric.rw.Convertible | ||
import lightdb.duckdb.DuckDBIndexer | ||
import lightdb.h2.H2Indexer | ||
import lightdb.halo.HaloDBStore | ||
import lightdb.lucene.LuceneIndexer | ||
import lightdb.mapdb.MapDBStore | ||
import lightdb.rocks.RocksDBStore | ||
import lightdb.sqlite.SQLiteIndexer | ||
import lightdb.store.{AtomicMapStore, MapStore} | ||
|
||
import java.nio.file.{Files, Path} | ||
|
||
object Runner { | ||
val implementations: Map[String, Bench] = Map( | ||
"ldbHaloLucene" -> LightDBBench(HaloDBStore, LuceneIndexer), | ||
"ldbMapLucene" -> LightDBBench(MapDBStore, LuceneIndexer), | ||
"ldbRocksLucene" -> LightDBBench(RocksDBStore, LuceneIndexer), | ||
"ldbAtomicLucene" -> LightDBBench(AtomicMapStore, LuceneIndexer), | ||
"ldbMapLucene" -> LightDBBench(MapStore, LuceneIndexer), | ||
"ldbHaloSQLite" -> LightDBBench(HaloDBStore, SQLiteIndexer), | ||
"ldbHaloH2" -> LightDBBench(HaloDBStore, H2Indexer), | ||
"ldbHaloDuck" -> LightDBBench(HaloDBStore, DuckDBIndexer), | ||
) | ||
|
||
def main(args: Array[String]): Unit = { | ||
args.headOption match { | ||
case Some(implName) if implementations.contains(implName) => | ||
val bench = implementations(implName) | ||
scribe.info(s"Initializing $implName benchmark...") | ||
bench.init() | ||
scribe.info(s"Initialized successfully!") | ||
val reports = bench.tasks.map { task => | ||
val status = StatusCallback() | ||
status.start() | ||
scribe.info(s"Executing ${task.name} task...") | ||
task.f(status) | ||
status.finish() | ||
val logs = status.logs | ||
scribe.info(s"Completed in ${logs.last.elapsed} seconds") | ||
BenchmarkReport(task.name, task.maxProgress, logs) | ||
} | ||
scribe.info(s"Disposing $implName benchmark...") | ||
bench.dispose() | ||
scribe.info(s"Disposed!") | ||
|
||
val json = reports.json | ||
Files.writeString(Path.of(s"report-$implName.json"), JsonFormatter.Default(json)) | ||
|
||
sys.exit(0) | ||
case Some(implName) => scribe.error(s"Invalid implementation name: $implName. Valid implementations: ${implementations.keys.mkString(", ")}") | ||
case None => scribe.error(s"Exactly one command-line argument must be present to specify the implementation. Valid implementations: ${implementations.keys.mkString(", ")}") | ||
} | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
benchmark/src/main/scala/benchmark/bench/StatusCallback.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package benchmark.bench | ||
|
||
import com.google.common.util.concurrent.AtomicDouble | ||
import com.sun.management.OperatingSystemMXBean | ||
|
||
import java.lang.management.ManagementFactory | ||
|
||
case class StatusCallback(every: Long = 1_000L) { | ||
val progress = new AtomicDouble(0.0) | ||
|
||
def logs: List[StatusLog] = _logs.reverse | ||
|
||
private var keepAlive = true | ||
private val startTime = System.currentTimeMillis() | ||
private var _logs = List.empty[StatusLog] | ||
|
||
def start(): Unit = { | ||
val t = new Thread { | ||
setDaemon(true) | ||
|
||
override def run(): Unit = { | ||
while (keepAlive) { | ||
report() | ||
Thread.sleep(every) | ||
} | ||
} | ||
} | ||
t.start() | ||
} | ||
|
||
def finish(): Unit = { | ||
keepAlive = false | ||
report() | ||
} | ||
|
||
private def report(): Unit = { | ||
val now = System.currentTimeMillis() | ||
val elapsed = (now - startTime) / 1000.0 | ||
val memory = ManagementFactory.getMemoryMXBean | ||
val heap = memory.getHeapMemoryUsage | ||
val nonHeap = memory.getNonHeapMemoryUsage | ||
val heapUsed = heap.getUsed | ||
val nonHeapUsed = nonHeap.getUsed | ||
val os = ManagementFactory.getPlatformMXBean(classOf[OperatingSystemMXBean]) | ||
val cpuLoad = os.getProcessCpuLoad | ||
val cpuTime = os.getProcessCpuTime | ||
val log = StatusLog( | ||
progress = progress.get(), | ||
timeStamp = now, | ||
elapsed = elapsed, | ||
heap = heapUsed, | ||
nonHeap = nonHeapUsed, | ||
cpuLoad = cpuLoad, | ||
cpuTime = cpuTime | ||
) | ||
_logs = log :: _logs | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package benchmark.bench | ||
|
||
import fabric.rw.RW | ||
|
||
case class StatusLog(progress: Double, | ||
timeStamp: Long, | ||
elapsed: Double, | ||
heap: Long, | ||
nonHeap: Long, | ||
cpuLoad: Double, | ||
cpuTime: Long) | ||
|
||
object StatusLog { | ||
implicit val rw: RW[StatusLog] = RW.gen | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package benchmark.bench | ||
|
||
case class Task(name: String, maxProgress: Double = 1.0, f: StatusCallback => Unit) |
104 changes: 104 additions & 0 deletions
104
benchmark/src/main/scala/benchmark/bench/impl/LightDBBench.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package benchmark.bench.impl | ||
|
||
import benchmark.bench.{Bench, StatusCallback} | ||
import fabric.rw.RW | ||
import lightdb.document.{Document, DocumentModel} | ||
import lightdb.index.{Indexed, IndexedCollection, IndexerManager} | ||
import lightdb.store.StoreManager | ||
import lightdb.upgrade.DatabaseUpgrade | ||
import lightdb.util.Unique | ||
import lightdb.{Id, LightDB} | ||
import org.apache.commons.io.FileUtils | ||
|
||
import java.io.File | ||
import java.nio.file.Path | ||
import scala.collection.parallel.CollectionConverters._ | ||
|
||
case class LightDBBench(sm: StoreManager, im: IndexerManager) extends Bench { | ||
override def init(): Unit = { | ||
val dbDir = new File("db") | ||
FileUtils.deleteDirectory(dbDir) | ||
dbDir.mkdirs() | ||
|
||
scribe.info("DB init...") | ||
DB.init() | ||
scribe.info("Initialized!") | ||
} | ||
|
||
override protected def insertRecords(status: StatusCallback): Unit = DB.people.transaction { implicit transaction => | ||
(0 until RecordCount) | ||
.foreach { index => | ||
DB.people.set(Person( | ||
name = Unique(), | ||
age = index | ||
)) | ||
status.progress.set(index + 1) | ||
} | ||
} | ||
|
||
override protected def streamRecords(status: StatusCallback): Unit = DB.people.transaction { implicit transaction => | ||
(0 until StreamIterations) | ||
.par | ||
.foreach { iteration => | ||
val count = DB.people.iterator.size | ||
if (count != RecordCount) { | ||
scribe.warn(s"RecordCount was not $RecordCount, it was $count") | ||
} | ||
status.progress.set(iteration + 1) | ||
} | ||
} | ||
|
||
override protected def searchEachRecord(status: StatusCallback): Unit = DB.people.transaction { implicit transaction => | ||
(0 until StreamIterations) | ||
.par | ||
.foreach { iteration => | ||
(0 until RecordCount) | ||
.par | ||
.foreach { index => | ||
val list = DB.people.query.filter(_.age === index).search.docs.list | ||
if (list.size != 1) { | ||
scribe.warn(s"Unable to find age = $index") | ||
} | ||
if (list.head.age != index) { | ||
scribe.warn(s"${list.head.age} was not $index") | ||
} | ||
status.progress.set((iteration + 1) * (index + 1)) | ||
} | ||
} | ||
} | ||
|
||
override protected def searchAllRecords(status: StatusCallback): Unit = DB.people.transaction { implicit transaction => | ||
(0 until StreamIterations) | ||
.par | ||
.foreach { iteration => | ||
val count = DB.people.query.search.docs.iterator.foldLeft(0)((count, _) => count + 1) | ||
if (count != RecordCount) { | ||
scribe.warn(s"RecordCount was not $RecordCount, it was $count") | ||
} | ||
status.progress.set(iteration + 1) | ||
} | ||
} | ||
|
||
override def dispose(): Unit = DB.dispose() | ||
|
||
object DB extends LightDB { | ||
override lazy val directory: Option[Path] = Some(Path.of(s"db/bench")) | ||
|
||
val people: IndexedCollection[Person, Person.type] = collection("people", Person, im.create[Person, Person.type]()) | ||
|
||
override def storeManager: StoreManager = sm | ||
|
||
override def upgrades: List[DatabaseUpgrade] = Nil | ||
} | ||
|
||
case class Person(name: String, | ||
age: Int, | ||
_id: Id[Person] = Person.id()) extends Document[Person] | ||
|
||
object Person extends DocumentModel[Person] with Indexed[Person] { | ||
implicit val rw: RW[Person] = RW.gen | ||
|
||
val name: I[String] = index.one("name", _.name, store = true) | ||
val age: I[Int] = index.one("age", _.age, store = true) | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
...a/benchmark/BenchmarkImplementation.scala → ...chmark/imdb/BenchmarkImplementation.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package benchmark | ||
package benchmark.imdb | ||
|
||
import cats.effect.IO | ||
|
||
|
19 changes: 9 additions & 10 deletions
19
.../main/scala/benchmark/IMDBBenchmark.scala → .../scala/benchmark/imdb/IMDBBenchmark.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 2 additions & 3 deletions
5
...ala/benchmark/LightDBImplementation.scala → ...enchmark/imdb/LightDBImplementation.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
...ala/benchmark/MariaDBImplementation.scala → ...enchmark/imdb/MariaDBImplementation.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
...ala/benchmark/MongoDBImplementation.scala → ...enchmark/imdb/MongoDBImplementation.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 4 additions & 4 deletions
8
...la/benchmark/PostgresImplementation.scala → ...nchmark/imdb/PostgresImplementation.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 2 additions & 1 deletion
3
...cala/benchmark/SQLiteImplementation.scala → ...benchmark/imdb/SQLiteImplementation.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...la/benchmark/ScarangoImplementation.scala → ...nchmark/imdb/ScarangoImplementation.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.