From: Ronald Rojas <ronladred@gmail.com>
To: xen-devel <xen-devel@lists.xen.org>,
Ian Jackson <ian.jackson@eu.citrix.com>,
Wei Liu <wei.liu2@citrix.com>,
George Dunlap <george.dunlap@citrix.com>,
George Dunlap <dunlapg@umich.edu>
Subject: [PATCH RFC 11/59] Refactor to move towards benchmark "plans" and data analysis
Date: Wed, 28 Dec 2016 20:14:04 -0500 [thread overview]
Message-ID: <1482974092-15891-11-git-send-email-ronladred@gmail.com> (raw)
In-Reply-To: <1482974092-15891-1-git-send-email-ronladred@gmail.com>
From: George Dunlap <george.dunlap@citrix.com>
A bit of a roll-up of lots of bits.
Signed-off-by: George Dunlap <george.dunlap@citrix.com>
---
Makefile | 4 +-
benchmark.go | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
main.go | 197 ++++++++++-----------------------------------
3 files changed, 302 insertions(+), 155 deletions(-)
create mode 100644 benchmark.go
diff --git a/Makefile b/Makefile
index 16af528..7a33cfb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
-BIN = controller
+BIN = schedbench
BINALL = $(BIN)
.PHONY: all
all: $(BIN)
-controller: main.go processworker.go xenworker.go
+schedbench: main.go processworker.go xenworker.go benchmark.go
go build -o $@ $^
.PHONY: clean
diff --git a/benchmark.go b/benchmark.go
new file mode 100644
index 0000000..b2b2399
--- /dev/null
+++ b/benchmark.go
@@ -0,0 +1,256 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/signal"
+ "time"
+ "io/ioutil"
+ "encoding/json"
+)
+
+type WorkerReport struct {
+ Id int
+ Now int
+ Mops int
+ MaxDelta int
+}
+
+type WorkerParams struct {
+ Args []string
+}
+
+type WorkerSet struct {
+ Params WorkerParams
+ Count int
+}
+
+type Worker interface {
+ SetId(int)
+ Init(WorkerParams) error
+ Shutdown()
+ Process(chan WorkerReport, chan bool)
+}
+
+const (
+ USEC = 1000
+ MSEC = USEC * 1000
+ SEC = MSEC * 1000
+)
+
+type WorkerState struct {
+ w Worker
+ LastReport WorkerReport
+}
+
+func Report(ws *WorkerState, r WorkerReport) {
+ //fmt.Println(r)
+
+ lr := ws.LastReport
+
+ if (lr.Now > 0) {
+ time := float64(r.Now - lr.Now) / SEC
+ mops := r.Mops - lr.Mops
+
+ tput := float64(mops) / time
+
+ fmt.Printf("%d Time: %2.3f Mops: %d Tput: %4.2f\n", r.Id, time, mops, tput);
+ }
+
+ ws.LastReport = r
+}
+
+type WorkerList []WorkerState
+
+func (ws *WorkerList) Start(report chan WorkerReport, done chan bool) (i int) {
+ i = 0
+ for j := range *ws {
+ go (*ws)[j].w.Process(report, done)
+ i++
+ }
+ return
+}
+
+func (ws *WorkerList) Stop() {
+ for i := range *ws {
+ (*ws)[i].w.Shutdown()
+ }
+}
+
+const (
+ WorkerProcess = iota
+ WorkerXen = iota
+)
+
+func NewWorkerList(workers []WorkerSet, workerType int) (ws WorkerList, err error) {
+ count := 0
+
+ // wsi: WorkerSet index
+ for wsi := range workers {
+ count += workers[wsi].Count
+ }
+
+ fmt.Println("Making ", count, " total workers")
+ ws = WorkerList(make([]WorkerState, count))
+
+ // wli: WorkerList index
+ wli := 0
+ for wsi := range workers {
+ for i := 0; i < workers[wsi].Count; i, wli = i+1, wli+1 {
+ switch workerType {
+ case WorkerProcess:
+ ws[wli].w = &ProcessWorker{}
+ case WorkerXen:
+ ws[wli].w = &XenWorker{}
+ default:
+ err = fmt.Errorf("Unknown type: %d", workerType)
+ }
+ ws[wli].w.SetId(wli)
+
+ ws[wli].w.Init(workers[wsi].Params)
+ }
+ }
+ return
+}
+
+type BenchmarkRunData struct {
+ Raw []WorkerReport
+}
+
+type BenchmarkRun struct {
+ Completed bool
+ Label string
+ Workers []WorkerSet
+ RuntimeSeconds int
+ Results BenchmarkRunData
+}
+
+func (run *BenchmarkRun) Run() (err error) {
+ Workers, err := NewWorkerList(run.Workers, WorkerProcess)
+ if err != nil {
+ fmt.Println("Error creating workers: %v", err)
+ return
+ }
+
+ report := make(chan WorkerReport)
+ done := make(chan bool)
+ signals := make(chan os.Signal, 1)
+
+ signal.Notify(signals, os.Interrupt)
+
+ i := Workers.Start(report, done)
+
+ // FIXME:
+ // 1. Make a zero timeout mean "never"
+ // 2. Make the signals / timeout thing a bit more rational; signal then timeout shouldn't hard kill
+ timeout := time.After(time.Duration(run.RuntimeSeconds) * time.Second);
+ stopped := false
+ for i > 0 {
+ select {
+ case r := <-report:
+ run.Results.Raw = append(run.Results.Raw, r)
+ Report(&Workers[r.Id], r)
+ case <-done:
+ i--;
+ fmt.Println(i, "workers left");
+ case <-timeout:
+ if ! stopped {
+ Workers.Stop()
+ stopped = true
+ run.Completed = true
+ }
+ case <-signals:
+ if ! stopped {
+ fmt.Println("SIGINT receieved, shutting down workers")
+ Workers.Stop()
+ stopped = true
+ if run.RuntimeSeconds == 0 {
+ run.Completed = true
+ }
+ err = fmt.Errorf("Interrupted")
+ } else {
+ err = fmt.Errorf("Interrupted")
+ fmt.Println("SIGINT received after stop, exiting without cleaning up")
+ return
+ }
+ }
+ }
+ return
+}
+
+type BenchmarkPlan struct {
+ filename string
+ Runs []BenchmarkRun
+}
+
+func (plan *BenchmarkPlan) Run() (err error) {
+ for i := range plan.Runs {
+ if ! plan.Runs[i].Completed {
+ fmt.Printf("Running test [%d] %s\n", i, plan.Runs[i].Label)
+ err = plan.Runs[i].Run()
+ if err != nil {
+ return
+ }
+ }
+ fmt.Printf("Test [%d] %s completed\n", i, plan.Runs[i].Label)
+ err = plan.Save()
+ if err != nil {
+ fmt.Println("Error saving: ", err)
+ return
+ }
+ }
+ return
+}
+
+func LoadBenchmark(filename string) (plan BenchmarkPlan, err error) {
+ plan.filename = filename
+
+ var b []byte
+ b, err = ioutil.ReadFile(filename)
+ if err != nil {
+ return
+ }
+
+ err = json.Unmarshal(b, &plan)
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+func (plan *BenchmarkPlan) Save() (err error) {
+ if plan.filename == "" {
+ err = fmt.Errorf("Invalid filename")
+ return
+ }
+
+ var b []byte
+ b, err = json.Marshal(*plan)
+ if err != nil {
+ return
+ }
+
+ backupFilename := fmt.Sprintf(".%s.tmp", plan.filename)
+ err = os.Rename(plan.filename, backupFilename)
+ if err != nil {
+ if os.IsNotExist(err) {
+ backupFilename = ""
+ } else {
+ return
+ }
+ }
+
+ err = ioutil.WriteFile(plan.filename, b, 0666)
+ if err != nil {
+ if backupFilename != "" {
+ os.Rename(backupFilename, plan.filename)
+ }
+ return
+ }
+
+ if backupFilename != "" {
+ os.Remove(backupFilename)
+ }
+ return
+}
diff --git a/main.go b/main.go
index 7fbb60a..4d9701c 100644
--- a/main.go
+++ b/main.go
@@ -3,163 +3,54 @@ package main
import (
"fmt"
"os"
- "os/signal"
- "time"
)
-type WorkerReport struct {
- Id int
- Now int
- Mops int
- MaxDelta int
-}
-
-type WorkerParams struct {
- Args []string
-}
-
-type WorkerSet struct {
- Params WorkerParams
- Count int
-}
-
-type BenchmarkParams struct {
- Workers []WorkerSet
- RuntimeSeconds int
-}
-
-type Worker interface {
- SetId(int)
- Init(WorkerParams) error
- Shutdown()
- Process(chan WorkerReport, chan bool)
-}
-
-const (
- USEC = 1000
- MSEC = USEC * 1000
- SEC = MSEC * 1000
-)
-
-type WorkerState struct {
- w Worker
- LastReport WorkerReport
-}
-
-func Report(ws *WorkerState, r WorkerReport) {
- //fmt.Println(r)
-
- lr := ws.LastReport
-
- if (lr.Now > 0) {
- time := float64(r.Now - lr.Now) / SEC
- mops := r.Mops - lr.Mops
-
- tput := float64(mops) / time
-
- fmt.Printf("%d Time: %2.3f Mops: %d Tput: %4.2f\n", r.Id, time, mops, tput);
- }
-
- ws.LastReport = r
-}
-
-type WorkerList []WorkerState
-
-func (ws *WorkerList) Start(report chan WorkerReport, done chan bool) (i int) {
- i = 0
- for j := range *ws {
- go (*ws)[j].w.Process(report, done)
- i++
- }
- return
-}
-
-func (ws *WorkerList) Stop() {
- for i := range *ws {
- (*ws)[i].w.Shutdown()
- }
-}
-
-const (
- WorkerProcess = iota
- WorkerXen = iota
-)
-
-func NewWorkerList(workers []WorkerSet, workerType int) (ws WorkerList, err error) {
- count := 0
-
- // wsi: WorkerSet index
- for wsi := range workers {
- count += workers[wsi].Count
- }
-
- fmt.Println("Making ", count, " total workers")
- ws = WorkerList(make([]WorkerState, count))
-
- // wli: WorkerList index
- wli := 0
- for wsi := range workers {
- for i := 0; i < workers[wsi].Count; i, wli = i+1, wli+1 {
- switch workerType {
- case WorkerProcess:
- ws[wli].w = &ProcessWorker{}
- case WorkerXen:
- ws[wli].w = &XenWorker{}
- default:
- err = fmt.Errorf("Unknown type: %d", workerType)
- }
- ws[wli].w.SetId(wli)
-
- ws[wli].w.Init(workers[wsi].Params)
- }
- }
- return
-}
-
func main() {
- bp := BenchmarkParams{
- Workers:[]WorkerSet{
- {Params:WorkerParams{[]string{"burnwait", "20", "20000000"}},
- Count:2},
- {Params:WorkerParams{[]string{"burnwait", "10", "30000000"}},
- Count:3},
- },
- RuntimeSeconds:5,
- }
-
- Workers, err := NewWorkerList(bp.Workers, WorkerProcess)
- if err != nil {
- fmt.Println("Error creating workers: %v", err)
- return
- }
-
- report := make(chan WorkerReport)
- done := make(chan bool)
- signals := make(chan os.Signal, 1)
-
- signal.Notify(signals, os.Interrupt)
+ filename := "test.bench"
+
+ switch(os.Args[1]) {
+ case "plan":
+ plan := BenchmarkPlan{
+ filename:filename,
+ Runs:[]BenchmarkRun{
+ {Label:"baseline-a",
+ Workers:[]WorkerSet{
+ {Params:WorkerParams{[]string{"burnwait", "20", "20000000"}},
+ Count:1}},
+ RuntimeSeconds:5,},
+ {Label:"baseline-b",
+ Workers:[]WorkerSet{
+ {Params:WorkerParams{[]string{"burnwait", "10", "20000000"}},
+ Count:1}},
+ RuntimeSeconds:5,},
+ {Label:"4a+4b",
+ Workers:[]WorkerSet{
+ {Params:WorkerParams{[]string{"burnwait", "20", "20000000"}},
+ Count:4},
+ {Params:WorkerParams{[]string{"burnwait", "10", "30000000"}},
+ Count:4}},
+ RuntimeSeconds:5,},
+ }}
+ err := plan.Save()
+ if err != nil {
+ fmt.Println("Saving plan ", filename, " ", err)
+ os.Exit(1)
+ }
+ fmt.Println("Created plan in ", filename)
+ case "run":
+ plan, err := LoadBenchmark(filename)
+ if err != nil {
+ fmt.Println("Loading benchmark ", filename, " ", err)
+ os.Exit(1)
+ }
- i := Workers.Start(report, done)
-
- timeout := time.After(time.Duration(bp.RuntimeSeconds) * time.Second);
- killed := false
- for i > 0 {
- select {
- case r := <-report:
- Report(&Workers[r.Id], r)
- case <-done:
- i--;
- fmt.Println(i, "workers left");
- case <-signals:
- case <-timeout:
- if ! killed {
- fmt.Println("SIGINT receieved, shutting down workers")
- Workers.Stop()
- killed = true
- } else {
- fmt.Println("Second SIGINT received, exiting without cleaning up")
- os.Exit(1)
- }
+ err = plan.Run()
+ if err != nil {
+ fmt.Println("Running benchmark run:", err)
+ os.Exit(1)
}
+ default:
+ fmt.Println("Unknown argument: ", os.Args[1])
}
}
+
--
2.7.4
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
next prev parent reply other threads:[~2016-12-29 1:14 UTC|newest]
Thread overview: 67+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-29 1:13 [PATCH RFC 01/59] Initial controller framework Ronald Rojas
2016-12-29 1:13 ` [PATCH RFC 02/59] controller: Revamp communication structure Ronald Rojas
2016-12-29 1:13 ` [PATCH RFC 03/59] controller: Initial attempt to generalize process / vm creation Ronald Rojas
2016-12-29 1:13 ` [PATCH RFC 04/59] Controller: Move process worker into its own file Ronald Rojas
2016-12-29 1:13 ` [PATCH RFC 05/59] controller: Add WorkerParams argument to Init in Worker interface Ronald Rojas
2016-12-29 1:13 ` [PATCH RFC 06/59] Reorganize to enable "Dist" directory Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 07/59] controller: Introduce basic Xen functionality Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 08/59] controller: Exit after second SIGINT Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 09/59] controller: Refactor creation and stopping of workers into WorkerList methods Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 10/59] controller: First cut at BenchmarkParams Ronald Rojas
2016-12-29 1:14 ` Ronald Rojas [this message]
2016-12-29 1:14 ` [PATCH RFC 12/59] Basic 'report' functionality Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 13/59] Add GPL headers / COPYING file (v2 only) Ronald Rojas
2016-12-29 10:51 ` Wei Liu
2016-12-29 1:14 ` [PATCH RFC 14/59] benchmark: Store data in terms of worker sets and worker ids Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 15/59] controller: Move "running" code to a separate file Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 16/59] controller: Rename an element in BenchmarkRun to be more accurate Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 17/59] controller: Collect and display statistics on WorkerSets Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 18/59] controller: Add cpupool global config Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 19/59] Add basic libxl framework, get domain cpu_time Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 20/59] xenworker: Use libxl_domain_unpause rather than forking xl Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 21/59] Report utilization statistics Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 22/59] Use tsc for time rather than rumpkernel clock_gettime() Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 23/59] run: Don't collect results reported after command to stop guests is issued Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 24/59] report: Lots of changes Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 25/59] main: Change default workload to something a bit more extreme Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 26/59] Use kops rather than mops Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 27/59] report: Allow report verbosity to be specified Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 28/59] controller: Handle worker early death Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 29/59] report: Add basic html report Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 30/59] htmlreport: Include utilization scatterplots Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 31/59] Make a binary that can run reports on a system without libxl Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 32/59] controller: Allow specification of an input file Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 33/59] controller: Add verbosity argument and update README with new instructions Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 34/59] controller: Make a useful config file Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 35/59] libxl: Add ListCpupool Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 36/59] controller: Make 'dummy' at the level of 'run' rather than xenworker Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 37/59] libxl.go: Provide a single global context by default Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 38/59] controller: Allow multiple schedulers in the same benchmark file Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 39/59] libxl.go: Put common link flags in libxl.go Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 40/59] controller: Add / update GPL text Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 41/59] libxl.go: Link statically rather than dynamically Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 42/59] plan: Allow "templating" from other runs Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 43/59] libxl: Add bitmap support Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 44/59] libxl: Implement CpupoolCreate Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 45/59] libxl: Implement Destroy, Add/Remove operations Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 46/59] libxl: Reorganize bitmapGotoC Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 47/59] libxl: Reorganize code Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 48/59] libxl: Add Ctx.CheckOpen Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 49/59] libxl: Implement libxl_cpupool_info and Scheduler.FromString() Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 50/59] libxl: Fix Bitmap.Max(), make Test() / Clear() more robust Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 51/59] controller: Make and/or modify cpupools when possible Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 52/59] libxl: Implement Bitmap.String() Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 53/59] controller: Add WorkerConfig.SoftAffinity Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 54/59] controller/run: Add RunConfig.NumaDisable Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 55/59] plan: Make the matrix generation more programmatic Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 56/59] controller/plan: Add NumaDisable to SimpleMatrix Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 57/59] tools/blktap2: remove unused inclusion of sys/sysctl.l Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 58/59] remove irrelevant files from old repository Ronald Rojas
2016-12-29 1:14 ` [PATCH RFC 59/59] tools/xenlight: Create interface for xenlight info Ronald Rojas
2016-12-29 10:34 ` George Dunlap
2016-12-29 10:52 ` Wei Liu
2016-12-29 13:49 ` Ronald Rojas
2016-12-29 13:45 ` George Dunlap
2016-12-29 20:20 ` George Dunlap
2017-01-03 17:45 ` Ronald Rojas
2017-01-04 16:44 ` George Dunlap
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1482974092-15891-11-git-send-email-ronladred@gmail.com \
--to=ronladred@gmail.com \
--cc=dunlapg@umich.edu \
--cc=george.dunlap@citrix.com \
--cc=ian.jackson@eu.citrix.com \
--cc=wei.liu2@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).