xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
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 12/59] Basic 'report' functionality
Date: Wed, 28 Dec 2016 20:14:05 -0500	[thread overview]
Message-ID: <1482974092-15891-12-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>

Go through the raw data and re-calculate throughput for each
timeframe.  Record for each worker the min and max of these; then take
an average over the whole run.

Have the report go through each and show the worker setup, as well as
the avg, min, and max for each worker.

Also default to running Xen again (rather than processes), and clean
up some chattiness wrt starting Xen processes.

Finally, make the "plan" slightly more programmatic, and test a more
"pipelined" testcase.

Signed-off-by: George Dunlap <george.dunlap@citrix.com>
---
 benchmark.go | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 main.go      |  56 ++++++++++++++++----
 xenworker.go |   4 +-
 3 files changed, 205 insertions(+), 18 deletions(-)

diff --git a/benchmark.go b/benchmark.go
index b2b2399..ec62c3d 100644
--- a/benchmark.go
+++ b/benchmark.go
@@ -9,6 +9,12 @@ import (
 	"encoding/json"
 )
 
+type WorkerSummary struct {
+	MaxTput float64
+	AvgTput float64
+	MinTput float64
+}
+
 type WorkerReport struct {
 	Id int
 	Now int
@@ -43,6 +49,14 @@ type WorkerState struct {
 	LastReport WorkerReport
 }
 
+func Throughput(lt int, lm int, t int, m int) (tput float64) {
+	time := float64(t - lt) / SEC
+	mops := m - lm
+	
+	tput = float64(mops) / time
+	return
+}
+
 func Report(ws *WorkerState, r WorkerReport) {
 	//fmt.Println(r)
 
@@ -52,8 +66,8 @@ func Report(ws *WorkerState, r WorkerReport) {
 		time := float64(r.Now - lr.Now) / SEC
 		mops := r.Mops - lr.Mops
 
-		tput := float64(mops) / time
-
+		tput := Throughput(lr.Now, lr.Mops, r.Now, r.Mops)
+		
 		fmt.Printf("%d Time: %2.3f Mops: %d Tput: %4.2f\n", r.Id, time, mops, tput);
 	}
 
@@ -114,19 +128,21 @@ func NewWorkerList(workers []WorkerSet, workerType int) (ws WorkerList, err erro
 }
 
 type BenchmarkRunData struct {
-	Raw []WorkerReport
+	WorkerCount int
+	Raw []WorkerReport       `json:",omitempty"`
+	Summary []WorkerSummary  `json:",omitempty"`
 }
 
 type BenchmarkRun struct {
-	Completed bool
 	Label string
 	Workers []WorkerSet
 	RuntimeSeconds int
+	Completed bool
 	Results BenchmarkRunData 
 }
 
 func (run *BenchmarkRun) Run() (err error) {
-	Workers, err := NewWorkerList(run.Workers, WorkerProcess)
+	Workers, err := NewWorkerList(run.Workers, WorkerXen)
 	if err != nil {
 		fmt.Println("Error creating workers: %v", err)
 		return
@@ -140,6 +156,8 @@ func (run *BenchmarkRun) Run() (err error) {
 	
 	i := Workers.Start(report, done)
 
+	run.Results.WorkerCount = i
+
 	// 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
@@ -178,8 +196,121 @@ func (run *BenchmarkRun) Run() (err error) {
 	return
 }
 
+func (run *BenchmarkRun) checkSummary() (done bool, err error) {
+	if run.Results.WorkerCount == 0 {
+		err = fmt.Errorf("Internal error: WorkerCount 0!")
+		return
+	}
+	
+	if len(run.Results.Summary) == run.Results.WorkerCount {
+		done = true
+		return 
+	}
+	
+	if len(run.Results.Summary) != 0 {
+		err = fmt.Errorf("Internal error: len(Summary) %d, len(Workers) %d!\n",
+			len(run.Results.Summary), run.Results.WorkerCount)
+		return
+	}
+
+	return
+}
+
+func (run *BenchmarkRun) Process() (err error) {
+	done, err := run.checkSummary()
+	if done || err != nil {
+		return
+	}
+	
+	wcount := run.Results.WorkerCount
+
+	if len(run.Results.Summary) != 0 {
+		err = fmt.Errorf("Internal error: len(Summary) %d, len(Workers) %d!\n",
+			len(run.Results.Summary), wcount)
+		return
+	}
+
+	run.Results.Summary = make([]WorkerSummary, wcount)
+
+	// FIXME: Filter out results which started before all have started
+	
+	data := make([]struct{
+		startTime int
+		lastTime int
+		lastMops int}, wcount)
+
+	for i := range run.Results.Raw {
+		e := run.Results.Raw[i]
+		if e.Id > wcount {
+			err = fmt.Errorf("Internal error: id %d > wcount %d", e.Id, wcount)
+			return
+		}
+		
+		d := &data[e.Id]
+		s := &run.Results.Summary[e.Id]
+
+		if d.startTime == 0 {
+			d.startTime = e.Now
+		} else {
+			tput := Throughput(d.lastTime, d.lastMops, e.Now, e.Mops)
+		
+			if tput > s.MaxTput {
+				s.MaxTput = tput
+			}
+			if tput < s.MinTput || s.MinTput == 0 {
+				s.MinTput = tput
+			}
+		}
+		d.lastTime = e.Now
+		d.lastMops = e.Mops
+	}
+
+	for i := range data {
+		run.Results.Summary[i].AvgTput = Throughput(data[i].startTime, 0, data[i].lastTime, data[i].lastMops)
+	}
+	
+	return
+}
+
+func (run *BenchmarkRun) TextReport() (err error) {
+	var done bool
+	done, err = run.checkSummary()
+	if err != nil {
+		return
+	}
+	if ! done {
+		err = fmt.Errorf("Run not yet processed")
+		return
+	}
+
+	fmt.Printf("== RUN %s ==", run.Label)
+
+	fmt.Printf(" Workers (%d total):\n", run.Results.WorkerCount)
+	wStart := 0
+	for i := range run.Workers {
+		ws := &run.Workers[i]
+		n := ws.Count
+		params := ""
+		for _, s := range ws.Params.Args {
+			params = fmt.Sprintf("%s %s", params, s)
+		}
+		fmt.Printf("[%d-%d]: %s\n", wStart, wStart+n-1, params)
+		wStart += n
+	}
+
+	fmt.Printf("\n%8s %8s %8s %8s\n", "id", "avg", "min", "max")
+	for i := 0; i < run.Results.WorkerCount; i++ {
+		s := &run.Results.Summary[i]
+		fmt.Printf("%8d %8.2f %8.2f %8.2f\n",
+			i, s.AvgTput, s.MinTput, s.MaxTput)
+	}
+
+	return
+}
+
 type BenchmarkPlan struct {
 	filename string
+	WorkerType int
 	Runs []BenchmarkRun
 }
 
@@ -254,3 +385,25 @@ func (plan *BenchmarkPlan) Save() (err error) {
 	}
 	return
 }
+
+func (plan *BenchmarkPlan) TextReport() (err error) {
+	for i := range plan.Runs {
+		r := &plan.Runs[i]
+		if ! r.Completed {
+			fmt.Printf("Test [%d] %s not run\n", i, r.Label)
+		}
+
+		err = r.Process()
+		if err != nil {
+			fmt.Printf("Error processing [%d] %s: %v\n", i, r.Label, err)
+			return
+		}
+
+		err = r.TextReport()
+		if err != nil {
+			return
+		}
+	}
+
+	return
+}
diff --git a/main.go b/main.go
index 4d9701c..2696810 100644
--- a/main.go
+++ b/main.go
@@ -10,27 +10,48 @@ func main() {
 
 	switch(os.Args[1]) {
 	case "plan":
+		workerA := []string{"burnwait", "20", "20000000"}
+		//workerB := []string{"burnwait", "10", "20000000"}
+		workerB := []string{"burnwait", "1", "20000000",
+			"burnwait", "2", "20000000",
+			"burnwait", "1", "20000000",
+			"burnwait", "1", "20000000",
+			"burnwait", "1", "20000000",
+			"burnwait", "1", "20000000",
+			"burnwait", "3", "20000000",
+		}
+
+
 		plan :=  BenchmarkPlan{
+			WorkerType:WorkerXen,
 			filename:filename,
 			Runs:[]BenchmarkRun{
 				{Label:"baseline-a",
 					Workers:[]WorkerSet{
-						{Params:WorkerParams{[]string{"burnwait", "20", "20000000"}},
+						{Params:WorkerParams{workerA},
 							Count:1}},
-					RuntimeSeconds:5,},
+					RuntimeSeconds:10,},
 				{Label:"baseline-b",
 					Workers:[]WorkerSet{
-						{Params:WorkerParams{[]string{"burnwait", "10", "20000000"}},
+						{Params:WorkerParams{workerB},
 							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,},
+					RuntimeSeconds:10,},
 			}}
+
+
+		for i := 1; i <= 16 ; i *= 2 {
+			label := fmt.Sprintf("%da+%db", i, i)
+			run := BenchmarkRun{
+				Label:label,
+				Workers:[]WorkerSet{
+					{Params:WorkerParams{workerA},
+						Count:i},
+					{Params:WorkerParams{workerB},
+						Count:i}},
+				RuntimeSeconds:10}
+			plan.Runs = append(plan.Runs, run)
+		}
+		
 		err := plan.Save()
 		if err != nil {
 			fmt.Println("Saving plan ", filename, " ", err)
@@ -49,6 +70,19 @@ func main() {
 			fmt.Println("Running benchmark run:", err)
 			os.Exit(1)
 		}
+		
+	case "report":
+		plan, err := LoadBenchmark(filename)
+		if err != nil {
+			fmt.Println("Loading benchmark ", filename, " ", err)
+			os.Exit(1)
+		}
+	
+		err = plan.TextReport()
+		if err != nil {
+			fmt.Println("Running benchmark run:", err)
+			os.Exit(1)
+		}
 	default:
 		fmt.Println("Unknown argument: ", os.Args[1])
 	}
diff --git a/xenworker.go b/xenworker.go
index 6023c50..1ed5cf0 100644
--- a/xenworker.go
+++ b/xenworker.go
@@ -105,7 +105,7 @@ func (w *XenWorker) Init(p WorkerParams) (err error) {
 			return
 		}
 
-		fmt.Printf(" %s domid %d\n", w.vmname, w.domid)
+		//fmt.Printf(" %s domid %d\n", w.vmname, w.domid)
 	}
 	
 	// Set xenstore config
@@ -133,7 +133,7 @@ func (w *XenWorker) Init(p WorkerParams) (err error) {
 		//fmt.Printf("json:\n%s\n", string(rcfgBytes))
 		rcfgPath := fmt.Sprintf("/local/domain/%d/rumprun/cfg", w.domid)
 
-		fmt.Printf("Writing to %s, json config %s\n", rcfgPath, rcfgBytes)
+		//fmt.Printf("Writing to %s, json config %s\n", rcfgPath, rcfgBytes)
 		
 		args := []string{"xenstore-write", rcfgPath, string(rcfgBytes)}
 		if mock {
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  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 ` [PATCH RFC 11/59] Refactor to move towards benchmark "plans" and data analysis Ronald Rojas
2016-12-29  1:14 ` Ronald Rojas [this message]
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-12-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).