Skip to content
This repository was archived by the owner on Mar 11, 2019. It is now read-only.
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
10 changes: 6 additions & 4 deletions powerapi-cli/src/main/scala/org/powerapi/app/PowerAPI.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import org.powerapi.core.power._
import org.powerapi.module.cpu.dvfs.CpuDvfsModule
import org.powerapi.module.cpu.simple.{SigarCpuSimpleModule, ProcFSCpuSimpleModule}
import org.powerapi.module.libpfm.{LibpfmModule, LibpfmHelper, LibpfmCoreProcessModule, LibpfmCoreModule, LibpfmProcessModule}
import org.powerapi.module.powerspy.PowerSpyModule
import org.powerapi.module.extPMeter.powerspy.PowerSpyModule
import org.powerapi.module.extPMeter.g5k.G5kOmegaWattModule
import scala.concurrent.duration.DurationInt
import scala.sys
import scala.sys.process.stringSeqToProcess
Expand All @@ -43,7 +44,7 @@ import scala.sys.process.stringSeqToProcess
* @author <a href="mailto:l.huertas.pro@gmail.com">Loïc Huertas</a>
*/
object PowerAPI extends App {
val modulesR = """(procfs-cpu-simple|sigar-cpu-simple|cpu-dvfs|libpfm|libpfm-process|libpfm-core|libpfm-core-process|powerspy|rapl)(,(procfs-cpu-simple|sigar-cpu-simple|cpu-dvfs|libpfm|libpfm-process|libpfm-core|libpfm-core-process|powerspy|rapl))*""".r
val modulesR = """(procfs-cpu-simple|sigar-cpu-simple|cpu-dvfs|libpfm|libpfm-process|libpfm-core|libpfm-core-process|powerspy|g5k-omegawatt|rapl)(,(procfs-cpu-simple|sigar-cpu-simple|cpu-dvfs|libpfm|libpfm-process|libpfm-core|libpfm-core-process|powerspy|g5k-omegawatt|rapl))*""".r
val aggR = """max|min|geomean|logsum|mean|median|stdev|sum|variance""".r
val durationR = """\d+""".r
val pidR = """(\d+)""".r
Expand Down Expand Up @@ -113,7 +114,7 @@ object PowerAPI extends App {
|You can use different settings per software-defined power meter for some modules by using the optional prefix option.
|Please, refer to the documentation inside the GitHub wiki for further details.
|
|usage: ./powerapi modules [procfs-cpu-simple|sigar-cpu-simple|cpu-dvfs|libpfm|libpfm-process|libpfm-core|libpfm-core-proces|powerspy|rapl,...] *--prefix [name]* \
|usage: ./powerapi modules [procfs-cpu-simple|sigar-cpu-simple|cpu-dvfs|libpfm|libpfm-process|libpfm-core|libpfm-core-proces|powerspy|g5k-omegawatt|rapl,...] *--prefix [name]* \
| monitor --frequency [ms] --targets [pid, ..., app, ...|all] --agg [max|min|geomean|logsum|mean|median|stdev|sum|variance] --[console,file [filepath],chart] \
| duration [s]
|
Expand Down Expand Up @@ -180,7 +181,8 @@ object PowerAPI extends App {
case "libpfm-process" => LibpfmProcessModule(powerMeterConf('prefix).asInstanceOf[Option[String]], libpfmHelper.get)
case "libpfm-core" => LibpfmCoreModule(powerMeterConf('prefix).asInstanceOf[Option[String]], libpfmHelper.get)
case "libpfm-core-process" => LibpfmCoreProcessModule(powerMeterConf('prefix).asInstanceOf[Option[String]], libpfmHelper.get)
case "powerspy" => PowerSpyModule()
case "powerspy" => PowerSpyModule(powerMeterConf('prefix).asInstanceOf[Option[String]])
case "g5k-omegawatt" => G5kOmegaWattModule(powerMeterConf('prefix).asInstanceOf[Option[String]])
case "rapl" => RAPLModule()
}
}).toSeq
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ package org.powerapi.core
* @author <a href="mailto:maxime.colmant@gmail.com">Maxime Colmant</a>
*/
trait ExternalPMeter {
def init(): Unit
def init(bus: MessageBus): Unit
def start(): Unit
def stop(): Unit
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,59 +20,60 @@
*
* If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
*/
package org.powerapi.module.powerspy
package org.powerapi.module.extPMeter

import akka.actor.ActorRef
import org.powerapi.core.{Channel, Message, MessageBus}
import org.powerapi.core.power.Power

/**
* PowerSpyChannel channel and messages.
* ExtPMeterChannel channel and messages.
*
* @author <a href="mailto:maxime.colmant@gmail.com">Maxime Colmant</a>
* @author <a href="mailto:l.huertas.pro@gmail.com">Loïc Huertas</a>
*/
object PowerSpyChannel extends Channel {
object ExtPMeterChannel extends Channel {

type M = PowerSpyPower
type M = ExtPMeterPower

/**
* PowerSpyPower is represented as a dedicated type of message.
* ExtPMeterPower is represented as a dedicated type of message.
*
* @param topic: subject used for routing the message.
* @param power: power consumption got by an external device.
*/
case class PowerSpyPower(topic: String,
power: Power) extends Message
case class ExtPMeterPower(topic: String,
power: Power) extends Message

/**
* Topic for communicating with the Sensor actor.
*/
private val pMeterTopic = "powerspy:power"
private val pMeterTopic = "extpmeter:power"

/**
* Topic for communicating with the Formula actor.
*/
private val topic = "sensor:powerspy"
private val topic = "sensor:extpmeter"

/**
* Publish a PowerSpyPower in the event bus.
* Publish a ExtPMeterPower in the event bus.
*/
def publishExternalPowerSpyPower(power: Power): MessageBus => Unit = {
publish(PowerSpyPower(pMeterTopic, power))
def publishExternalPMeterPower(power: Power): MessageBus => Unit = {
publish(ExtPMeterPower(pMeterTopic, power))
}

def publishPowerSpyPower(power: Power): MessageBus => Unit = {
publish(PowerSpyPower(topic, power))
def publishPMeterPower(power: Power): MessageBus => Unit = {
publish(ExtPMeterPower(topic, power))
}

/**
* External methods used for interacting with the bus.
*/
def subscribeExternalPowerSpyPower: MessageBus => ActorRef => Unit = {
def subscribeExternalPMeterPower: MessageBus => ActorRef => Unit = {
subscribe(pMeterTopic)
}

def subscribePowerSpyPower: MessageBus => ActorRef => Unit = {
def subscribePMeterPower: MessageBus => ActorRef => Unit = {
subscribe(topic)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
* If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
*/
package org.powerapi.module.powerspy
package org.powerapi.module.extPMeter

import akka.event.LoggingReceive
import org.powerapi.core.{OSHelper, APIComponent, MessageBus}
Expand All @@ -29,7 +29,7 @@ import org.powerapi.core.power._
import org.powerapi.core.target.{Application, All, Process, TargetUsageRatio}
import org.powerapi.module.{Cache, CacheKey}
import org.powerapi.module.PowerChannel.publishRawPowerReport
import org.powerapi.module.powerspy.PowerSpyChannel.{PowerSpyPower, subscribePowerSpyPower}
import org.powerapi.module.extPMeter.ExtPMeterChannel.{ExtPMeterPower, subscribePMeterPower}
import scala.reflect.ClassTag

/**
Expand All @@ -39,20 +39,21 @@ import scala.reflect.ClassTag
* The simple CpuSensor is used for getting the Target cpu usage ratio (UsageReport).
*
* @author <a href="mailto:maxime.colmant@gmail.com">Maxime Colmant</a>
* @author <a href="mailto:l.huertas.pro@gmail.com">Loïc Huertas</a>
*/
class PowerSpyFormula(eventBus: MessageBus, osHelper: OSHelper, idlePower: Power) extends APIComponent {
class ExtPMeterFormula(eventBus: MessageBus, osHelper: OSHelper, idlePower: Power) extends APIComponent {

override def preStart(): Unit = {
subscribePowerSpyPower(eventBus)(self)
subscribePMeterPower(eventBus)(self)
subscribeMonitorTick(eventBus)(self)
super.preStart()
}

def receive: PartialFunction[Any, Unit] = running(None)

def running(pspyPower: Option[PowerSpyPower]): PartialFunction[Any, Unit] = LoggingReceive {
case msg: PowerSpyPower => context.become(running(Some(msg)))
case msg: MonitorTick => compute(pspyPower, msg)
def running(epmPower: Option[ExtPMeterPower]): PartialFunction[Any, Unit] = LoggingReceive {
case msg: ExtPMeterPower => context.become(running(Some(msg)))
case msg: MonitorTick => compute(epmPower, msg)
} orElse default

// In order to compute the target's ratio
Expand Down Expand Up @@ -98,17 +99,17 @@ class PowerSpyFormula(eventBus: MessageBus, osHelper: OSHelper, idlePower: Power
}
}

def compute(pSpyPower: Option[PowerSpyPower], monitorTick: MonitorTick): Unit = {
pSpyPower match {
def compute(epmPower: Option[ExtPMeterPower], monitorTick: MonitorTick): Unit = {
epmPower match {
case Some(pPower) => {
lazy val dynamicP = if(pPower.power.toMilliWatts - idlePower.toMilliWatts > 0) pPower.power - idlePower else 0.W

monitorTick.target match {
case All => publishRawPowerReport(monitorTick.muid, monitorTick.target, pPower.power, "PowerSpy", monitorTick.tick)(eventBus)
case _ => publishRawPowerReport(monitorTick.muid, monitorTick.target, dynamicP * targetCpuUsageRatio(monitorTick).ratio, "PowerSpy", monitorTick.tick)(eventBus)
case All => publishRawPowerReport(monitorTick.muid, monitorTick.target, pPower.power, "ExtPMeter", monitorTick.tick)(eventBus)
case _ => publishRawPowerReport(monitorTick.muid, monitorTick.target, dynamicP * targetCpuUsageRatio(monitorTick).ratio, "ExtPMeter", monitorTick.tick)(eventBus)
}
}
case _ => log.debug("{}", "no PowerSpyPower message received")
case _ => log.debug("{}", "no ExtPMeterPower message received")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
* If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
*/
package org.powerapi.module.powerspy
package org.powerapi.module.extPMeter

import org.powerapi.core.{Configuration, ConfigValue}
import org.powerapi.core.power._
Expand All @@ -29,8 +29,9 @@ import org.powerapi.core.power._
* Main configuration.
*
* @author <a href="mailto:maxime.colmant@gmail.com">Maxime Colmant</a>
* @author <a href="mailto:l.huertas.pro@gmail.com">Loïc Huertas</a>
*/
trait PowerSpyFormulaConfiguration extends Configuration {
trait ExtPMeterFormulaConfiguration extends Configuration {
lazy val idlePower = load { _.getDouble(s"powerapi.hardware.idle-power") } match {
case ConfigValue(idle) => idle.W
case _ => 0.W
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@
*
* If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
*/
package org.powerapi.module.powerspy
package org.powerapi.module.extPMeter

import org.powerapi.PowerModule
import org.powerapi.core.{OSHelper, LinuxHelper}
import org.powerapi.core.{ExternalPMeter, OSHelper}
import org.powerapi.core.power.Power
import scala.concurrent.duration.FiniteDuration

class PowerSpyModule(osHelper: OSHelper, mac: String, interval: FiniteDuration, idlePower: Power) extends PowerModule {
class ExtPMeterModule(osHelper: OSHelper, extPMeter: ExternalPMeter, idlePower: Power) extends PowerModule {
lazy val underlyingClasses = eventBus match {
case Some(bus) => {
(Seq((classOf[PowerSpySensor], Seq(new PowerSpyPMeter(bus, mac, interval)))), Seq((classOf[PowerSpyFormula], Seq(osHelper, idlePower))))
(Seq((classOf[ExtPMeterSensor], Seq(extPMeter))), Seq((classOf[ExtPMeterFormula], Seq(osHelper, idlePower))))
}
case _ => (Seq(), Seq())
}
Expand All @@ -39,10 +39,3 @@ class PowerSpyModule(osHelper: OSHelper, mac: String, interval: FiniteDuration,
lazy val underlyingFormulaeClasses = underlyingClasses._2
}

object PowerSpyModule extends PowerSpyFormulaConfiguration with PowerSpyPMeterConfiguration {
def apply(): PowerSpyModule = {
val linuxHelper = new LinuxHelper

new PowerSpyModule(linuxHelper, mac, interval, idlePower)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,23 @@
*
* If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
*/
package org.powerapi.module.powerspy
package org.powerapi.module.extPMeter

import akka.event.LoggingReceive
import org.powerapi.core.{ExternalPMeter, MessageBus, APIComponent}
import org.powerapi.module.powerspy.PowerSpyChannel.{PowerSpyPower, publishPowerSpyPower, subscribeExternalPowerSpyPower}
import org.powerapi.module.extPMeter.ExtPMeterChannel.{ExtPMeterPower, publishPMeterPower, subscribeExternalPMeterPower}

/**
* PowerSpySensor's implementation by using an helper.
* ExtPMeterSensor's implementation by using an helper.
*
* @author <a href="mailto:maxime.colmant@gmail.com">Maxime Colmant</a>
* @author <a href="mailto:l.huertas.pro@gmail.com">Loïc Huertas</a>
*/
class PowerSpySensor(eventBus: MessageBus, pMeter: ExternalPMeter) extends APIComponent {
class ExtPMeterSensor(eventBus: MessageBus, pMeter: ExternalPMeter) extends APIComponent {

override def preStart(): Unit = {
subscribeExternalPowerSpyPower(eventBus)(self)
pMeter.init()
subscribeExternalPMeterPower(eventBus)(self)
pMeter.init(eventBus)
pMeter.start()
super.preStart()
}
Expand All @@ -46,10 +47,10 @@ class PowerSpySensor(eventBus: MessageBus, pMeter: ExternalPMeter) extends APICo
}

def receive: PartialFunction[Any, Unit] = LoggingReceive {
case msg: PowerSpyPower => sense(msg)
case msg: ExtPMeterPower => sense(msg)
} orElse default

def sense(pSpyPower: PowerSpyPower): Unit = {
publishPowerSpyPower(pSpyPower.power)(eventBus)
def sense(epmPower: ExtPMeterPower): Unit = {
publishPMeterPower(epmPower.power)(eventBus)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* This software is licensed under the GNU Affero General Public License, quoted below.
*
* This file is a part of PowerAPI.
*
* Copyright (C) 2011-2015 Inria, University of Lille 1.
*
* PowerAPI is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* PowerAPI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with PowerAPI.
*
* If not, please consult http://www.gnu.org/licenses/agpl-3.0.html.
*/
package org.powerapi.module.extPMeter.g5k

import org.powerapi.core.LinuxHelper
import org.powerapi.module.extPMeter.{ExtPMeterFormulaConfiguration, ExtPMeterModule}

object G5kOmegaWattModule extends ExtPMeterFormulaConfiguration {
def apply(prefixConfig: Option[String] = None): ExtPMeterModule = {
val conf = new G5kPMeterConfiguration(prefixConfig)
val linuxHelper = new LinuxHelper

new ExtPMeterModule(linuxHelper, new G5kPMeter(conf.probe, conf.interval), idlePower)
}
}
Loading