#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import sys import os import tempfile import subprocess import re (COLUMN_HEAP, COLUMN_DIRECT, COLUMN_CONNECTIONS, COLUMN_SESSIONS, COLUMN_PRODUCERS, COLUMN_TRANSACTED, COLUMN_MESSAGES, COLUMN_MESSAGE_SIZE, COLUMN_DELIVERY_MODE, COLUMN_HUMAN_READABLE_HEAP, COLUMN_HUMAN_READABLE_DIRECT) = range(11) TEMPLATE = """ set datafile separator "," set terminal png set output "{outputFile}" byte_buffer_size=256*1024 heap(messages, connections, sessions)=15*1024*1024 + 15*1024*sessions*connections + 1024*messages + 17*1024*connections direct(messages, messageSize, connections, sessions)=2*1024*1024 + (200+messageSize*2)*messages + 2*byte_buffer_size*connections set title "{title}" set key top left set log xy set xlabel "{xlabel}" set ylabel "Memory Usage in MBytes" plot {plotCmdArgs} """ def main(): if len(sys.argv) != 2: printUsage() sys.exit(1) filename = sys.argv[1] if not os.path.exists(filename): print "file " + filename + " doesn't exist" protocol, jvm, data = parseCSV(filename) print protocol, jvm print("creating plots for datafile '%s'" % filename) plotForProtocol(data, protocol, jvm, TEMPLATE) def printUsage(): print "Usage: {scriptName} RESULT_FILE".format(scriptName = sys.argv[0]) def parseCSV(filename): rows = [] protocolVersion = None javaVersion = None with open(filename) as f: lastLine = None for line in f: if line.startswith("#"): # parse header for amqp and java version if protocolVersion == None or javaVersion == None: protocolMatch = re.search("amqp=(\d-\d+(?:-\d+)?)", line) protocolVersion = protocolMatch.group(1) if protocolMatch else None javaMatch = re.search("java=(1\.\d)", line) javaVersion = javaMatch.group(1) if javaMatch else None # if not header a comment line indicates an execption of the previous execution so delete that result if rows and not lastLine.startswith("#"): rows = rows[:-1] lastLine = line continue columns = line.strip().split(",") rows.append(columns) lastLine = line return (protocolVersion, javaVersion, rows) def plotForProtocol(data, protocol, jvm, template): print(" creating plots for " + protocol) print(" creating by_messages plots...") for messageSize in (0, 1024, 102400, 10485760, 32768000): plotCmdArgs = ('datafile using 7:($1/1024/1024) title "Heap Memory",' '(heap(x,1,1)/1024/1024) title "heap formula" linecolor rgb "red",' 'datafile using 7:($2/1024/1024) title "Direct Memory" linecolor rgb "blue",' '(direct(x,%s,1,1)/1024/1024) title "direct formual" linecolor rgb "blue"' % messageSize) plotScript = template.format(title="Memory Usage by Number of Messages\\n(AMQP=%s; messageSize=%s)" % (protocol, messageSize), xlabel="Number of Messages", outputFile="memUsage_by_messages_%s_msgSize=%s.png" % (protocol, messageSize), plotCmdArgs=plotCmdArgs) plotDataPredicate = lambda line: (line[COLUMN_CONNECTIONS]=="1" and line[COLUMN_SESSIONS]=="1" and line[COLUMN_PRODUCERS]=="1" and line[COLUMN_MESSAGE_SIZE]=="%s" % messageSize) plotByPredicate(plotScript, data, plotDataPredicate) print(" creating by_msgSize plots...") for messages in (10, 50, 100, 1000, 10000, 100000): plotCmdArgs = ('datafile using 8:($1/1024/1024) title "Heap Memory",' '(heap(%s,1,1)/1024/1024) title "heap formula" linecolor rgb "red",' 'datafile using 8:($2/1024/1024) title "Direct Memory" linecolor rgb "blue",' '(direct(%s,x,1,1)/1024/1024) title "direct formual" linecolor rgb "blue"' % (messages, messages)) plotScript = template.format(title="Memory Usage by MessageSize\\n(AMQP=%s; messages=%s)" % (protocol, messages), xlabel="Message Size", outputFile="memUsage_by_msgSize_%s_msgNum=%s.png" % (protocol, messages), plotCmdArgs=plotCmdArgs) plotDataPredicate = lambda line: (line[COLUMN_CONNECTIONS]=="1" and line[COLUMN_SESSIONS]=="1" and line[COLUMN_PRODUCERS]=="1" and line[COLUMN_MESSAGES]=="%s" % messages) plotByPredicate(plotScript, data, plotDataPredicate) print(" creating by_connections plots...") for sessions in (10, 100, 200): plotCmdArgs = ('datafile using 3:($1/1024/1024) title "Heap Memory",' '(heap(2,x,%s)/1024/1024) title "heap formula" linecolor rgb "red",' 'datafile using 3:($2/1024/1024) title "Direct Memory" linecolor rgb "blue",' '(direct(2,0,x,%s)/1024/1024) title "direct formual" linecolor rgb "blue"' % (sessions, sessions)) plotScript = template.format(title="Memory Usage by Connections\\n(AMQP=%s; sessions=%s)" % (protocol, sessions), xlabel="Number of Connections", outputFile="memUsage_by_connections_%s_sessions=%s.png" % (protocol, sessions), plotCmdArgs=plotCmdArgs) plotDataPredicate = lambda line: (line[COLUMN_SESSIONS]=="%s" % sessions and line[COLUMN_PRODUCERS]=="1" and line[COLUMN_MESSAGES]=="2" and line[COLUMN_MESSAGE_SIZE]=="0") plotByPredicate(plotScript, data, plotDataPredicate) print(" creating by_sessions plots...") for connections in (1, 100, 1000): plotCmdArgs = ('datafile using 4:($1/1024/1024) title "Heap Memory",' '(heap(2,%s,x)/1024/1024) title "heap formula" linecolor rgb "red",' 'datafile using 4:($2/1024/1024) title "Direct Memory" linecolor rgb "blue",' '(direct(2,0,%s,x)/1024/1024) title "direct formual" linecolor rgb "blue"' % (connections,connections)) plotScript = template.format(title="Memory Usage by Sessions per Connection\\n(AMQP=%s; connections=%s)" % (protocol, connections), xlabel="Number of Sessions per Connection", outputFile="memUsage_by_sessions_%s_connections=%s.png" % (protocol, connections), plotCmdArgs=plotCmdArgs) plotDataPredicate = lambda line: (line[COLUMN_CONNECTIONS]=="%s" % connections and line[COLUMN_PRODUCERS]=="1" and line[COLUMN_MESSAGES]=="2" and line[COLUMN_MESSAGE_SIZE]=="0") plotByPredicate(plotScript, data, plotDataPredicate) def plotByPredicate(plotScript, data, predicate): filteredData = [] for line in data: if predicate(line): filteredData.append(line) plot(plotScript, filteredData) def plot(plotScript, data): plotFile = tempfile.NamedTemporaryFile(mode="w") plotFile.write(plotScript) plotFile.flush() tmpDataFile = tempfile.NamedTemporaryFile(mode="w") for line in data: tmpDataFile.write(",".join(line) + "\n") tmpDataFile.flush() subprocess.call(["gnuplot", "-e", "datafile=\"%s\"" % tmpDataFile.name, plotFile.name], stdout=sys.stdout, stderr=sys.stderr) if __name__ == '__main__': main()