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

Commit 62d385d

Browse files
committed
Merge pull request #67 from Spirals-Team/fix/#58
fix(#58): Refactors the Configuration trait
2 parents 6722161 + 1236f96 commit 62d385d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+933
-225
lines changed

powerapi-cli/src/main/scala/org/powerapi/app/PowerAPI.scala

+20-16
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,11 @@ import java.lang.management.ManagementFactory
2626

2727
import org.powerapi.core.target.{Application, All, Process, Target}
2828
import org.powerapi.module.rapl.RAPLModule
29-
import org.powerapi.module.sigar.SigarModule
3029
import org.powerapi.reporter.{FileDisplay, JFreeChartDisplay, ConsoleDisplay}
3130
import org.powerapi.{PowerMonitoring, PowerMeter}
3231
import org.powerapi.core.power._
3332
import org.powerapi.module.cpu.dvfs.CpuDvfsModule
34-
import org.powerapi.module.cpu.simple.CpuSimpleModule
33+
import org.powerapi.module.cpu.simple.{SigarCpuSimpleModule, ProcFSCpuSimpleModule}
3534
import org.powerapi.module.libpfm.{LibpfmHelper, LibpfmCoreProcessModule, LibpfmCoreModule}
3635
import org.powerapi.module.powerspy.PowerSpyModule
3736
import scala.concurrent.duration.DurationInt
@@ -45,7 +44,7 @@ import scala.sys.process.stringSeqToProcess
4544
* @author <a href="mailto:[email protected]">Loïc Huertas</a>
4645
*/
4746
object PowerAPI extends App {
48-
val modulesR = """(cpu-simple|cpu-dvfs|libpfm-core|libpfm-core-process|powerspy|rapl|sigar)(,(cpu-simple|cpu-dvfs|libpfm-core|libpfm-core-process|powerspy|rapl|sigar))*""".r
47+
val modulesR = """(procfs-cpu-simple|sigar-cpu-simple|cpu-dvfs|libpfm-core|libpfm-core-process|powerspy|rapl)(,(procfs-cpu-simple|sigar-cpu-simple|cpu-dvfs|libpfm-core|libpfm-core-process|powerspy|rapl))*""".r
4948
val aggR = """max|min|geomean|logsum|mean|median|stdev|sum|variance""".r
5049
val durationR = """\d+""".r
5150
val pidR = """(\d+)""".r
@@ -111,14 +110,16 @@ object PowerAPI extends App {
111110
"""
112111
|PowerAPI, Spirals Team
113112
|
114-
|Build a software-defined power meter. Do not forget to configure correctly the modules (see the documentation).
113+
|Build a software-defined power meter. Do not forget to configure correctly the modules.
114+
|You can use different settings per software-defined power meter for some modules by using the optional prefix option.
115+
|Please, refer to the documentation inside the GitHub wiki for further details.
115116
|
116-
|usage: ./powerapi modules [cpu-simple|cpu-dvfs|libpfm-core|libpfm-core-proces|powerspy|rapl,...] \
117+
|usage: ./powerapi modules [procfs-cpu-simple|sigar-cpu-simple|cpu-dvfs|libpfm-core|libpfm-core-proces|powerspy|rapl,...] *--prefix [name]* \
117118
| monitor --frequency [ms] --targets [pid, ..., app, ...|all] --agg [max|min|geomean|logsum|mean|median|stdev|sum|variance] --[console,file [filepath],chart] \
118119
| duration [s]
119120
|
120-
|example: ./powerapi modules cpu-simple monitor --frequency 1000 --targets firefox --agg max --console monitor --targets chrome --agg max --console \
121-
| modules powerspy monitor --frequency 1000 --targets all --agg max --console \
121+
|example: ./powerapi modules procfs-cpu-simple monitor --frequency 1000 --targets firefox,chrome --agg max --console \
122+
| modules powerspy --prefix powermeter2 monitor --frequency 1000 --targets all --agg max --console \
122123
| duration 30
123124
""".stripMargin
124125

@@ -127,16 +128,21 @@ object PowerAPI extends App {
127128

128129
def cli(options: List[Map[Symbol, Any]], duration: String, args: List[String]): (List[Map[Symbol, Any]], String) = args match {
129130
case Nil => (options, duration)
131+
case "modules" :: value :: "--prefix" :: prefix :: "monitor" :: tail if validateModules(value) => {
132+
val (remainingArgs, monitors) = cliMonitorsSubcommand(List(), Map(), tail.map(_.toString))
133+
cli(options :+ Map('modules -> value, 'prefix -> Some(prefix), 'monitors -> monitors), duration, remainingArgs)
134+
}
130135
case "modules" :: value :: "monitor" :: tail if validateModules(value) => {
131136
val (remainingArgs, monitors) = cliMonitorsSubcommand(List(), Map(), tail.map(_.toString))
132-
cli(options :+ Map('modules -> value, 'monitors -> monitors), duration, remainingArgs)
137+
cli(options :+ Map('modules -> value, 'prefix -> None, 'monitors -> monitors), duration, remainingArgs)
133138
}
134139
case "duration" :: value :: tail if validateDuration(value) => cli(options, value, tail)
135140
case option :: tail => println(s"unknown cli option $option"); sys.exit(1)
136141
}
137142

138143
def cliMonitorsSubcommand(options: List[Map[Symbol, Any]], currentMonitor: Map[Symbol, Any], args: List[String]): (List[String], List[Map[Symbol, Any]]) = args match {
139144
case Nil => (List(), options :+ currentMonitor)
145+
case "modules" :: value :: "--prefix" :: prefix :: "monitor" :: tail if validateModules(value) => (List("modules", value, "--prefix", prefix, "monitor") ++ tail, options :+ currentMonitor)
140146
case "modules" :: value :: "monitor" :: tail if validateModules(value) => (List("modules", value, "monitor") ++ tail, options :+ currentMonitor)
141147
case "duration" :: value :: tail if validateDuration(value) => (List("duration", value) ++ tail, options :+ currentMonitor)
142148
case "monitor" :: tail => cliMonitorsSubcommand(options :+ currentMonitor, Map(), tail)
@@ -155,7 +161,7 @@ object PowerAPI extends App {
155161
}
156162

157163
else {
158-
if(!System.getProperty("os.name").startsWith("Windows")) Seq("bash", "scripts/system.bash").!
164+
if(System.getProperty("os.name").toLowerCase.indexOf("nix") >= 0 || System.getProperty("os.name").toLowerCase.indexOf("nux") >= 0) Seq("bash", "scripts/system.bash").!
159165
val (configuration, duration) = cli(List(), "3600", args.toList)
160166

161167
var libpfmHelper: Option[LibpfmHelper] = None
@@ -166,17 +172,15 @@ object PowerAPI extends App {
166172
}
167173

168174
for(powerMeterConf <- configuration) {
169-
val modulesStr = powerMeterConf('modules).toString
170-
171-
val modules = (for(module <- modulesStr.split(",")) yield {
175+
val modules = (for(module <- powerMeterConf('modules).toString.split(",")) yield {
172176
module match {
173-
case "cpu-simple" => CpuSimpleModule()
177+
case "procfs-cpu-simple" => ProcFSCpuSimpleModule()
178+
case "sigar-cpu-simple" => SigarCpuSimpleModule()
174179
case "cpu-dvfs" => CpuDvfsModule()
175-
case "libpfm-core" => LibpfmCoreModule(libpfmHelper.get)
176-
case "libpfm-core-process" => LibpfmCoreProcessModule(libpfmHelper.get)
180+
case "libpfm-core" => LibpfmCoreModule(powerMeterConf('prefix).asInstanceOf[Option[String]], libpfmHelper.get)
181+
case "libpfm-core-process" => LibpfmCoreProcessModule(powerMeterConf('prefix).asInstanceOf[Option[String]], libpfmHelper.get)
177182
case "powerspy" => PowerSpyModule()
178183
case "rapl" => RAPLModule()
179-
case "sigar" => SigarModule()
180184
}
181185
}).toSeq
182186

powerapi-core/src/main/scala/org/powerapi/PowerMeter.scala

+7-7
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ object PowerMeterMessages {
4848
/**
4949
* Main configuration.
5050
*/
51-
trait PowerMeterConfiguration extends Configuration {
51+
class PowerMeterConfiguration extends Configuration(None) {
5252
lazy val timeout: Timeout = load { _.getDuration("powerapi.actors.timeout", TimeUnit.MILLISECONDS) } match {
5353
case ConfigValue(value) => Timeout(value.milliseconds)
5454
case _ => Timeout(15l.seconds)
@@ -101,12 +101,12 @@ class PowerMeterActor(eventBus: MessageBus, modules: Seq[PowerModule], timeout:
101101
}
102102

103103
/**
104-
* Implements the main functionalities for configuring a <i>Software-Defined Power Meter</i>.
104+
* Implements the main features for configuring a <i>Software-Defined Power Meter</i>.
105105
*
106106
* @author <a href="mailto:[email protected]">Romain Rouvoy</a>
107107
* @author <a href="mailto:[email protected]">Loïc Huertas</a>
108108
*/
109-
class PowerMeter(modules: Seq[PowerModule], system: ActorSystem) extends Configuration with PowerMeterConfiguration {
109+
class PowerMeter(system: ActorSystem, modules: Seq[PowerModule]) extends PowerMeterConfiguration {
110110
private val eventBus = new MessageBus
111111
private val powerMeterActor = system.actorOf(Props(classOf[PowerMeterActor], eventBus, modules, timeout))
112112

@@ -147,18 +147,18 @@ class PowerMeter(modules: Seq[PowerModule], system: ActorSystem) extends Configu
147147
}
148148

149149
object PowerMeter {
150-
lazy val system = ActorSystem(s"PowerMeter-${System.nanoTime()}")
150+
lazy val system = ActorSystem(s"PowerMeter-${System.nanoTime}")
151151

152152
/**
153153
* Loads a specific power module as a tuple (sensor,formula).
154154
*
155-
* Example: `PowerMeter.load(PowerSpyModule, system)`
155+
* Example: `PowerMeter.loadModule(PowerSpyModule)`
156156
*
157-
* @param modules: the list of power modules to be loaded within the PowerMeter.
157+
* @param modules: PowerModule to be loaded within the PowerMeter.
158158
* @return the resulting instance of the requested power meter.
159159
*/
160160
def loadModule(modules: PowerModule*): PowerMeter = {
161-
new PowerMeter(modules, system)
161+
new PowerMeter(system, modules)
162162
}
163163
}
164164

powerapi-core/src/main/scala/org/powerapi/core/Configuration.scala

+7-1
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,15 @@ case class ConfigError[T](exception: Throwable) extends ConfigResult[T]
4242
*
4343
* @author <a href="mailto:[email protected]">Maxime Colmant</a>
4444
*/
45-
trait Configuration {
45+
abstract class Configuration(prefix: Option[String] = None) {
4646
private lazy val conf = ConfigFactory.load()
4747

48+
val configurationPath = prefix match {
49+
case Some(p) if p.endsWith(".") => s"$p"
50+
case Some(p) => s"$p."
51+
case None => ""
52+
}
53+
4854
/**
4955
* Method to load a value from a configuration file.
5056
*

powerapi-core/src/main/scala/org/powerapi/core/MonitorActors.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ class MonitorChild(eventBus: MessageBus,
125125
*
126126
* @author Maxime Colmant <[email protected]>
127127
*/
128-
class Monitors(eventBus: MessageBus) extends Supervisor with Configuration {
128+
class Monitors(eventBus: MessageBus) extends Supervisor {
129129

130130
override def preStart(): Unit = {
131131
subscribeMonitorsChannel(eventBus)(self)

powerapi-core/src/main/scala/org/powerapi/core/OSHelper.scala

+9-9
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import org.powerapi.core.FileHelper.using
3232
import org.powerapi.core.target.{All, Application, Process, Target, TargetUsageRatio}
3333
import org.powerapi.module.{Cache, CacheKey}
3434
import scala.collection.JavaConversions._
35-
import scala.sys.process._
35+
import scala.sys.process.stringSeqToProcess
3636

3737
/**
3838
* This is not a monitoring target. It's an internal wrapper for the Thread IDentifier.
@@ -161,7 +161,7 @@ trait OSHelper {
161161
*
162162
* @author <a href="mailto:[email protected]">Maxime Colmant</a>
163163
*/
164-
class LinuxHelper extends OSHelper with Configuration {
164+
class LinuxHelper extends Configuration(None) with OSHelper {
165165
private val log = LogManager.getLogger
166166

167167
private val PSFormat = """^\s*(\d+)\s*""".r
@@ -172,15 +172,15 @@ class LinuxHelper extends OSHelper with Configuration {
172172
* This file allows to get all the cpu frequencies with the help of procfs and cpufreq_utils.
173173
*/
174174
lazy val frequenciesPath = load { _.getString("powerapi.procfs.frequencies-path") } match {
175-
case ConfigValue(path) if path.contains("%?core") => path
175+
case ConfigValue(p) if p.contains("%?core") => p
176176
case _ => "/sys/devices/system/cpu/cpu%?core/cpufreq/scaling_available_frequencies"
177177
}
178178

179179
/**
180180
* This file allows to get all threads associated to one PID with the help of the procfs.
181181
*/
182182
lazy val taskPath = load { _.getString("powerapi.procfs.process-task-path") } match {
183-
case ConfigValue(path) if path.contains("%?pid") => path
183+
case ConfigValue(p) if p.contains("%?pid") => p
184184
case _ => "/proc/%?pid/task"
185185
}
186186

@@ -189,7 +189,7 @@ class LinuxHelper extends OSHelper with Configuration {
189189
* Typically presents under /proc/stat.
190190
*/
191191
lazy val globalStatPath = load { _.getString("powerapi.procfs.global-path") } match {
192-
case ConfigValue(path) => path
192+
case ConfigValue(p) => p
193193
case _ => "/proc/stat"
194194
}
195195

@@ -198,15 +198,15 @@ class LinuxHelper extends OSHelper with Configuration {
198198
* Typically presents under /proc/[pid]/stat.
199199
*/
200200
lazy val processStatPath = load { _.getString("powerapi.procfs.process-path") } match {
201-
case ConfigValue(path) if path.contains("%?pid") => path
201+
case ConfigValue(p) if p.contains("%?pid") => p
202202
case _ => "/proc/%?pid/stat"
203203
}
204204

205205
/**
206206
* Time in state file, giving information about how many time CPU spent under each frequency.
207207
*/
208208
lazy val timeInStatePath = load { _.getString("powerapi.sysfs.timeinstates-path") } match {
209-
case ConfigValue(path) => path
209+
case ConfigValue(p) => p
210210
case _ => "/sys/devices/system/cpu/cpu%?index/cpufreq/stats/time_in_state"
211211
}
212212

@@ -371,14 +371,14 @@ class LinuxHelper extends OSHelper with Configuration {
371371
*
372372
* @author <a href="mailto:[email protected]">Loïc Huertas</a>
373373
*/
374-
class SigarHelper extends OSHelper with Configuration {
374+
class SigarHelper extends Configuration(None) with OSHelper {
375375
private val log = LogManager.getLogger
376376

377377
/**
378378
* Sigar native libraries
379379
*/
380380
lazy val libNativePath = load { _.getString("powerapi.sigar.native-path") } match {
381-
case ConfigValue(path) => path
381+
case ConfigValue(p) => p
382382
case _ => "./lib"
383383
}
384384

powerapi-core/src/main/scala/org/powerapi/module/cpu/dvfs/CpuDvfsModule.scala

+6-7
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,18 @@
2222
*/
2323
package org.powerapi.module.cpu.dvfs
2424

25-
import com.typesafe.config.Config
2625
import org.powerapi.PowerModule
27-
import org.powerapi.core.{Configuration, ConfigValue, LinuxHelper}
26+
import org.powerapi.core.{OSHelper, LinuxHelper}
2827

29-
import scala.collection.JavaConversions
30-
31-
class CpuDvfsModule(tdp: Double, tdpFactor: Double, frequencies: Map[Int, Double]) extends PowerModule {
32-
lazy val underlyingSensorsClasses = Seq((classOf[CpuSensor], Seq(new LinuxHelper)))
28+
class CpuDvfsModule(osHelper: OSHelper, tdp: Double, tdpFactor: Double, frequencies: Map[Int, Double]) extends PowerModule {
29+
lazy val underlyingSensorsClasses = Seq((classOf[CpuSensor], Seq(osHelper)))
3330
lazy val underlyingFormulaeClasses = Seq((classOf[CpuFormula], Seq(tdp, tdpFactor, frequencies)))
3431
}
3532

3633
object CpuDvfsModule extends CpuFormulaConfiguration {
3734
def apply(): CpuDvfsModule = {
38-
new CpuDvfsModule(tdp, tdpFactor, frequencies)
35+
val linuxHelper = new LinuxHelper
36+
37+
new CpuDvfsModule(linuxHelper, tdp, tdpFactor, frequencies)
3938
}
4039
}

powerapi-core/src/main/scala/org/powerapi/module/cpu/simple/CpuFormulaConfiguration.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ trait CpuFormulaConfiguration extends Configuration {
4545
*
4646
* @see [1], JouleSort: A Balanced Energy-Efficiency Benchmark, by Rivoire et al.
4747
*/
48-
lazy val tdpFactor = load { _.getDouble("powerapi.cpu.tdp-factor") } match {
48+
lazy val tdpFactor = load { _.getDouble(s"powerapi.cpu.tdp-factor") } match {
4949
case ConfigValue(value) => value
5050
case _ => 0.7
5151
}

powerapi-core/src/main/scala/org/powerapi/module/cpu/simple/CpuSensor.scala

+2-4
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,7 @@ class CpuSensor(eventBus: MessageBus, osHelper: OSHelper) extends SensorComponen
5757
publishUsageReport(monitorTick.muid, monitorTick.target, targetCpuUsageRatio(monitorTick), monitorTick.tick)(eventBus)
5858
}
5959

60-
def monitorStopped(msg: MonitorStop): Unit = {
61-
}
60+
def monitorStopped(msg: MonitorStop): Unit = {}
6261

63-
def monitorAllStopped(msg: MonitorStopAll): Unit = {
64-
}
62+
def monitorAllStopped(msg: MonitorStopAll): Unit = {}
6563
}

powerapi-core/src/main/scala/org/powerapi/module/cpu/simple/CpuSimpleModule.scala

+15-5
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,25 @@
2323
package org.powerapi.module.cpu.simple
2424

2525
import org.powerapi.PowerModule
26-
import org.powerapi.core.{Configuration, ConfigValue, LinuxHelper}
26+
import org.powerapi.core.{SigarHelper, LinuxHelper, OSHelper}
2727

28-
class CpuSimpleModule(tdp: Double, tdpFactor: Double) extends PowerModule {
29-
lazy val underlyingSensorsClasses = Seq((classOf[CpuSensor], Seq(new LinuxHelper)))
28+
class CpuSimpleModule(osHelper: OSHelper, tdp: Double, tdpFactor: Double) extends PowerModule {
29+
lazy val underlyingSensorsClasses = Seq((classOf[CpuSensor], Seq(osHelper)))
3030
lazy val underlyingFormulaeClasses = Seq((classOf[CpuFormula], Seq(tdp, tdpFactor)))
3131
}
3232

33-
object CpuSimpleModule extends CpuFormulaConfiguration {
33+
object ProcFSCpuSimpleModule extends CpuFormulaConfiguration {
3434
def apply(): CpuSimpleModule = {
35-
new CpuSimpleModule(tdp, tdpFactor)
35+
val linuxHelper = new LinuxHelper
36+
37+
new CpuSimpleModule(linuxHelper, tdp, tdpFactor)
38+
}
39+
}
40+
41+
object SigarCpuSimpleModule extends CpuFormulaConfiguration {
42+
def apply(): CpuSimpleModule = {
43+
val sigarHelper = new SigarHelper
44+
45+
new CpuSimpleModule(sigarHelper, tdp, tdpFactor)
3646
}
3747
}

powerapi-core/src/main/scala/org/powerapi/module/libpfm/LibpfmCoreModule.scala

+14-21
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,14 @@ class LibpfmCoreModule(libpfmHelper: LibpfmHelper, timeout: Timeout, topology: M
3535
lazy val underlyingFormulaeClasses = Seq((classOf[LibpfmCoreCyclesFormula], Seq(cyclesThreadName, cyclesRefName, formulae, samplingInterval)))
3636
}
3737

38-
object LibpfmCoreModule extends LibpfmCoreSensorConfiguration with LibpfmCoreCyclesFormulaConfiguration {
39-
lazy val libpfmHelper = new LibpfmHelper
38+
object LibpfmCoreModule {
39+
def apply(prefixConfig: Option[String] = None, libpfmHelper: LibpfmHelper): LibpfmCoreModule = {
40+
val coreSensorConfig = new LibpfmCoreSensorConfiguration(prefixConfig)
41+
val coreCyclesFormulaConfig = new LibpfmCoreCyclesFormulaConfiguration(prefixConfig)
4042

41-
def apply(): LibpfmCoreModule = {
42-
new LibpfmCoreModule(libpfmHelper, timeout, topology, configuration, events, cyclesThreadName, cyclesRefName, formulae, samplingInterval)
43-
}
44-
45-
def apply(libpfmHelper: LibpfmHelper): LibpfmCoreModule = {
46-
new LibpfmCoreModule(libpfmHelper, timeout, topology, configuration, events, cyclesThreadName, cyclesRefName, formulae, samplingInterval)
43+
new LibpfmCoreModule(libpfmHelper, coreSensorConfig.timeout, coreSensorConfig.topology, coreSensorConfig.configuration,
44+
coreSensorConfig.events, coreCyclesFormulaConfig.cyclesThreadName, coreCyclesFormulaConfig.cyclesRefName,
45+
coreCyclesFormulaConfig.formulae, coreCyclesFormulaConfig.samplingInterval)
4746
}
4847
}
4948

@@ -52,22 +51,16 @@ class LibpfmCoreSensorModule(libpfmHelper: LibpfmHelper, timeout: Timeout, topol
5251
lazy val underlyingFormulaeClasses = Seq()
5352
}
5453

55-
object LibpfmCoreSensorModule extends LibpfmCoreSensorConfiguration {
56-
lazy val libpfmHelper = new LibpfmHelper
54+
object LibpfmCoreSensorModule {
55+
def apply(prefixConfig: Option[String] = None, libpfmHelper: LibpfmHelper): LibpfmCoreSensorModule = {
56+
val coreSensorConfig = new LibpfmCoreSensorConfiguration(prefixConfig)
5757

58-
def apply(): LibpfmCoreSensorModule = {
59-
new LibpfmCoreSensorModule(libpfmHelper, timeout, topology, configuration, events)
58+
new LibpfmCoreSensorModule(libpfmHelper, coreSensorConfig.timeout, coreSensorConfig.topology, coreSensorConfig.configuration, coreSensorConfig.events)
6059
}
6160

62-
def apply(libpfmHelper: LibpfmHelper): LibpfmCoreSensorModule = {
63-
new LibpfmCoreSensorModule(libpfmHelper, timeout, topology, configuration, events)
64-
}
65-
66-
def apply(events: Set[String]): LibpfmCoreSensorModule = {
67-
new LibpfmCoreSensorModule(libpfmHelper, timeout, topology, configuration, events)
68-
}
61+
def apply(prefixConfig: Option[String], libpfmHelper: LibpfmHelper, events: Set[String]): LibpfmCoreSensorModule = {
62+
val coreSensorConfig = new LibpfmCoreSensorConfiguration(prefixConfig)
6963

70-
def apply(libpfmHelper: LibpfmHelper, events: Set[String]): LibpfmCoreSensorModule = {
71-
new LibpfmCoreSensorModule(libpfmHelper, timeout, topology, configuration, events)
64+
new LibpfmCoreSensorModule(libpfmHelper, coreSensorConfig.timeout, coreSensorConfig.topology, coreSensorConfig.configuration, events)
7265
}
7366
}

0 commit comments

Comments
 (0)