Merge pull request #17230 from MrStonedOne/runtimeCondenserFix

Refactor the Runtime Condenser to be less shit.
This commit is contained in:
Cheridan
2016-04-30 05:33:58 -05:00
3 changed files with 198 additions and 394 deletions
+198 -307
View File
@@ -1,4 +1,5 @@
/* Runtime Condenser by Nodrak
* Cleaned up and refactored by MrStonedOne
* This will sum up identical runtimes into one, giving a total of how many times it occured. The first occurance
* of the runtime will log the proc, source, usr and src, the rest will just add to the total. Infinite loops will
* also be caught and displayed (if any) above the list of runtimes.
@@ -7,238 +8,230 @@
* 1) Copy and paste your list of runtimes from Dream Daemon into input.exe
* 2) Run RuntimeCondenser.exe
* 3) Open output.txt for a condensed report of the runtimes
*
* How to compile:
* Requires visual c++ compiler 2012 or any linux compiler with c++11 support.
* Windows:
* Normal: cl.exe /EHsc /Ox /Qpar Main.cpp
* Debug: cl.exe /EHsc /Zi Main.cpp
* Linux:
* Normal: g++ -O3 -std=c++11 Main.cpp -o rc
* Debug: g++ -g -Og -std=c++11 Main.cpp -o rc
* Any Compile errors most likely indicate lack of c++11 support. Google how to upgrade or nag coderbus for help..
*/
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
//Make all of these global. It's bad yes, but it's a small program so it really doesn't affect anything.
//Because hardcoded numbers are bad :(
const unsigned short maxStorage = 99; //100 - 1
struct runtime {
string text;
string proc;
string source;
string usr;
string src;
string loc;
unsigned int count;
};
struct harddel {
string type;
unsigned int count;
};
//What we use to read input
string lastLine = "";
string currentLine = "";
string nextLine = "";
//What we use to read input
string currentLine = "Blank";
string nextLine = "Blank";
//Stores lines we want to keep to print out
unordered_map<string,runtime*> storedRuntime;
unordered_map<string,runtime*> storedInfiniteLoop;
unordered_map<string,harddel*> storedHardDel;
//Stores lines we want to keep to print out
string storedRuntime[maxStorage+1];
string storedProc[maxStorage+1];
string storedSource[maxStorage+1];
string storedUsr[maxStorage+1];
string storedSrc[maxStorage+1];
string storedHardDel[maxStorage+1];
//Stat tracking stuff for output
unsigned int totalRuntimes = 0;
unsigned int totalUniqueRuntimes = 0;
unsigned int totalInfiniteLoops = 0;
unsigned int totalUniqueInfiniteLoops = 0;
unsigned int totalHardDels = 0;
unsigned int totalUniqueHardDels = 0;
//Stat tracking stuff for output
unsigned int totalRuntimes = 0;
unsigned int totalUniqueRuntimes = 0;
unsigned int totalInfiniteLoops = 0;
unsigned int totalUniqueInfiniteLoops = 0;
unsigned int totalHardDels = 0;
unsigned int totalUniqueHardDels = 0;
//Misc
runtime* currentRuntime = NULL; //for storing the current runtime when we want to read the extra info on the next lines.
//Misc
unsigned int numRuntime[maxStorage+1]; //Number of times a specific runtime has occured
unsigned int numHardDel[maxStorage+1]; //Number of times a specific hard del has occured
bool checkNextLines = false; //Used in case byond has condensed a large number of similar runtimes
int storedIterator = 0; //Used to remember where we stored the runtime
bool readFromFile()
{
//like substr, but returns an empty string if the string is smaller then start, rather then an exception.
inline string safe_substr(string S, size_t start = 0, size_t end = string::npos) {
if (start > S.length())
start = S.length();
return S.substr(start, end);
}
inline void forward_progress(ifstream &inputFile) {
lastLine = currentLine;
currentLine = nextLine;
getline(inputFile, nextLine);
//strip out any timestamps.
if (nextLine.length() >= 10)
if (nextLine[0] == '[' && nextLine[3] == ':' && nextLine[6] == ':' && nextLine[9] == ']')
nextLine = nextLine.substr(10);
}
bool readFromFile() {
//Open file to read
ifstream inputFile("input.txt");
if(inputFile.is_open())
{
while(!inputFile.eof()) //Until end of file
{
//If we've run out of storage
if(storedRuntime[maxStorage] != "Blank") break;
ifstream inputFile("Input.txt");
if (inputFile.is_open()) {
while (!inputFile.eof()) { //Until end of file
//Update our lines
currentLine = nextLine;
getline(inputFile, nextLine);
forward_progress(inputFile);
//After finding a new runtime, check to see if there are extra values to store
if(checkNextLines)
{
if (currentRuntime) {
//Skip ahead
currentLine = nextLine;
getline(inputFile, nextLine);
forward_progress(inputFile);
//If we find this, we have new stuff to store
if(nextLine.find("usr:") != std::string::npos)
{
if (safe_substr(nextLine, 2, 4) == "usr:") {
//Skip ahead
forward_progress(inputFile);
//Store more info
storedSource[storedIterator] = currentLine;
storedUsr[storedIterator] = nextLine;
currentRuntime->source = lastLine;
currentRuntime->usr = currentLine;
currentRuntime->src = nextLine;
//Skip ahead again
currentLine = nextLine;
getline(inputFile, nextLine);
forward_progress(inputFile);
//Store the last of the info
storedSrc[storedIterator] = nextLine;
if (safe_substr(nextLine, 2, 8) == "src.loc:")
currentRuntime->loc = nextLine;
}
checkNextLines = false;
currentRuntime = NULL;
}
//Found an infinite loop!
if(currentLine.find("Infinite loop suspected") != std::string::npos || currentLine.find("Maximum recursion level reached") != std::string::npos)
{
if (safe_substr(currentLine, 0, 23) == "Infinite loop suspected" || safe_substr(currentLine, 0, 31) == "Maximum recursion level reached") {
totalInfiniteLoops++;
for(int i=0; i <= maxStorage; i++)
{
//We've already encountered this
if(currentLine == storedRuntime[i])
{
numRuntime[i]++;
break;
}
//We've never encountered this
if(storedRuntime[i] == "Blank")
{
storedRuntime[i] = currentLine;
currentLine = nextLine;
getline(inputFile, nextLine); //Skip the "if this is not an infinite loop" line
storedProc[i] = nextLine;
numRuntime[i] = 1;
checkNextLines = true;
storedIterator = i;
totalUniqueInfiniteLoops++;
break;
}
runtime* R = storedInfiniteLoop[currentLine];
if (!R || R->text != currentLine) {
R = new runtime;
storedInfiniteLoop[currentLine] = R;
R->text = currentLine;
forward_progress(inputFile);
R->proc = nextLine;
R->count = 1;
currentRuntime = R;
totalUniqueInfiniteLoops++;
} else { //existed already
R->count++;
}
}
//Found a runtime!
else if(currentLine.find("runtime error:") != std::string::npos)
{
else if (safe_substr(currentLine, 0, 14) == "runtime error:") {
if (currentLine.length() <= 17) { //empty runtime, check next line.
if (nextLine.length() < 2) //runtime is on the line before this one. (byond bug)
nextLine = lastLine;
forward_progress(inputFile);
currentLine = "runtime error: " + currentLine;
}
totalRuntimes++;
for(int i=0; i <= maxStorage; i++)
{
//We've already encountered this
if(currentLine == storedRuntime[i])
{
numRuntime[i]++;
break;
}
//We've never encountered this
if(storedRuntime[i] == "Blank")
{
storedRuntime[i] = currentLine;
storedProc[i] = nextLine;
numRuntime[i] = 1;
checkNextLines = true;
storedIterator = i;
totalUniqueRuntimes++;
break;
}
runtime* R = storedRuntime[currentLine];
if (!R || R->text != currentLine) {
R = new runtime;
storedRuntime[currentLine] = R;
R->text = currentLine;
R->proc = nextLine;
R->count = 1;
currentRuntime = R;
totalUniqueRuntimes++;
} else { //existed already
R->count++;
}
}
//Found a hard del!
else if(currentLine.find("Path :") != std::string::npos)
{
//this is pretty ugly but the alternative was implementing regex which I haven't the slightest idea how to do
//it takes advantage of the formatting of the line to extract the amount of failures
std::string tmp;
char c;
int failures;
std::stringstream ss(nextLine);
ss >> tmp >> c >> failures;
else if (safe_substr(currentLine, 0, 7) == "Path : ") {
string deltype = safe_substr(currentLine, 7);
if (deltype.substr(deltype.size()-1,1) == " ") //some times they have a single trailing space.
deltype = deltype.substr(0, deltype.size()-1);
unsigned int failures = strtoul(safe_substr(nextLine, 11).c_str(), NULL, 10);
if (failures <= 0)
continue;
totalHardDels += failures;
for(int i=0; i <= maxStorage; i++)
{
//We've already encountered this
if(currentLine == storedHardDel[i])
{
numHardDel[i] += failures;
break;
}
//We've never encountered this
if(storedHardDel[i] == "Blank")
{
storedHardDel[i] = currentLine;
numHardDel[i] = failures;
checkNextLines = true;
totalUniqueHardDels++;
break;
}
harddel * D = storedHardDel[deltype];
if (!D || D->type != deltype) {
D = new harddel;
storedHardDel[deltype] = D;
D->type = deltype;
D->count = failures;
totalUniqueHardDels++;
} else {
D->count += failures;
}
}
}
}
else
{
} else {
return false;
}
return true;
}
bool runtimeComp(const runtime* a, const runtime* b) {
return a->count > b->count;
}
bool writeToFile()
{
bool hardDelComp(const harddel* a, const harddel* b) {
return a->count > b->count;
}
bool writeToFile() {
//Open and clear the file
ofstream outputFile("Output.txt", ios::trunc);
if(outputFile.is_open())
{
if(outputFile.is_open()) {
outputFile << "Note: The proc name, source file, src and usr are all from the FIRST of the identical runtimes. Everything else is cropped.\n\n";
if(totalUniqueInfiniteLoops > 0)
{
outputFile << "Total unique infinite loops: " << totalUniqueInfiniteLoops << endl;
}
if(totalInfiniteLoops > 0)
{
if(totalInfiniteLoops > 0)
outputFile << "Total infinite loops: " << totalInfiniteLoops << endl << endl;
}
outputFile << "Total unique runtimes: " << totalUniqueRuntimes << endl;
outputFile << "Total runtimes: " << totalRuntimes << endl << endl;
if(totalUniqueHardDels > 0)
{
outputFile << "Total unique hard deletions: " << totalUniqueHardDels << endl;
}
if(totalHardDels > 0)
{
outputFile << "Total hard deletions: " << totalHardDels << endl << endl;
}
//Display a warning if we've hit the maximum space we've allocated for storage
if(totalUniqueRuntimes + totalUniqueInfiniteLoops >= maxStorage)
{
outputFile << "Warning: The maximum number of unique runtimes has been hit. If there were more, they have been cropped out.\n\n";
}
if(totalUniqueHardDels >= maxStorage)
{
outputFile << "Warning: The maximum number of unique hard deletions has been hit. If there were more, they have been croped out.\n\n";
}
if(totalHardDels > 0)
outputFile << "Total hard deletions: " << totalHardDels << endl << endl;
//If we have infinite loops, display them first.
if(totalInfiniteLoops > 0)
{
if(totalInfiniteLoops > 0) {
vector<runtime*> infiniteLoops;
infiniteLoops.reserve(storedInfiniteLoop.size());
for (unordered_map<string,runtime*>::iterator it=storedInfiniteLoop.begin(); it != storedInfiniteLoop.end(); it++)
infiniteLoops.push_back(it->second);
sort(infiniteLoops.begin(), infiniteLoops.end(), runtimeComp);
outputFile << "** Infinite loops **";
for(int i=0; i <= maxStorage; i++)
{
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos)
{
if(numRuntime[i] != 0) outputFile << endl << endl << "The following infinite loop has occured " << numRuntime[i] << " time(s).\n";
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
}
for (int i=0; i < infiniteLoops.size(); i++) {
runtime* R = infiniteLoops[i];
outputFile << endl << endl << "The following infinite loop has occurred " << R->count << " time(s).\n";
outputFile << R->text << endl;
if(R->proc.length())
outputFile << R->proc << endl;
if(R->source.length())
outputFile << R->source << endl;
if(R->usr.length())
outputFile << R->usr << endl;
if(R->src.length())
outputFile << R->src << endl;
if(R->loc.length())
outputFile << R->loc << endl;
}
outputFile << endl << endl; //For spacing
}
@@ -246,170 +239,68 @@ bool writeToFile()
//Do runtimes next
outputFile << "** Runtimes **";
for(int i=0; i <= maxStorage; i++)
{
if(storedRuntime[i].find("Infinite loop suspected") != std::string::npos || storedRuntime[i].find("Maximum recursion level reached") != std::string::npos) continue;
if(numRuntime[i] != 0) outputFile << endl << endl << "The following runtime has occured " << numRuntime[i] << " time(s).\n";
if(storedRuntime[i] != "Blank") outputFile << storedRuntime[i] << endl;
if(storedProc[i] != "Blank") outputFile << storedProc[i] << endl;
if(storedSource[i] != "Blank") outputFile << storedSource[i] << endl;
if(storedUsr[i] != "Blank") outputFile << storedUsr[i] << endl;
if(storedSrc[i] != "Blank") outputFile << storedSrc[i] << endl;
vector<runtime*> runtimes;
runtimes.reserve(storedRuntime.size());
for (unordered_map<string,runtime*>::iterator it=storedRuntime.begin(); it != storedRuntime.end(); it++)
runtimes.push_back(it->second);
sort(runtimes.begin(), runtimes.end(), runtimeComp);
for (int i=0; i < runtimes.size(); i++) {
runtime* R = runtimes[i];
outputFile << endl << endl << "The following runtime has occurred " << R->count << " time(s).\n";
outputFile << R->text << endl;
if(R->proc.length())
outputFile << R->proc << endl;
if(R->source.length())
outputFile << R->source << endl;
if(R->usr.length())
outputFile << R->usr << endl;
if(R->src.length())
outputFile << R->src << endl;
if(R->loc.length())
outputFile << R->loc << endl;
}
outputFile << endl << endl; //For spacing
//and finally, hard deletes
if(totalHardDels > 0)
{
if(totalHardDels > 0) {
outputFile << endl << "** Hard deletions **";
for(int i=0; i <= maxStorage; i++)
{
if(numHardDel[i] != 0 && storedHardDel[i] != "Blank") outputFile << endl << storedHardDel[i] << " - " << numHardDel[i] << " time(s).\n";
vector<harddel*> hardDels;
hardDels.reserve(storedHardDel.size());
for (unordered_map<string,harddel*>::iterator it=storedHardDel.begin(); it != storedHardDel.end(); it++)
hardDels.push_back(it->second);
sort(hardDels.begin(), hardDels.end(), hardDelComp);
for(int i=0; i < hardDels.size(); i++) {
harddel* D = hardDels[i];
outputFile << endl << D->type << " - " << D->count << " time(s).\n";
}
}
outputFile.close();
}
else
{
} else {
return false;
}
return true;
}
void sortRuntimes()
{
string tempRuntime[maxStorage+1];
string tempProc[maxStorage+1];
string tempSource[maxStorage+1];
string tempUsr[maxStorage+1];
string tempSrc[maxStorage+1];
unsigned int tempNumRuntime[maxStorage+1];
unsigned int highestCount = 0; //Used for descending order
// int keepLooping = 0;
//Move all of our data into temporary arrays. Also clear the stored data (not necessary but.. just incase)
for(int i=0; i <= maxStorage; i++)
{
//Get the largest occurance of a single runtime
if(highestCount < numRuntime[i])
{
highestCount = numRuntime[i];
}
tempRuntime[i] = storedRuntime[i]; storedRuntime[i] = "Blank";
tempProc[i] = storedProc[i]; storedProc[i] = "Blank";
tempSource[i] = storedSource[i]; storedSource[i] = "Blank";
tempUsr[i] = storedUsr[i]; storedUsr[i] = "Blank";
tempSrc[i] = storedSrc[i]; storedSrc[i] = "Blank";
tempNumRuntime[i] = numRuntime[i]; numRuntime[i] = 0;
}
while(highestCount > 0)
{
for(int i=0; i <= maxStorage; i++) //For every runtime
{
if(tempNumRuntime[i] == highestCount) //If the number of occurances of that runtime is equal to our current highest
{
for(int j=0; j <= maxStorage; j++) //Find the next available slot and store the info
{
if(storedRuntime[j] == "Blank") //Found an empty spot
{
storedRuntime[j] = tempRuntime[i];
storedProc[j] = tempProc[i];
storedSource[j] = tempSource[i];
storedUsr[j] = tempUsr[i];
storedSrc[j] = tempSrc[i];
numRuntime[j] = tempNumRuntime[i];
break;
}
}
}
}
highestCount--; //Lower our 'highest' by one and continue
}
}
void sortHardDels() //copypasting and I don't care~
{
string tempHardDel[maxStorage + 1];
unsigned int tempNumHardDel[maxStorage + 1];
unsigned int highestCount = 0;
for (int i = 0; i <= maxStorage; i++)
{
//Get the largest occurance of a single hard deletion
if (highestCount < numHardDel[i])
{
highestCount = numHardDel[i];
}
tempHardDel[i] = storedHardDel[i]; storedHardDel[i] = "Blank";
tempNumHardDel[i] = numHardDel[i]; numHardDel[i] = 0;
}
while (highestCount > 0)
{
for (int i = 0; i <= maxStorage; i++) //For every hard deletion
{
if (tempNumHardDel[i] == highestCount) //If the number of occurances of that hard deletion is equal to our current highest
{
for (int j = 0; j <= maxStorage; j++) //Find the next available slot and store the info
{
if (storedHardDel[j] == "Blank") //Found an empty spot
{
storedHardDel[j] = tempHardDel[i];
numHardDel[j] = tempNumHardDel[i];
break;
}
}
}
}
highestCount--; //Lower our 'highest' by one and continue
}
}
int main() {
char exit; //Used to stop the program from immediatly exiting
char exit; //Used to stop the program from immediately exiting
//Start everything fresh. "Blank" should never occur in the runtime logs on its own.
for(int i=0; i <= maxStorage; i++)
{
storedRuntime[i] = "Blank";
storedProc[i] = "Blank";
storedSource[i] = "Blank";
storedUsr[i] = "Blank";
storedSrc[i] = "Blank";
numRuntime[i] = 0;
storedHardDel[i] = "Blank";
numHardDel[i] = 0;
}
if(readFromFile())
{
if(readFromFile()) {
cout << "Input read successfully!\n";
}
else
{
} else {
cout << "Input failed to open, shutting down.\n";
cout << "\nEnter any letter to quit.\n";
cin >> exit;
return 1;
}
sortRuntimes();
sortHardDels();
if(writeToFile())
{
if(writeToFile()) {
cout << "Output was successful!\n";
cout << "\nEnter any letter to quit.\n";
cin >> exit;
return 0;
}
else
{
} else {
cout << "The output file could not be opened, shutting down.\n";
cout << "\nEnter any letter to quit.\n";
cin >> exit;
Binary file not shown.
-87
View File
@@ -1,87 +0,0 @@
#!/usr/bin/env python3
# Runtime Condenser, rewritten in python by tkdrg
# Only the first set of proc, file, usr and src will be kept. The rest is truncated.
# This script is valid on both python2 and python3
runtimes = dict()
infloops = dict()
harddels = dict()
def readFromFile(target='input.txt'):
global runtimes, infloops, harddels
f = open(target)
for line in iter(f.readline, ''):
if 'Infinite loop suspected' in line or 'Maximum recursion level reached' in line:
f.readline() # Throw away the 'If it is not an infinite loop' line
line = f.readline()
try:
i = infloops[line]
i['num'] += 1
except KeyError:
infloops[line] = {'file': f.readline(), 'usr': f.readline(), 'src': f.readline(), 'num': 1}
elif 'runtime error:' in line:
try:
i = runtimes[line]
i['num'] += 1
except KeyError:
runtimes[line] = {'proc': f.readline(), 'file': f.readline(), 'usr': f.readline(), 'src': f.readline(), 'num': 1}
elif 'Path :' in line:
try:
i = harddels[line]
i['num'] += int(f.readline().split()[2])
except KeyError:
harddels[line] = {'num': int(f.readline().split()[2])}
def writeToFile(target='output.txt'):
global runtimes, infloops, harddels
f = open(target, 'w')
f.write('Note: The proc name, file, and usr are all from the FIRST of the identical runtimes. Everything else is cropped.\n\n')
if len(infloops):
f.write('Total unique infinite loops: {}\n'.format(len(infloops)))
f.write('Total infinite loops: {}\n\n'.format(sum((i[1]['num'] for i in infloops))))
if len(runtimes):
f.write('Total unique runtimes: {}\n'.format(len(runtimes)))
f.write('Total runtimes: {}\n\n'.format(sum((i[1]['num'] for i in runtimes))))
if len(harddels):
f.write('Total unique hard deletions: {}\n'.format(len(harddels)))
f.write('Total hard deletions: {}\n\n'.format(sum((i[1]['num'] for i in harddels))))
if len(infloops):
f.write('** Infinite loops **\n')
for t in infloops:
i = t[1]
f.write('The following infinite loop has occured {} time(s).\n'.format(i['num']))
f.write(''.join([t[0], i['file'], i['usr'], i['src']]))
f.write('\n')
if len(runtimes):
f.write('** Runtimes **\n')
for t in runtimes:
i = t[1]
f.write('The following runtime has occured {} time(s).\n'.format(i['num']))
f.write(''.join([t[0], i['proc'], i['file'], i['usr'], i['src']]))
f.write('\n')
if len(harddels):
f.write('** Hard deletions **\n')
for t in harddels:
i = t[1]
f.write('The following path has failed to GC {} time(s).\n'.format(i['num']))
f.write('{}\n'.format(t[0]))
if __name__ == '__main__':
readFromFile()
runtimes = sorted(runtimes.items(), key=lambda x: x[1]['num'], reverse=True)
infloops = sorted(infloops.items(), key=lambda x: x[1]['num'], reverse=True)
harddels = sorted(harddels.items(), key=lambda x: x[1]['num'], reverse=True)
writeToFile()