# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # DLProfile Example using l2hmc-qcd

# ## Set imports and neccessary environment variables

import pathlib
import os
import sys
import matplotlib.pyplot as plt
import warnings
import pprint
import pandas
import ntpath

VANIDL_DIR="{}".format(pathlib.Path(os.getcwd()).parent.absolute())
sys.path.insert(0, VANIDL_DIR)
warnings.filterwarnings('ignore')

os.environ["DARSHAN_DIR"] = "/soft/perftools/darshan/darshan-3.1.8"
os.environ["VANIDL_DIR"] = VANIDL_DIR

# #### Formatting

pp = pprint.PrettyPrinter(indent=1)
class color:
    PURPLE = '\033[95m'
    CYAN = '\033[96m'
    DARKCYAN = '\033[36m'
    BLUE = '\033[94m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RED = '\033[91m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'
    END = '\033[0m'


# ## Create instrance of DL Profile and load the darshan file

from src.vanidl import VaniDL
profile = VaniDL()

# +
#import shutil
#shutil.rmtree('/tmp/temp_analysis')

# +

DATAPATH_INCLUDES = []
status = profile.Load("/home/dhari/darshan-logs/apps/l2hmc-qcd/l2hmc_run2_p8.darshan", data_paths_include=DATAPATH_INCLUDES)
if status:
    print("Darshan Trace loaded Successfully!")
else:
    print("Darshan Trace load Failed!")
    print(profile._error_str())
# -

# ## Use Profile object to analyze the darshan I/O trace.

# ### Verify if object works
#
# The GetDXTAsDF() function enables users to perform analysis 

df = profile.GetDXTAsDF()
pp.pprint("Files used in the application")
pp.pprint(df['Filename'].unique().tolist())

df_normal = profile.GetTraceAsDF()
pp.pprint("Files used in the application")
pp.pprint(df_normal['Filename'].unique().tolist())

# ### Collect the summary of the Application

# +
summary = profile.GetSummary()
print("\n")
print(color.BOLD + "Data Access Summary (from Darshan):"+ color.END)
print("Total Job time\t\t\t:\t{:0.2f} seconds".format(summary['job_time']))
#FIXME: calculate time per rank and then take max across it.
print("Time spent in I/O\t\t:\t{:0.2f} seconds".format(summary['total_io_time']))
print("% Time spent in I/O\t\t:\t{:0.2f}%".format(float(summary['total_io_time'])*100/summary['job_time']))
print("Total Data Accessed\t\t:\t{:0.2f} GB".format(float(summary['total_io_bytes'])/1024.0/1024.0/1024.0))
print("Data Access Modules used\t:\t{}".format(summary['io_interface_used']))
print("Data Operations\t\t\t:\t{}".format(summary['io_operations_used']))
print("# of files used\t\t\t:\t{}".format(len(summary['files_used'])))
print("# of MPI Ranks\t\t\t:\t{:0.0f} ranks".format(8))
      
     
print(color.UNDERLINE + "Access Pattern:"+ color.END)
print("\tSequential\t\t:\t{:0.2f}%".format(float(summary['access_pattern']['sequential'])))
print("\tConsecutive\t\t:\t{:0.2f}%".format(float(summary['access_pattern']['consecutive'])))
#An I/O op issued at an offset greater than where the previous I/O op ended.
#An I/O op issued at the offset immediately after the end of the previous I/O

print("\n")
print(color.BOLD + "Files Summary:"+ color.END)
print("File Types\t\t\t:\t{}".format(summary['file_used_summary']['types']))
print(color.UNDERLINE + "Dataset Size:"+ color.END)
print("\tTotal\t\t\t:\t{:0.3f} GB".format(float(summary['file_used_summary']['size']['total'])/1024.0/1024.0/1024.0))
print("\tMin,Max\t\t\t:\t{:0.3f} GB and {:0.3f} GB".format(float(summary['file_used_summary']['size']['min'])/1024.0/1024.0/1024.0,float(summary['file_used_summary']['size']['max'])/1024.0/1024.0/1024.0))
print("\tAverage\t\t\t:\t{:0.3f} GB".format(float(summary['file_used_summary']['size']['mean'])/1024.0/1024.0/1024.0))
# -

pp.pprint("Job time : {} seconds".format(profile.GetJobTime()))

pp.pprint("Time spent by application on I/O: {} seconds".format(profile.GetIOTime()))

# ### I/O time spent on each file

for file in df_normal['Filename'].unique():
    filename = os.path.splitext(ntpath.basename(file))[0]
    print("I/O time for file {}: {:0.2f} seconds".format(filename,profile.GetIOTime(filepath=file)))

# ### I/O Time spent per rank

for rank in df['Rank'].unique():
    print("I/O time for rank {}: {:0.2f} seconds".format(rank,profile.GetIOTime(rank=rank)))

"Total I/O performed by application: {:0.2f} GB".format(float(profile.GetIOSize())/1024.0/1024.0/1024.0)

# ### I/O performed on each file

for file in df_normal['Filename'].unique():
    filename = os.path.splitext(ntpath.basename(file))[0]
    print("I/O performed on file {}: {:0.2f} KB".format(filename,float(profile.GetIOSize(filepath=file))/1024.0))

for col in df_normal.columns:
    print(col)

for index, row in df_normal.iterrows():
    if row['Module'] == "STDIO":
        if row['STDIO_BYTES_READ'] != 0:
            print(row['Filename'], row['STDIO_F_READ_START_TIMESTAMP'],row['STDIO_F_READ_END_TIMESTAMP'])
        if row['STDIO_BYTES_WRITTEN'] != 0:
            print(row['Filename'], row['STDIO_F_WRITE_START_TIMESTAMP'],row['STDIO_F_WRITE_END_TIMESTAMP'])

ranks_set=[0,1,2,3,4,5,6,7]
def progress(count, total, status=''):
    bar_len = 60
    filled_len = int(round(bar_len * count / float(total)))
    percents = round(100.0 * count / float(total), 1)
    bar = '=' * filled_len + '-' * (bar_len - filled_len)
    if count == 1:
        print("")
    print("\r[{}] {}% {} of {} {} ".format(bar, percents, count, total, status), end='')
    if count == total:
        print("")
    os.sys.stdout.flush()
timestamps = []
data = []
pb_total = df_normal.count()['Module'];
i = 1
for index, row in df_normal.iterrows():
    if i % 100 == 0 or i == pb_total:
        progress(i, pb_total, status='Creating Darshan Timeline')
    i += 1
    if row['Module'] == "STDIO":
        args_val = {
            "Module": row['Module'],
            "Rank": row['Rank'],
            "Filename": row['Filename'],
            "STDIO_OPENS": row['STDIO_OPENS'],
            "STDIO_FDOPENS": row['STDIO_FDOPENS'],
            "STDIO_READS": row['STDIO_READS'],
            "STDIO_WRITES": row['STDIO_WRITES'],
            "STDIO_SEEKS": row['STDIO_SEEKS'],
            "STDIO_FLUSHES": row['STDIO_FLUSHES'],
            "STDIO_BYTES_WRITTEN": row['STDIO_BYTES_WRITTEN'],
            "STDIO_BYTES_READ": row['STDIO_BYTES_READ'],
            "STDIO_MAX_BYTE_READ": row['STDIO_MAX_BYTE_READ'],
            "STDIO_MAX_BYTE_WRITTEN": row['STDIO_MAX_BYTE_WRITTEN'],
            "STDIO_FASTEST_RANK": row['STDIO_FASTEST_RANK'],
            "STDIO_FASTEST_RANK_BYTES": row['STDIO_FASTEST_RANK_BYTES'],
            "STDIO_SLOWEST_RANK": row['STDIO_SLOWEST_RANK'],
            "STDIO_SLOWEST_RANK_BYTES": row['STDIO_SLOWEST_RANK_BYTES'],
            "STDIO_F_META_TIME": row['STDIO_F_META_TIME'],
            "STDIO_F_WRITE_TIME": row['STDIO_F_WRITE_TIME'],
            "STDIO_F_READ_TIME": row['STDIO_F_READ_TIME'],
            "STDIO_F_OPEN_START_TIMESTAMP": row['STDIO_F_OPEN_START_TIMESTAMP'],
            "STDIO_F_CLOSE_START_TIMESTAMP": row['STDIO_F_CLOSE_START_TIMESTAMP'],
            "STDIO_F_WRITE_START_TIMESTAMP": row['STDIO_F_WRITE_START_TIMESTAMP'],
            "STDIO_F_READ_START_TIMESTAMP": row['STDIO_F_READ_START_TIMESTAMP'],
            "STDIO_F_OPEN_END_TIMESTAMP": row['STDIO_F_OPEN_END_TIMESTAMP'],
            "STDIO_F_CLOSE_END_TIMESTAMP": row['STDIO_F_CLOSE_END_TIMESTAMP'],
            "STDIO_F_WRITE_END_TIMESTAMP": row['STDIO_F_WRITE_END_TIMESTAMP'],
            "STDIO_F_READ_END_TIMESTAMP": row['STDIO_F_READ_END_TIMESTAMP'],
            "STDIO_F_FASTEST_RANK_TIME": row['STDIO_F_FASTEST_RANK_TIME'],
            "STDIO_F_SLOWEST_RANK_TIME": row['STDIO_F_SLOWEST_RANK_TIME'],
            "STDIO_F_VARIANCE_RANK_TIME": row['STDIO_F_VARIANCE_RANK_TIME'],
            "STDIO_F_VARIANCE_RANK_BYTES": row['STDIO_F_VARIANCE_RANK_BYTES']
        }
        ranks = []
        if row['Rank'] != -1:
            ranks.append(int(row['Rank']))
        else:
            ranks.extend(list(ranks_set))
        for rank in ranks:
            if row['STDIO_BYTES_READ'] != 0:
                event_start = {"name": "darshan", "cat": row['Module'], "ph": "B",
                               "ts": int(float(row['STDIO_F_READ_START_TIMESTAMP']) * 1e6),
                               "pid": rank, "tid": 1,
                               "args": args_val
                               }
                event_end = {"ph": "E", "ts": int(float(row['STDIO_F_READ_END_TIMESTAMP']) * 1e6),
                             "pid": rank, "tid": 1,
                             "args": args_val
                             }
                timestamps.append(int(float(row['STDIO_F_READ_START_TIMESTAMP']) * 1e6))
                data.append(event_start)
                timestamps.append(int(float(row['STDIO_F_READ_END_TIMESTAMP']) * 1e6))
                data.append(event_end)
            if row['STDIO_BYTES_WRITTEN'] != 0:
                event_start = {"name": "darshan", "cat": row['Module'], "ph": "B",
                               "ts": int(float(row['STDIO_F_WRITE_START_TIMESTAMP']) * 1e6),
                               "pid": rank, "tid": 1,
                               "args": args_val
                               }
                event_end = {"ph": "E", "ts": int(float(row['STDIO_F_WRITE_END_TIMESTAMP']) * 1e6),
                             "pid": rank, "tid": 1,
                             "args": args_val
                             }
                timestamps.append(int(float(row['STDIO_F_WRITE_START_TIMESTAMP']) * 1e6))
                data.append(event_start)
                timestamps.append(int(float(row['STDIO_F_WRITE_END_TIMESTAMP']) * 1e6))
                data.append(event_end)

data

profile.CreateChromeTimeline(location="/home/dhari", filename="l2hmc_run2_p8_io.json")



StarcoderdataJupyterScriptsDedupFiltered