aboutsummaryrefslogtreecommitdiff
path: root/lab6_malloclab/grade-malloc.py
blob: fdb7e912b12f6b48e0e2c483570a3f9c69d76a4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python3

import sys
import os
import re
import io
import subprocess
import pprint

debug = os.getenv("DEBUG") or False

os.system("make")

TRACES = [
    "binary-bal.rep",
    "binary2-bal.rep",
    "cccp-bal.rep",
    "coalescing-bal.rep",
    "cp-decl-bal.rep",
    "random-bal.rep",
    "random2-bal.rep",
    "realloc-bal.rep",
    "realloc2-bal.rep"
]

reCorrect = re.compile(r"correct:(\d+)")
rePerfidx = re.compile(r"perfidx:(\d+)")
reTerm = re.compile(r"Terminated with")


#
# Traces-handout is used in the solution file, traces is in the student version.
#
TRACEDIR = 'traces-handout' if os.path.isdir('traces-handout') else 'traces'
if debug:
    print('traces', TRACEDIR)


def is_exe(fpath):
    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)


MDRIVERS = ['./mdriver']
if len(sys.argv) > 1:
    MDRIVERS = [file for file in sys.argv[1:] if is_exe(file)]


def runCmd(cmd):
    proc = subprocess.Popen(cmd, bufsize=0, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    try:
        stdout, stderr = proc.communicate(timeout=60)
        if proc.returncode != 0:
            ##
            ## For failure, we assume no output
            ##
            if debug: print(f"Running {cmd} returned {proc.returncode}")
            return "", ""
    except subprocess.TimeoutExpired:
        print("Timeout running command:", cmd)
        proc.kill()
        stdout = ""
        stderr = ""
    return stdout, stderr


def runTrace(program, tracefile):
    if debug:
        print("Run", program, "on", tracefile)
    if not is_exe(program):
        print(f"Your program file {program} does not exist or is not executable")
        return False, None

    test_out, test_err = runCmd([program,
                                 "-g",
                                 "-a",
                                 "-f", os.path.join(TRACEDIR, tracefile)])

    if "ERROR" in test_out:
        print(f"*** Your program failed running trace `{tracefile}'")
        print(f"*** so it contains errors and can not be graded.")
        print(f"*** Your program must work for all traces.")
        sys.exit(100)


    test = io.StringIO(test_out)

    perfidx = None
    correct = False
    for line in test:
        if debug:
            print("output:", line.strip())
        term = reTerm.match(line)
        if term:
            if debug: print(f"Program terminated: {line}")
            return 0,0
        cor = reCorrect.match(line)
        if cor:
            correct = cor.group(1)
        else:
            per = rePerfidx.match(line)
            if per:
                perfidx = per.group(1)
            else:
                print(line.strip())
    return correct, perfidx

def computeScore(x):
    if len(x) != 9:
        print("Bogus score vector")
    
    if sum(x) == 0:
        return 0

    binary = (x[0] + x[1])/2
    prog = (x[2] + x[4])/2
    coal = x[3]
    rand = (x[5] + x[6])/2
    realloc = (x[7] + x[8])/2
#Intercept    0.005740
#binary       0.108161
#prog         0.728372
#coal        -1.011578
#rand         0.768576
#realloc      0.574040
    print(binary, ",", prog, ",", coal, ",", rand, ",", realloc)
    return min(110, 0.00574 + binary * 0.108 + prog * 0.728 + coal * -1.012 + rand * 0.769 + realloc * 0.574)

perfDict = {}
for mdriver in MDRIVERS:
    performanceList = []
    allCorrect = True
    for trace in TRACES:
        correct, perfidx = runTrace(mdriver, trace)
        allCorrect = allCorrect and correct
        performanceList.append(perfidx)
    if allCorrect:
        perfDict[mdriver] = [int(x) for x in performanceList]
    else:
        print("%-20s:" % (mdriver), "failed")

#print(perfDict)
for mdriver in perfDict.keys():
    trimmed = perfDict[mdriver]
    score = min(110, computeScore(trimmed))
    print(f"Grade {mdriver:<30s} {score:3.1f}")