Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created Benchmark Entrypoint with JMH #255

Merged
merged 8 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ jobs:
run: sbt "project tinkergraph" test
- name: Run OverflowDB tests
run: sbt "project overflowdb" test
- name: Run Neo4j tests
run: sbt "project neo4j" test
# - name: Run Neo4j tests
# run: sbt "project neo4j" test
- name: Run Neo4j Embedded tests
run: sbt "project neo4jEmbed" test
# - name: Run TigerGraph tests
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
/build/
/bin/
*.bin
*.cpg
*.gzip
graph.xml
gsql_client.*
*.txt
*.csv

# Ignore Gradle GUI config
gradle-app.setting
Expand Down Expand Up @@ -32,3 +35,4 @@ gradle-app.setting
**/.bsp/
target
/project/target/
/neo4j-db
65 changes: 54 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,51 @@ research to begin on Joern where I also spend time providing help and support.
## Quickstart

One can run Plume from the `plume` binary which will use `OverflowDB` as the graph database backend if no config is
found. If one would like to configure another backend then the example `driver.yaml` can be adjusted to include the use
of another database by uncommenting and editing the respective fields given by the skeleton. E.g. using Neo4j:

```yaml
database: Neo4j
params:
hostname: localhost
port: 7687
username: neo4j
password: neo4j
txMax: 25
found. If one would like to configure another backend then use the CLI arguments:

```bash
Usage: plume [tinkergraph|overflowdb|neo4j|neo4j-embedded|tigergraph|neptune] [options] input-dir

An AST creator for comparing graph databases as static analysis backends.
-h, --help
input-dir The target application to parse.
Command: tinkergraph [options]

--import-path <value> The TinkerGraph to import.
--export-path <value> The TinkerGraph export path to serialize the result to.
Command: overflowdb [options]

--storage-location <value>
--heap-percentage-threshold <value>
--enable-serialization-stats
Command: neo4j [options]

--hostname <value>
--port <value>
--username <value>
--password <value>
--tx-max <value>
Command: neo4j-embedded [options]

--databaseName <value>
--databaseDir <value>
--tx-max <value>
Command: tigergraph [options]

--hostname <value>
--restpp-port <value>
--gsql-port <value>
--username <value>
--password <value>
--timeout <value>
--tx-max <value>
--scheme <value>
Command: neptune [options]

