diff --git a/trainbenchmark/trainbenchmark-reporting/build.gradle b/trainbenchmark/trainbenchmark-reporting/build.gradle index 7fc02588564bd4cedce73c2ecfc52d06fb27f0e3..f9eceadfaa6d52807c57a40fb9269ef2514db295 100644 --- a/trainbenchmark/trainbenchmark-reporting/build.gradle +++ b/trainbenchmark/trainbenchmark-reporting/build.gradle @@ -7,7 +7,7 @@ task doMerge(type: Exec) { task plot(type: Exec) { group = 'Benchmark' description = 'Plots the \'classic\' TrainBenchmark result' - commandLine 'Rscript', 'report.R' + commandLine 'Rscript', 'combined.R' dependsOn doMerge } diff --git a/trainbenchmark/trainbenchmark-reporting/combined.R b/trainbenchmark/trainbenchmark-reporting/combined.R new file mode 100644 index 0000000000000000000000000000000000000000..bd8fceaec1d3d46fc07e7693c5c3a43b332cad9a --- /dev/null +++ b/trainbenchmark/trainbenchmark-reporting/combined.R @@ -0,0 +1,167 @@ +library(data.table) +library(reshape2) +library(plyr) +library(ggplot2) +library(ggrepel) +library(arules) +library(ggforce) +library(extrafont) + +loadfonts(device="postscript") +loadfonts(quiet=TRUE) + +source('util.R') + +# constants +phases = c("Read", "Check", "Read.and.Check", "Transformation", "Recheck", "Transformation.and.Recheck") +phasesPrettified = c("Read", "Check", "Read and Check", "Transformation", "Recheck", "Transformation and Recheck") + +sizes = list() # 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 +sizes[["Repair"]] = c("8k", "15k", "33k", "66k", "135k", "271k", "566k", "1.1M", "2.2M", "4.6M", "9.3M", "18M", "37M") + +toolList = read.csv("tool-list.csv") + +dir.create("../diagrams/recent") +dir.create("../diagrams/recent/benchmark") +for (scenario in c("inject", "repair")) { + dir.create(file.path("../diagrams/recent/benchmark", scenario)) + + # load the data + tsvs = list.files(paste("../results/merged/benchmark", sep="/"), pattern = paste("times-.*", scenario, ".*\\.csv", sep=""), full.names = T, recursive = T) + + print("TESTTEST") + + l = lapply(tsvs, read.csv) + times = rbindlist(l) + + # preprocess the data + times$Tool = factor(times$Tool, levels = toolList$Tool) + keep_descriptions_first_char(times) + + times$Model = gsub("\\D+", "", times$Model) + times$Model = as.numeric(times$Model) + times$Time = times$Time / 10^6 + # make the phases a factor with a fixed set of values to help dcasting + # (e.g. Batch measurements do not have Transformation and Recheck attributes, + # hence accessing the "Transformation" attribute would throw an error) + times$Phase = factor(times$Phase, levels = c("Read", "Check", "Transformation", "Recheck")) + + times.wide = dcast(data = times, + formula = Tool + Workload + Description + Model + Run ~ Phase, + value.var = "Time", + drop = T, + fun.aggregate = mean + ) + + # calculate aggregated values + times.derived = times.wide + times.derived$Read.and.Check = times.derived$Read + times.derived$Check + times.derived$Transformation.and.Recheck = times.derived$Transformation + times.derived$Recheck + + # calculate the median value of runs + times.aggregated.runs = ddply( + .data = times.derived, + .variables = c("Tool", "Workload", "Description", "Model"), + .fun = colwise(median), + .progress = "text" + ) + # drop the "Run" column + times.aggregated.runs = subset(times.aggregated.runs, select = -c(Run)) + + times.processed = melt( + data = times.aggregated.runs, + id.vars = c("Tool", "Workload", "Description", "Model"), + measure.vars = phases, + variable.name = "Phase", + value.name = "Time" + ) + + # beautify plotted record: + # 1. change dots to spaces + # 2. make sure that the phases are still factors + times.plot = times.processed + times.plot$Phase = gsub('\\.', ' ', times.plot$Phase) + times.plot$Phase = factor(times.plot$Phase, levels = phasesPrettified) + # times.plot$Workload = factor(times.plot$Workload, levels = workloads) + + ### line charts + for (phase in phasesPrettified) { + phase.filename = gsub(' ', '-', phase) + workloadSizes = sizes[["Repair"]] + + # filter the dataframe to the current phase + df = times.plot[times.plot$Phase == phase, ] + + # do not visualize empty data sets + if (nrow(df) == 0) { + print(paste("No rows to visualize for phase", phase)) + next + } + + # x axis labels + xbreaks = unique(df$Model) + currentWorkloadSizes = head(workloadSizes, n=length(xbreaks)) + xlabels = paste(xbreaks, "\n", currentWorkloadSizes, sep = "") + + # drop every other models size + maxLabel = max(log2(max(df$Model)), 2) + if (maxLabel %% 2) { + start = 3 + } else { + start = 2 + } + filter = seq(start, maxLabel, by=2) + + xlabels[filter] = "" + + # y axis labels + yaxis = nice_y_axis() + ybreaks = yaxis$ybreaks + yminor_breaks = yaxis$yminor_breaks + ylabels = yaxis$ylabels + + p = ggplot(df) + #na.omit(df)) + + aes(x = as.factor(Model), y = Time) + + labs(title = paste("Individual query execution time,", phase, "phase"), x = "Model size\n#Elements", y = "Execution times [ms]") + + geom_point(aes(col = Tool, shape = Tool), size = 2.0) + + scale_shape_manual(values = c(1,16, 0,15, 2,17, 5,18, 8,10)) + + # scale_shape_manual(values = c(1,21, 0,22, 2,24, 5,23, 6,25)) + + scale_colour_manual(values = c( "#56B4E9", "#56B4E9", # Sky blue - Name Lookup + "#009E73", "#009E73", # Bluish green - Intrinsic References + "#0072B2", "#0072B2", # Blue - Manual Serialization + "#E69F00", "#E69F00", # Orange - RelAST + "#D55E00", # Vermillion - Tinkergraph + "#CC79A7", # ReddishPurple - VIATRA + "#F0E442" # Yellow + ) + ) + + geom_line(aes(col = Tool, group = Tool), size = 0.5) + + # scale_linetype_manual(values=c(0,1,2,3,4,5,6,7,8,9), na.value="blank") + + scale_x_discrete(breaks = xbreaks, labels = xlabels) + + scale_y_log10(breaks = ybreaks, minor_breaks=yminor_breaks, labels = ylabels, limits = c(2e-3,8e4), expand = c(0, 0)) + + guides(color = guide_legend(ncol = 5)) + + theme_bw() + + theme( + plot.title = element_blank(), # element_text(hjust = 0.5), + # text = element_text(family="Open Sans", size = 10), + # legend.key = element_blank(), + legend.title = element_blank(), + strip.text.x = element_blank(), + legend.position = "bottom", # "none", # + axis.text = element_text(size = 16) + #, panel.grid.minor = element_blank() + ) + fnTmp <- paste("../diagrams/recent/benchmark/", scenario, "/", phase.filename, "-", scenario, "-tmp.pdf", sep="") + fn <- paste("../diagrams/recent/benchmark/", scenario, "/", phase.filename, "-", scenario, ".pdf", sep="") + ggsave( + plot = p, + filename = fnTmp, + width = 250, + height = 150, + units = "mm" + ) + embed_fonts(fnTmp, outfile=fn) + file.remove(fnTmp) + + } +} diff --git a/trainbenchmark/trainbenchmark-reporting/individual.R b/trainbenchmark/trainbenchmark-reporting/individual.R index bdd70e34084e80b7b43860bed746d137e624ab73..3897760c9e48e8f80f089b5f19bff6068c99fe08 100644 --- a/trainbenchmark/trainbenchmark-reporting/individual.R +++ b/trainbenchmark/trainbenchmark-reporting/individual.R @@ -130,56 +130,45 @@ for (scenario in c("inject", "repair")) { aes(x = as.factor(Model), y = Time) + labs(title = paste("Individual query execution time,", phase, "phase"), x = "Model size\n#Elements", y = "Execution times [ms]") + geom_point(aes(col = Tool, shape = Tool), size = 2.0) + - # scale_shape_manual(values = seq(0, 15)) + - # scale_shape_manual(#values = c(0, 15, 1, 16, 2, 17, 4, 7), - # # labels=c( - # # "Name Lookup ", "Name Lookup (Incremental)", # http://www.sthda.com/english/wiki/r-plot-pch-symbols-the-different-point-shapes-available-in-r - JastAdd NameLookup - # # "Intrinsic References", "Intrinsic References (Incremental)", # Tud-cyan - JastAdd Optimized - # # "Grammar Extension", "Grammar Extension (Incremental)", # HKS65 (green) - JastAdd Specialized - # # "TinkerGraph", # HKS92 (grey) - TinkerGraph - # # "Viatra (Incremental)", # HKS33 (violet) - VIATRA - # # "(none)" - # # ) - # ) + - # scale_colour_manual( - # values = c( - # "#EE7F00", "#EE7F00", # HKS07 (orange) - JastAdd NameLookup - # "#009EE0", "#009EE0", # Tud-cyan - JastAdd Optimized - # "#6AB023", "#6AB023", # HKS65 (green) - JastAdd Specialized - # "#727879", # HKS92 (grey) - TinkerGraph - # "#93107E", # HKS33 (violet) - VIATRA - # "#F0E442", # Yellow - # "#CC79A7"), - # labels=c( - # "Name Lookup ", "Name Lookup (Incremental)", # HKS07 (orange) - JastAdd NameLookup - # "Intrinsic References", "Intrinsic References (Incremental)", # Tud-cyan - JastAdd Optimized - # "Grammar Extension", "Grammar Extension (Incremental)", # HKS65 (green) - JastAdd Specialized - # "TinkerGraph", # HKS92 (grey) - TinkerGraph - # "Viatra (Incremental)", # HKS33 (violet) - VIATRA - # "(none)" - # )) + + scale_shape_manual(values = c(1,16, 0,15, 2,17, 5,18, 8,10)) + + # scale_shape_manual(values = c(1,21, 0,22, 2,24, 5,23, 6,25)) + + scale_colour_manual(values = c( "#56B4E9", "#56B4E9", # Sky blue - Name Lookup + "#009E73", "#009E73", # Bluish green - Intrinsic References + "#0072B2", "#0072B2", # Blue - Manual Serialization + "#E69F00", "#E69F00", # Orange - RelAST + "#D55E00", # Vermillion - Tinkergraph + "#CC79A7", # ReddishPurple - VIATRA + "#F0E442" # Yellow + ) + ) + geom_line(aes(col = Tool, group = Tool), size = 0.5) + + # scale_linetype_manual(values=c(0,1,2,3,4,5,6,7,8,9), na.value="blank") + scale_x_discrete(breaks = xbreaks, labels = xlabels) + scale_y_log10(breaks = ybreaks, minor_breaks=yminor_breaks, labels = ylabels, limits = c(2e-3,8e4), expand = c(0, 0)) + facet_grid_paginate(~ Workload, nrow=1, ncol = 1, page=cpage, scale = "free") + guides(color = guide_legend(ncol = 5)) + theme_bw() + theme( - plot.title = element_text(hjust = 0.5), + plot.title = element_blank(), # element_text(hjust = 0.5), # text = element_text(family="Open Sans", size = 10), # legend.key = element_blank(), legend.title = element_blank(), - legend.position = "bottom", + strip.text.x = element_blank(), + legend.position = "bottom", # "none", # axis.text = element_text(size = 16) - #, panel.grid.minor = element_blank() + #, panel.grid.minor = element_blank() ) - print(p) + fnTmp <- paste("../diagrams/recent/", scenario, "/", phase.filename, "-", workloads[cpage], "-", scenario, "-tmp.pdf", sep="") + fn <- paste("../diagrams/recent/", scenario, "/", phase.filename, "-", workloads[cpage], "-", scenario, ".pdf", sep="") ggsave( plot = p, - filename = paste("../diagrams/recent/", scenario, "/", phase.filename, "-", workloads[cpage], "-", scenario, ".pdf", sep=""), - width = 500, height = 300, units = "mm" + filename = fnTmp, + width = 250, + height = 150, + units = "mm" ) - embed_fonts(paste("../diagrams/recent/", scenario, "/", phase.filename, "-", workloads[cpage], "-", scenario, ".pdf", sep=""), outfile=paste("../diagrams/recent/", scenario, "/", phase.filename, "-",workloads[cpage], "-", scenario, "-embed", ".pdf", sep="")) + embed_fonts(fnTmp, outfile=fn) + file.remove(fnTmp) } } diff --git a/trainbenchmark/trainbenchmark-reporting/merge_results.py b/trainbenchmark/trainbenchmark-reporting/merge_results.py index dfe5e7344a565ec570f5c52532d17a11a8a1bcd6..e321720e7e056b0938e8638b783614122ee8b165 100755 --- a/trainbenchmark/trainbenchmark-reporting/merge_results.py +++ b/trainbenchmark/trainbenchmark-reporting/merge_results.py @@ -10,7 +10,7 @@ import sys FORMAT = '%(asctime)s %(levelname)-8s %(threadName)-10s (%(filename)s:%(lineno)d): %(message)s' -BENCHMARK_PATTERN = re.compile('.*-(BatchModel|Repair|Inject)Test.*') +BENCHMARK_PATTERN = re.compile('.*-(BatchModel|Repair|Inject).*') logger = logging.getLogger('merge_result') SIZE_PATTERN = re.compile('.*-railway-[^\\-]*-([^\\-]*)-.csv') NAME_PATTERN = re.compile('(times|matches)-([^\\-]*)-.*.csv') diff --git a/trainbenchmark/trainbenchmark-reporting/report.R b/trainbenchmark/trainbenchmark-reporting/report.R deleted file mode 100644 index 96c9833d00c34cfd5702c449b57aece61ce1bf9c..0000000000000000000000000000000000000000 --- a/trainbenchmark/trainbenchmark-reporting/report.R +++ /dev/null @@ -1,231 +0,0 @@ -library(data.table) -library(reshape2) -library(plyr) -library(ggplot2) -library(ggrepel) -library(arules) - -source('util.R') - -# constants -workloads = c("Inject", "Repair") -phases = c("Read", "Check", "Read.and.Check", "Transformation", "Recheck", "Transformation.and.Recheck") - -sizes = list() # 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 -sizes[["Inject"]] = c("5k", "19k", "31k", "67k", "138k", "283k", "573k", "1.2M", "2.3M", "4.6M", "9.2M", "18M", "37M") -sizes[["Repair"]] = c("8k", "15k", "33k", "66k", "135k", "271k", "566k", "1.1M", "2.2M", "4.6M", "9.3M", "18M", "37M") - -toolList = read.csv("tool-list.csv", colClasses=c(rep("character",1))) - -# load the data -tsvs = list.files("../results/recent", pattern = "times-.*\\.csv", full.names = T, recursive = T) -l = lapply(tsvs, read.csv) -times = rbindlist(l) - -# preprocess the data -times$Tool = factor(times$Tool, levels = toolList$Tool) -keep_descriptions_first_char(times) - -times$Model = gsub("\\D+", "", times$Model) -times$Model = as.numeric(times$Model) -times$Time = times$Time / 10^6 -# make the phases a factor with a fixed set of values to help dcasting -# (e.g. Batch measurements do not have Transformation and Recheck attributes, -# hence accessing the "Transformation" attribute would throw an error) -times$Phase = factor(times$Phase, levels = c("Read", "Check", "Transformation", "Recheck")) - -if (nrow(times[times$Phase == "Transformation"]) == 0) { - stop("There are no records on the 'Transformation' phase in the dataset. Cannot generate report.") -} - -times.wide = dcast(data = times, - formula = Tool + Workload + Description + Model + Run ~ Phase, - value.var = "Time", - drop = T, - fun.aggregate = mean -) - -# calculate aggregated values -times.derived = times.wide -times.derived$Read.and.Check = times.derived$Read + times.derived$Check -times.derived$Transformation.and.Recheck = times.derived$Transformation + times.derived$Recheck - -# calculate the median value of runs -times.aggregated.runs = ddply( - .data = times.derived, - .variables = c("Tool", "Workload", "Description", "Model"), - .fun = colwise(median), - .progress = "text" -) -# drop the "Run" column -times.aggregated.runs = subset(times.aggregated.runs, select = -c(Run)) - -times.processed = melt( - data = times.aggregated.runs, - id.vars = c("Tool", "Workload", "Description", "Model"), - measure.vars = phases, - variable.name = "Phase", - value.name = "Time" -) - -# beautify plotted record: -# 1. change dots to spaces -# 2. make sure that the phases are still factors -times.plot = times.processed -times.plot$Phase = gsub('\\.', ' ', times.plot$Phase) -times.plot$Phase = factor(times.plot$Phase, levels = c("Read", "Check", "Read and Check", "Transformation", "Recheck", "Transformation and Recheck")) - -### line charts -for (workload in workloads) { - workloadSizes = sizes[[workload]] - - # filter the dataframe to the current workload - df = times.plot[times.plot$Workload == workload, ] - - # do not visualize empty data sets - if (nrow(df) == 0) { - print(paste("No rows to visualize for workload", workload)) - next - } - - # x axis labels - xbreaks = unique(df$Model) - currentWorkloadSizes = head(workloadSizes, n=length(xbreaks)) - xlabels = paste(xbreaks, "\n", currentWorkloadSizes, sep = "") - - # drop every other models size - evens = seq(2, log2(max(df$Model)), by=2) - xlabels[evens] = "" - - # y axis labels - yaxis = nice_y_axis() - ybreaks = yaxis$ybreaks - ylabels = yaxis$ylabels - - # another ugly hack - for both facet sets: - # - upper (Read, Check, Read and Check), - # - lower (Transformation, Recheck, Transformation and Recheck), - # we calculate minimum and maximum values - - validation.facets = c("Read", "Check", "Read and Check") - read.and.check.extremes = get_extremes(df, validation.facets) - read.and.check.extremes = create_extremes_for_facets(read.and.check.extremes, validation.facets) - - revalidation.facets = c("Transformation", "Recheck", "Transformation and Recheck") - transformation.and.recheck.extremes = get_extremes(df, revalidation.facets) - transformation.and.recheck.extremes = create_extremes_for_facets(transformation.and.recheck.extremes, revalidation.facets) - - extremes = NULL - extremes = rbind(extremes, read.and.check.extremes) - extremes = rbind(extremes, transformation.and.recheck.extremes) - - p = ggplot(df) + #na.omit(df)) + - aes(x = as.factor(Model), y = Time) + - labs(title = paste(workload, "scenario, execution time"), x = "Model size\n#Elements", y = "Execution times [ms]") + - geom_point(aes(col = Tool, shape = Tool), size = 2.0) + - geom_point(data = extremes, color = "transparent") + # add extremes for minimum and maximum values - scale_shape_manual(values = seq(0, 15)) + - geom_line(aes(col = Tool, group = Tool), size = 0.5) + - scale_x_discrete(breaks = xbreaks, labels = xlabels) + - scale_y_log10(breaks = ybreaks, labels = ylabels) + - facet_wrap(~ Phase, ncol = 3, scale = "free") + - guides(color = guide_legend(ncol = 4)) + - theme_bw() + - theme( - plot.title = element_text(hjust = 0.5), - text = element_text(size = 10), - legend.key = element_blank(), - legend.title = element_blank(), - legend.position = "bottom", - axis.text = element_text(size = 9) - ) - print(p) - - ggsave( - plot = p, - filename = paste("../diagrams/times-", workload, ".pdf", sep=""), - width = 210, height = 297, units = "mm" - ) -} - -### heatmaps - -heatmap = function(df, attributes, map.from = NULL, map.to = NULL, levels, title, filename, width = 210, height = 100, ncol = 3, legend.position = "bottom") { - df$Model = discretize( - df$Model, - "fixed", - categories = c(-Inf, 16, 256, Inf), - labels = c("small", "medium", "large")) - - df$Time = discretize( - df$Time, - "fixed", - categories = c(-Inf, 200, 1000, 5000, Inf), - labels = c("instantaneous", "fast", "acceptable", "slow")) - - if (!is.null(map.from)) { - attribute = attributes[1]; - df[[attribute]] = mapvalues(df[[attribute]], from = map.from, to = map.to, warn_missing = FALSE) - } - df[[attributes]] = factor(df[[attributes]], levels = levels) - - frequencies = as.data.frame(table(df[, c("Model", "Time", attributes)])) - total.frequencies = ddply(frequencies, attributes, summarize, Total = sum(Freq)) - frequencies = merge(frequencies, total.frequencies) - frequencies$Freq = frequencies$Freq / frequencies$Total - - p = ggplot(na.omit(frequencies)) + - labs(title = title, x = "Model size", y = "Execution time") + - geom_tile(aes(x = Model, y = Time, fill = Freq)) + - scale_fill_gradient(low = "white", high = "darkred") - - if (length(attributes) == 1) { - p = p + facet_wrap(as.formula(paste("~" ,attributes[1])), ncol = ncol) - } else { - p = p + facet_grid(as.formula(paste(attributes[1], "~" ,attributes[2]))) - } - - p = p + - theme_bw() + - theme( - plot.title = element_text(hjust = 0.5), - legend.key = element_blank(), - legend.title = element_blank(), - legend.position = legend.position, - axis.text.x = element_text(angle = 90, hjust = 1), - strip.text.x = element_text(size = 7), - strip.text.y = element_text(size = 7) - ) - print(p) - - ggsave(file = paste("../diagrams/heatmap-", filename, ".pdf", sep = ""), width = width, height = height, units = "mm") -} - -times.plot.read.and.check.only = subset(times.plot, Phase == "Read and Check") - -tools = read.csv("tools.csv", colClasses=c(rep("character",3))) - -# storage / read and check time -heatmap(df = times.plot.read.and.check.only, - attributes = c("Tool"), - map.from = tools$tool, - map.to = tools$storage, - levels = c("in-memory", "disk-resident"), - title = "Comparison of performance by storage\n(read and check)", - filename = "storage", - height = 74, - width = 106, - ncol = 2, - legend.position = "right") - -heatmap(df = times.plot, - attributes = c("Tool"), - map.from = tools$tool, - map.to = tools$format, - levels = c("EMF", "property graph", "RDF", "SQL"), - title = "Comparison of performance by formats\n(total execution time)", - filename = "formats", - height = 115, - width = 108, - ncol = 2, - legend.position = "right")