Skip to content
This repository has been archived by the owner on Mar 11, 2019. It is now read-only.

Commit

Permalink
fix(#54): Refactors the LibpfmChildSensor
Browse files Browse the repository at this point in the history
Closes #54. Uses the helper as a parameter in order to rewrite tests (we will be able to mock this object).
A new libpfm jar is provided in order to be used in all supported architectures by libpfm.

chore(dependencies): update plugins and dependencies

Updates all dependencies and plugins used by PowerAPI.
  • Loading branch information
mcolmant committed Jun 1, 2015
1 parent 737a202 commit dd608e0
Show file tree
Hide file tree
Showing 29 changed files with 734 additions and 355 deletions.
13 changes: 4 additions & 9 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
language: scala
scala:
- 2.11.4
- 2.11.6
script:
- sbt clean coverage test
before_install:
- openssl aes-256-cbc -K $encrypted_48ebb0d1c0b9_key -iv $encrypted_48ebb0d1c0b9_iv
-in secrets.tar.enc -out secrets.tar -d
- tar xf secrets.tar
- sbt clean "project powerapi-core" coverage test
after_success:
- sbt coverageReport
- sbt coverageAggregate
- sbt codacyCoverage
- sbt "project powerapi-core" coverageReport
- sbt "project powerapi-core" codacyCoverage
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ PowerAPI is used in a variety of projects to address key challenges of GreenIT:
* [Greenspector](http://greenspector.com) optimises the power consumption of software by identifying potential energy leaks in the source code.

## Acknowledgments
We all stand on the shoulders of giants and get by with a little help from our friends. PowerAPI is written in [Scala](http://www.scala-lang.org) (version 2.11.4 under [3-clause BSD license](http://www.scala-lang.org/license.html)) and built on top of:
* [Akka](http://akka.io) (version 2.3.6 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for asynchronous processing
* [Typesage Config](https://github.com/typesafehub/config) (version 1.2.1 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for reading configuration files.
* [Apache log4j2](http://logging.apache.org/log4j/2.x) (version 2.1 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for logging outside actors.
We all stand on the shoulders of giants and get by with a little help from our friends. PowerAPI is written in [Scala](http://www.scala-lang.org) (version 2.11.6 under [3-clause BSD license](http://www.scala-lang.org/license.html)) and built on top of:
* [Akka](http://akka.io) (version 2.3.11 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for asynchronous processing
* [Typesafe Config](https://github.com/typesafehub/config) (version 1.2.1 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for reading configuration files.
* [Apache log4j2](http://logging.apache.org/log4j/2.x) (version 2.3 under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0)), for logging outside actors.
* [powerspy.scala](https://github.com/Spirals-Team/powerspy.scala) (version 1.0.1 under [AGPL license](http://www.gnu.org/licenses/agpl-3.0.html)), for using the [PowerSpy powermeter](http://www.alciom.com/en/products/powerspy2-en-gb-2.html).
* [BridJ](https://code.google.com/p/bridj/) (version 0.6.2 under [3-clause BSD license](https://github.com/ochafik/nativelibs4java/blob/master/libraries/BridJ/LICENSE)), for system or C calls.
* [BridJ](https://code.google.com/p/bridj/) (version 0.7.0 under [3-clause BSD license](https://github.com/ochafik/nativelibs4java/blob/master/libraries/BridJ/LICENSE)), for system or C calls.
* [perfmon2](http://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree) (version 4.6.0 under [MIT license](http://sourceforge.net/p/perfmon2/libpfm4/ci/master/tree/COPYING)), for accessing hardware performance counters.
* [JFreeChart](http://www.jfree.org/jfreechart/) (version 1.0.19 under [LGPL license](https://www.gnu.org/licenses/lgpl.html)), for creation of interactive and animated charts.
* [Scala IO](http://jesseeichar.github.io/scala-io-doc/0.4.3/index.html#!/overview) (version 0.4.3 under [3-clause BSD license](http://www.scala-lang.org/license.html)), for an extensions of IO.
Expand Down
8 changes: 3 additions & 5 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name := "powerapi"

version in ThisBuild := "3.1"

scalaVersion in ThisBuild := "2.11.4"
scalaVersion in ThisBuild := "2.11.6"

scalacOptions in ThisBuild ++= Seq(
"-language:reflectiveCalls",
Expand All @@ -13,10 +13,8 @@ scalacOptions in ThisBuild ++= Seq(

// Logging
libraryDependencies in ThisBuild ++= Seq(
"org.apache.logging.log4j" % "log4j-api" % "2.1",
"org.apache.logging.log4j" % "log4j-core" % "2.1"
"org.apache.logging.log4j" % "log4j-api" % "2.3",
"org.apache.logging.log4j" % "log4j-core" % "2.3"
)

parallelExecution in (ThisBuild, Test) := false

codacyProjectTokenFile := Some("./codacy-token.txt")
44 changes: 25 additions & 19 deletions powerapi-cli/src/main/scala/org/powerapi/app/PowerAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import org.powerapi.core.target.{Application, All, Process, Target}
import org.powerapi.module.rapl.RAPLModule
import org.powerapi.module.sigar.SigarModule
import org.powerapi.reporter.{FileDisplay, JFreeChartDisplay, ConsoleDisplay}
import org.powerapi.{PowerMonitoring, PowerMeter, PowerModule}
import org.powerapi.{PowerMonitoring, PowerMeter}
import org.powerapi.core.power._
import org.powerapi.module.cpu.dvfs.CpuDvfsModule
import org.powerapi.module.cpu.simple.CpuSimpleModule
Expand Down Expand Up @@ -66,20 +66,6 @@ object PowerAPI extends App {
case _ => false
}

implicit def modulesStrToPowerModules(str: String): Seq[PowerModule] = {
(for(module <- str.split(",")) yield {
module match {
case "cpu-simple" => CpuSimpleModule()
case "cpu-dvfs" => CpuDvfsModule()
case "libpfm-core" => LibpfmCoreModule()
case "libpfm-core-process" => LibpfmCoreProcessModule()
case "powerspy" => PowerSpyModule()
case "rapl" => RAPLModule()
case "sigar" => SigarModule()
}
}).toSeq
}

def validateAgg(str: String): Boolean = str match {
case aggR(_*) => true
case _ => false
Expand Down Expand Up @@ -172,9 +158,27 @@ object PowerAPI extends App {
if(!System.getProperty("os.name").startsWith("Windows")) Seq("bash", "scripts/system.bash").!
val (configuration, duration) = cli(List(), "3600", args.toList)

var libpfmHelper: Option[LibpfmHelper] = None

if(configuration.count(powerMeterConf => powerMeterConf('modules).toString.contains("libpfm")) != 0) {
libpfmHelper = Some(new LibpfmHelper)
libpfmHelper.get.init()
}

for(powerMeterConf <- configuration) {
val modules = powerMeterConf('modules).toString
if(modules.contains("libpfm-core") || modules.contains("libpfm-core-process")) LibpfmHelper.init()
val modulesStr = powerMeterConf('modules).toString

val modules = (for(module <- modulesStr.split(",")) yield {
module match {
case "cpu-simple" => CpuSimpleModule()
case "cpu-dvfs" => CpuDvfsModule()
case "libpfm-core" => LibpfmCoreModule(libpfmHelper.get)
case "libpfm-core-process" => LibpfmCoreProcessModule(libpfmHelper.get)
case "powerspy" => PowerSpyModule()
case "rapl" => RAPLModule()
case "sigar" => SigarModule()
}
}).toSeq

val powerMeter = PowerMeter.loadModule(modules: _*)
powerMeters :+= powerMeter
Expand Down Expand Up @@ -209,8 +213,10 @@ object PowerAPI extends App {

Thread.sleep(duration.toInt.seconds.toMillis)

val isLibpfmInit = configuration.count(powerMeterConf => powerMeterConf('modules).toString.contains("libpfm-core") || powerMeterConf('modules).toString.contains("libpfm-core-process")) != 0
if(isLibpfmInit) LibpfmHelper.deinit()
libpfmHelper match {
case Some(helper) => helper.deinit()
case _ => {}
}
}

shutdownHookThread.start()
Expand Down
13 changes: 5 additions & 8 deletions powerapi-core/build.sbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import SonatypeKeys._

sonatypeSettings

name := "powerapi-core"

organization := "org.powerapi"
Expand All @@ -12,10 +8,10 @@ resolvers ++= Seq(

// App
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % "2.3.6",
"com.typesafe.akka" %% "akka-actor" % "2.3.11",
"com.typesafe" % "config" % "1.2.1",
"fr.inria.powerspy" % "powerspy-core_2.11" % "1.1",
"com.nativelibs4java" % "bridj" % "0.6.2",
"com.nativelibs4java" % "bridj" % "0.7.0",
"com.github.scala-incubator.io" %% "scala-io-core" % "0.4.3",
"com.github.scala-incubator.io" %% "scala-io-file" % "0.4.3",
"org.jfree" % "jfreechart" % "1.0.19",
Expand All @@ -25,8 +21,9 @@ libraryDependencies ++= Seq(

// Tests
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-testkit" % "2.3.6" % "test",
"org.scalatest" %% "scalatest" % "2.2.2" % "test"
"com.typesafe.akka" %% "akka-testkit" % "2.3.11" % "test",
"org.scalatest" %% "scalatest" % "2.2.5" % "test",
"org.scalamock" %% "scalamock-scalatest-support" % "3.2.2" % "test"
)

startYear := Some(2014)
Expand Down
Binary file modified powerapi-core/lib/libpfm.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
import org.bridj.BridJ;
import org.bridj.CRuntime;
import org.bridj.Pointer;

import perfmon2.libpfm.LibpfmLibrary;
import perfmon2.libpfm.perf_event_attr;

/**
Expand All @@ -47,10 +45,10 @@ public class CUtils {
/**
* perf_event_open maccro (not generated correctly).
*/
public static int perf_event_open(Pointer<perf_event_attr> __hw, int __pid, int __cpu, int __gr, @CLong long __flags) {
return syscall(LibpfmLibrary.__NR_perf_event_open, Pointer.getPeer(__hw), __pid, __cpu, __gr, __flags);
public static int perf_event_open(int __nrPerfEventOpen, Pointer<perf_event_attr> __hw, int __pid, int __cpu, int __gr, @CLong long __flags) {
return syscall(__nrPerfEventOpen, Pointer.getPeer(__hw), __pid, __cpu, __gr, __flags);
}
private native static int syscall(int __cdde, Object... varArgs1);
private native static int syscall(int __code, Object... varArgs1);

/**
* Interact with a given file descriptor. In this case, we use it to enable, disable and reset a file descriptor (so, a counter).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,46 @@ import org.powerapi.module.libpfm.cycles.{LibpfmCoreCyclesFormulaConfiguration,
import scala.collection.BitSet
import scala.concurrent.duration.FiniteDuration

class LibpfmCoreModule(timeout: Timeout, topology: Map[Int, Set[Int]], configuration: BitSet, events: Set[String],
class LibpfmCoreModule(libpfmHelper: LibpfmHelper, timeout: Timeout, topology: Map[Int, Set[Int]], configuration: BitSet, events: Set[String],
cyclesThreadName: String, cyclesRefName: String, formulae: Map[Double, List[Double]], samplingInterval: FiniteDuration) extends PowerModule {

lazy val underlyingSensorsClasses = Seq((classOf[LibpfmCoreSensor], Seq(timeout, topology, configuration, events)))
lazy val underlyingSensorsClasses = Seq((classOf[LibpfmCoreSensor], Seq(libpfmHelper, timeout, topology, configuration, events)))
lazy val underlyingFormulaeClasses = Seq((classOf[LibpfmCoreCyclesFormula], Seq(cyclesThreadName, cyclesRefName, formulae, samplingInterval)))
}

object LibpfmCoreModule extends LibpfmCoreSensorConfiguration with LibpfmCoreCyclesFormulaConfiguration {
lazy val libpfmHelper = new LibpfmHelper

def apply(): LibpfmCoreModule = {
new LibpfmCoreModule(timeout, topology, configuration, events, cyclesThreadName, cyclesRefName, formulae, samplingInterval)
new LibpfmCoreModule(libpfmHelper, timeout, topology, configuration, events, cyclesThreadName, cyclesRefName, formulae, samplingInterval)
}

def apply(libpfmHelper: LibpfmHelper): LibpfmCoreModule = {
new LibpfmCoreModule(libpfmHelper, timeout, topology, configuration, events, cyclesThreadName, cyclesRefName, formulae, samplingInterval)
}
}

class LibpfmCoreSensorModule(timeout: Timeout, topology: Map[Int, Set[Int]], configuration: BitSet, events: Set[String]) extends PowerModule {
lazy val underlyingSensorsClasses = Seq((classOf[LibpfmCoreSensor], Seq(timeout, topology, configuration, events)))
class LibpfmCoreSensorModule(libpfmHelper: LibpfmHelper, timeout: Timeout, topology: Map[Int, Set[Int]], configuration: BitSet, events: Set[String]) extends PowerModule {
lazy val underlyingSensorsClasses = Seq((classOf[LibpfmCoreSensor], Seq(libpfmHelper, timeout, topology, configuration, events)))
lazy val underlyingFormulaeClasses = Seq()
}

object LibpfmCoreSensorModule extends LibpfmCoreSensorConfiguration {
lazy val libpfmHelper = new LibpfmHelper

def apply(): LibpfmCoreSensorModule = {
new LibpfmCoreSensorModule(timeout, topology, configuration, events)
new LibpfmCoreSensorModule(libpfmHelper, timeout, topology, configuration, events)
}

def apply(libpfmHelper: LibpfmHelper): LibpfmCoreSensorModule = {
new LibpfmCoreSensorModule(libpfmHelper, timeout, topology, configuration, events)
}

def apply(events: Set[String]): LibpfmCoreSensorModule = {
new LibpfmCoreSensorModule(timeout, topology, configuration, events)
new LibpfmCoreSensorModule(libpfmHelper, timeout, topology, configuration, events)
}

def apply(libpfmHelper: LibpfmHelper, events: Set[String]): LibpfmCoreSensorModule = {
new LibpfmCoreSensorModule(libpfmHelper, timeout, topology, configuration, events)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,21 @@ import org.powerapi.module.libpfm.cycles.{LibpfmCoreCyclesFormulaConfiguration,
import scala.collection.BitSet
import scala.concurrent.duration.FiniteDuration

class LibpfmCoreProcessModule(timeout: Timeout, topology: Map[Int, Set[Int]], configuration: BitSet, events: Set[String], inDepth: Boolean,
class LibpfmCoreProcessModule(libpfmHelper: LibpfmHelper, timeout: Timeout, topology: Map[Int, Set[Int]], configuration: BitSet, events: Set[String], inDepth: Boolean,
cyclesThreadName: String, cyclesRefName: String, formulae: Map[Double, List[Double]], samplingInterval: FiniteDuration) extends PowerModule {

lazy val underlyingSensorsClasses = Seq((classOf[LibpfmCoreProcessSensor], Seq(new LinuxHelper, timeout, topology, configuration, events, inDepth)))
lazy val underlyingSensorsClasses = Seq((classOf[LibpfmCoreProcessSensor], Seq(new LinuxHelper, libpfmHelper, timeout, topology, configuration, events, inDepth)))
lazy val underlyingFormulaeClasses = Seq((classOf[LibpfmCoreCyclesFormula], Seq(cyclesThreadName, cyclesRefName, formulae, samplingInterval)))
}

object LibpfmCoreProcessModule extends LibpfmCoreProcessSensorConfiguration with LibpfmCoreCyclesFormulaConfiguration {
lazy val libpfmHelper = new LibpfmHelper

def apply(): LibpfmCoreProcessModule = {
new LibpfmCoreProcessModule(timeout, topology, configuration, events, inDepth, cyclesThreadName, cyclesRefName, formulae, samplingInterval)
new LibpfmCoreProcessModule(libpfmHelper, timeout, topology, configuration, events, inDepth, cyclesThreadName, cyclesRefName, formulae, samplingInterval)
}

def apply(libpfmHelper: LibpfmHelper): LibpfmCoreProcessModule = {
new LibpfmCoreProcessModule(libpfmHelper, timeout, topology, configuration, events, inDepth, cyclesThreadName, cyclesRefName, formulae, samplingInterval)
}
}
Loading

0 comments on commit dd608e0

Please sign in to comment.