--hostname <value>
--port <value>
--key-cert-chain-file <value>
--tx-max <value>
```

For more documentation and basic guides, check out the [project homepage](https://plume-oss.github.io/plume-docs/) or
Expand Down Expand Up @@ -100,6 +134,15 @@ sbt stage

This will build `target/scala-2.13/plume_2.13-X.X.X.jar` which can be imported into your local project.

## Benchmarks

Plume specifies a `benchmark` binary which orchestrates running JMH benchmarks for AST creation with various graph
database backends. While the binary explains the available functions, the execution should be run within `sbt`, e.g.

```sbt
Jmh/runMain com.github.plume.oss.Benchmark overflowdb testprogram -o output -r results --storage-location test.cpg
```

## Logging

Plume uses [SLF4J](http://www.slf4j.org/) as the logging fascade.
Expand Down
11 changes: 11 additions & 0 deletions astcreator/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name := "astcreator"

dependsOn(Projects.base, Projects.commons, Projects.gremlin, Projects.overflowdb)

libraryDependencies ++= Seq(
"io.joern" %% "semanticcpg" % Versions.joern,
"io.joern" %% "x2cpg" % Versions.joern,
"io.joern" %% "jimple2cpg" % Versions.joern,
"io.joern" %% "jimple2cpg" % Versions.joern % Test classifier "tests",
"io.joern" %% "x2cpg" % Versions.joern % Test classifier "tests",
)
1 change: 1 addition & 0 deletions benchmark
35 changes: 22 additions & 13 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ inThisBuild(
organization := "com.github.plume-oss",
version := "2.0.0",
scalaVersion := "3.4.2",
resolvers ++= Seq(Resolver.mavenLocal, Resolver.mavenCentral, Resolver.JCenterRepository)
resolvers ++= Seq(
Resolver.mavenLocal,
Resolver.mavenCentral,
Resolver.JCenterRepository,
"Sonatype OSS" at "https://oss.sonatype.org/content/repositories/public",
"Atlassian" at "https://packages.atlassian.com/mvn/maven-atlassian-external",
"Gradle Releases" at "https://repo.gradle.org/gradle/libs-releases/"
)
)
)

Expand All @@ -20,28 +27,30 @@ lazy val neo4j = Projects.neo4j
lazy val neo4jEmbed = Projects.neo4jEmbed
lazy val tigergraph = Projects.tigergraph
lazy val overflowDb = Projects.overflowdb
// AST creation
lazy val astcreator = Projects.astcreator

lazy val root = (project in file("."))
.dependsOn(commons, base, gremlin, tinkergraph, neptune, neo4j, neo4jEmbed, tigergraph, overflowDb)
.aggregate(commons, base, gremlin, tinkergraph, neptune, neo4j, neo4jEmbed, tigergraph, overflowDb)
.dependsOn(astcreator, commons, base, gremlin, tinkergraph, neptune, neo4j, neo4jEmbed, tigergraph, overflowDb)
.aggregate(astcreator, commons, base, gremlin, tinkergraph, neptune, neo4j, neo4jEmbed, tigergraph, overflowDb)

trapExit := false
Test / fork := true
Test / parallelExecution := false

libraryDependencies ++= Seq(
"io.joern" %% "semanticcpg" % Versions.joern,
"io.joern" %% "x2cpg" % Versions.joern,
"io.joern" %% "jimple2cpg" % Versions.joern,
"io.joern" %% "jimple2cpg" % Versions.joern % Test classifier "tests",
"io.joern" %% "x2cpg" % Versions.joern % Test classifier "tests",
"org.slf4j" % "slf4j-api" % Versions.slf4j,
"org.apache.logging.log4j" % "log4j-core" % Versions.log4j % Test,
"org.apache.logging.log4j" % "log4j-slf4j-impl" % Versions.log4j % Test,
"org.scalatest" %% "scalatest" % Versions.scalatest % Test
"org.openjdk.jmh" % "jmh-generator-annprocess" % Versions.jmh,
"org.openjdk.jmh" % "jmh-core" % Versions.jmh,
"org.openjdk.jmh" % "jmh-generator-bytecode" % Versions.jmh,
"org.openjdk.jmh" % "jmh-generator-reflection" % Versions.jmh,
"org.openjdk.jmh" % "jmh-generator-asm" % Versions.jmh,
"org.slf4j" % "slf4j-api" % Versions.slf4j,
"org.apache.logging.log4j" % "log4j-core" % Versions.log4j % Test,
"org.apache.logging.log4j" % "log4j-slf4j-impl" % Versions.log4j % Test,
"org.scalatest" %% "scalatest" % Versions.scalatest % Test
)

enablePlugins(JavaAppPackaging)
enablePlugins(JavaAppPackaging, JmhPlugin)

scmInfo := Some(ScmInfo(url("https://github.com/plume-oss/plume"), "[email protected]:plume-oss/plume.git"))

Expand Down
59 changes: 0 additions & 59 deletions commons/src/main/scala/com/github/plume/oss/PlumeStatistics.scala

This file was deleted.

37 changes: 0 additions & 37 deletions driver.yaml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import overflowdb.{BatchedUpdate, DetachedNodeGeneric}

import scala.jdk.CollectionConverters.IteratorHasAsScala
import scala.language.postfixOps
import scala.util.Try

class PlumeDriverFixture(val driver: IDriver)
extends AnyWordSpec
Expand Down Expand Up @@ -68,15 +69,27 @@ class PlumeDriverFixture(val driver: IDriver)
val changes = diffGraph1.iterator.asScala.toList
val srcNode = changes
.collectFirst {
case c: DetachedNodeGeneric if c.getRefOrId == m.getOrElse("id", -1L).toString.toLong =>
case c: DetachedNodeGeneric
if c.getRefOrId == m.getOrElse("id", -1L).toString.toLong || Try(
c.getRefOrId
.asInstanceOf[StoredNode]
.id()
).map(_ == m.getOrElse("id", -1L).toString.toLong).getOrElse(false) =>
c
} match {
case Some(src) => src
case None => fail("Unable to extract method node")
}
val dstNode = changes
.collectFirst {
case c: NewBlock if c.getRefOrId().asInstanceOf[Long] == b.getOrElse("id", -1L).toString.toLong => c
case c: NewBlock
if Try(c.getRefOrId().asInstanceOf[Long])
.map(_ == b.getOrElse("id", -1L).toString.toLong)
.getOrElse(false) ||
Try(c.getRefOrId().asInstanceOf[StoredNode].id())
.map(_ == b.getOrElse("id", -1L).toString.toLong)
.getOrElse(false) =>
c
} match {
case Some(dst) => dst
case None => fail("Unable to extract block node")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.github.plume.oss.drivers

import com.github.plume.oss.PlumeStatistics
import com.github.plume.oss.util.BatchedUpdateUtil
import io.shiftleft.codepropertygraph.generated.{EdgeTypes, NodeTypes, PropertyNames}
import io.shiftleft.codepropertygraph.generated.PropertyNames
import org.apache.commons.configuration.BaseConfiguration
import org.apache.tinkerpop.gremlin.process.traversal.P.within
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.{coalesce, constant, values}
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.{GraphTraversal, GraphTraversalSource, __}
import org.apache.tinkerpop.gremlin.structure.{Edge, Graph, T, Vertex}
Expand All @@ -14,7 +12,7 @@ import overflowdb.BatchedUpdate.{Change, DiffOrBuilder}
import overflowdb.{BatchedUpdate, DetachedNodeData}

import java.util.concurrent.atomic.AtomicBoolean
import scala.jdk.CollectionConverters.{CollectionHasAsScala, IteratorHasAsScala, MapHasAsScala}
import scala.jdk.CollectionConverters.{IteratorHasAsScala, MapHasAsScala}
import scala.util.{Failure, Success, Try}

/** The driver used by databases implementing Gremlin.
Expand All @@ -25,15 +23,14 @@ abstract class GremlinDriver(txMax: Int = 50) extends IDriver {
protected val config: BaseConfiguration = new BaseConfiguration()
config.setProperty("gremlin.graph", "org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph")
config.setProperty("gremlin.tinkergraph.vertexIdManager", "LONG")
protected val graph: Graph =
PlumeStatistics.time(PlumeStatistics.TIME_OPEN_DRIVER, { TinkerGraph.open(config) })
protected val graph: Graph = TinkerGraph.open(config)
protected var traversalSource: Option[GraphTraversalSource] = None
private val connected = new AtomicBoolean(true)

override def isConnected: Boolean = connected.get()

override def close(): Unit =
Try(PlumeStatistics.time(PlumeStatistics.TIME_CLOSE_DRIVER, { graph.close() })) match {
Try(graph.close()) match {
case Success(_) => connected.set(false)
case Failure(e) =>
logger.warn("Exception thrown while attempting to close graph.", e)
Expand Down
Loading
Loading