Commit 00d0d00f authored by Andreas Schmidt's avatar Andreas Schmidt
Browse files

Merge branch 'develop' of git.nt.uni-saarland.de:as/X-Lap into HEAD

parents cafd78bc 66281a29
Loading
Loading
Loading
Loading
+75 −25
Original line number Diff line number Diff line
@@ -19,32 +19,35 @@ def _get_cyclestamp(df, event, idx):
    cycleevent = [x for x in list(df) if str(x) == cname][0]
    return list(df[cycleevent])[idx]

def _happens_before(df, a, b):
def _get_thread_for_event(config, e):
    for name, data in config['stamps'].items():
        if name == str(e)[:-2]:
            return data['Thread']
    return None

def _happens_before(df, a, b, config):
    """
    check if a happens-before b in the trace
    """
    l = len(df[a])
    # first, check if the timestamps are often equal. In this case, we have a
    # very short region and we should therefore check cyclestamps as well.
    #
    # EPSILON represents a grace period, in microseconds, for detecting similar
    # timestamps.
    #
    # TODO: we should only check the cycle stamps if a and b occur in the same
    # thread.
    EPSILON=1
    numeq = len([i for i in range(l) if _get_timestamp(df, a, i) + EPSILON >= _get_timestamp(df, b, i) and _get_timestamp(df, a, i) <= _get_timestamp(df, b, i) + EPSILON])
    if (numeq >= 0.95 * l):
        # The region is so short that we have to take cyclestamps into consideration
    # check whether a and b occur in the same thread. If so, a and b cannot be
    # concurrent.
    ta = _get_thread_for_event(config, a)
    tb = _get_thread_for_event(config, b)
    if (ta == tb and ta != None and tb != None):
        for i in range(l):
            tsa = _get_timestamp(df, a, i)
            tsb = _get_timestamp(df, b, i)
            if tsa > tsb:
                return False
            if tsa == tsb and _get_cyclestamp(df, a, i) > _get_cyclestamp(df, b, i):
            csa = _get_cyclestamp(df, a, i)
            csb = _get_cyclestamp(df, b, i)
            if tsa == tsb and csa > csb and csb != 0:
                return False
    else:
        # The region i long enough to use timestamps only
        return True

    # since a and b occur in different threads, we cannot compare cyclestamps.
    # If in doubt, a and b are concurrent.
    for i in range(l):
        if _get_timestamp(df, a, i) >= _get_timestamp(df, b, i):
            return False
@@ -70,6 +73,52 @@ def _happens_directly_before(df, a, b, hb):
            return False
    return True

def _locally_happens_directly_before(df, a, b, hb, config):
    """
    check if a happens-directly-before b in the trace but, be a little bit more
    tolerant regarding intra-thread durations. Consider the following scenario

    Thread A: A1 -> A2 -> A3
    Thread B: B1 -> B2

    This setup can result in the following directly-happens-before graph:

    A1   B1
     \  /
      A2
     /  \
    A3   B2

    In this case, B1 does not happens-directly-before B2 because, by chance, A2
    happens inbetween. If we ignore this anomaly, we only analyse <B1,A2> and
    <A2,B2>. Both ranges probably have low latency criticality, since their
    durations are random (because they depend on thread interleavings).
    However, we really want to analyse <B1,B2> because they actually represent
    a meaningful range in thread B.

    This function therefore computes a modified happens-directly-before graph
    with relaxed restrictions for intra-thread ranges:

    A1    B1
      \  /|
       A2 |
      /  \|
    A3    B2
    """
    if not _fast_happens_before(df, a, b, hb):
        return False
    ta = _get_thread_for_event(config, a)
    tb = _get_thread_for_event(config, b)
    if ta == tb and ta != None and tb != None:
        for c in df:
            if _get_thread_for_event(config, c) != ta:
                continue
            if _fast_happens_before(df, a, c, hb) and _fast_happens_before(df, c, b, hb):
                return False
        return True
    else:
        return _happens_directly_before(df, a, b, hb)

def _plot_controlflow_graph(df, hdb):
    """
    print the control flow graph in a format that dot understands
@@ -94,9 +143,7 @@ def _plot_critical_regions(df,hdb):
        print("%-10f %10s -> %10s"%(region['Correlation'], region['Start'], region['End']), file=sys.stderr)


def analyse(df):
    #print(str(_happens_before(df, 'PrrtSendStart_T', 'PrrtSendEnd_T')), file=sys.stderr)
    #print(str(len([i for i in range(len(df['PrrtSendStart_T'])) if _get_timestamp(df, 'PrrtSendStart_T', i) == _get_timestamp(df, 'PrrtSendEnd_T', i) and _get_cyclestamp(df, 'PrrtSendStart_T', i) < _get_cyclestamp(df, 'PrrtSendEnd_T', i)])), file=sys.stderr)
def analyse(df, config):
    hb = []
    for event1 in df:
        if not str(event1).endswith("_T"):
@@ -107,10 +154,9 @@ def analyse(df):
                continue
            if str(event1) == str(event2):
                continue
            if _happens_before(df, event1, event2):
            if _happens_before(df, event1, event2, config):
                hb += [{'Start':str(event1), 'End':str(event2)}]

    #print (",".join(map(str,hb)), file=sys.stderr)
    hdb = []
    e2e = list(df['EndToEnd_D'])
    for event1 in df:
@@ -121,6 +167,7 @@ def analyse(df):
                continue
            if str(event1) == str(event2):
                continue
            #if _locally_happens_directly_before(df, event1, event2, hb, config):
            if _happens_directly_before(df, event1, event2, hb):
                # compute the correlation between e2e latency and event1-event2 latency
                l1 = list(df[event1])
@@ -128,7 +175,10 @@ def analyse(df):
                l3 = []
                for i in range(len(l1)):
                    l3 += [_get_timestamp(df,event2,i) - _get_timestamp(df,event1,i)]
                if any(map(lambda x: x != 0, l3)):
                    correlation = pearsonr(l3, e2e)[0]
                else:
                    correlation = 0

                hdb += [{'Start':str(event1), 'End':str(event2), 'Correlation':correlation}]

+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ def main():
                print(output)
        elif command == "latency":
            df_data = evaluate(data_files["sender"], data_files["receiver"], config=config, kind=0)
            latency.analyse(df_data)
            latency.analyse(df_data, config)
        else:
            df_data = evaluate(data_files["sender"], data_files["receiver"], config=config, kind=0)