SWDEV-432445: Handling multiple agents for ATT

Change-Id: I41d30baf2c469d8ddb58e3385b88a7b04a30422e


[ROCm/rocprofiler commit: b93d5e7e79]
Этот коммит содержится в:
Giovanni LB
2023-12-05 23:25:15 -03:00
коммит произвёл Giovanni Baraldi
родитель f275cdd602
Коммит f446834082
9 изменённых файлов: 155 добавлений и 238 удалений
+12
Просмотреть файл
@@ -306,3 +306,15 @@ Example for file plugin output:
- Added Tool versioning to be able to run rocprofv2 using rocprof. See README for more information.
- Added Plugin Versioning way in rocprofv2. See README for more details.
- Added --version in the rocprof and rocprofv2 to be able to see the current rocprof/v2 version along with ROCm version information.
## ROCprofiler for rocm 6.2
### Added
- ATT: Continuous mode. The input file now has a DISPATCH_RANGE=begin,end that specifies continuous ATT collection during the application run.
- ATT: Ability to dump raw codeobjects as .out files with ISA_CAPTURE_MODE=[0,1,2]
### Removed
- ATT: Network mode, since it was redundant with file mode.
- ATT: Generated isa.s file, since the functionality was moved from collection to parsing time.
+12 -14
Просмотреть файл
@@ -352,17 +352,17 @@ Tool used to collect fine-grained hardware metrics. Provides ISA-level instructi
Path for the running application
- ATT plugin optional parameters
- --att_kernel "filename": Kernel filename(s) (glob) to use. A CSV file (or UI folder) will be generated for each kernel.txt file. Default: all in current folder.
- --mode [csv, network, file, off (default)]
- --mode [csv, file, off (default)]
- off
Runs trace collection but not analysis, so it can be analyzed at a later time. Run rocprofv2 ATT with the same parameters (+ --mode csv), removing the application binary, to analyze previously generated traces.
- csv
Dumps the analyzed assembly into a CSV format, with the hitcount and total cycles cost. Recommended mode for most users.
- network (deprecated)
Opens the server with the browser UI.
att needs 2 ports available (e.g. 8000, 18000). There is an option (default: --ports "8000,18000") to change these.
In case rocprofv2 is running on a different machine, use port forwarding `ssh -L 8000:localhost:8000 <user@IP>` so the browser can be used locally. For docker, use --network=host --ipc=host -p8000:8000 -p18000:18000
- file (deprecated)
Dumps the analyzed json files to disk for vieweing at a later time. Run python3 httpserver.py from within the generated ui/ folder to view the trace, similarly to network mode. The folder can be copied to another machine, and will run without rocm.
Dumps the analyzed json files to disk for vieweing at a later time. Run python3 httpserver.py from within the generated name_ui/ folder to view the trace. The folder can be copied to another machine, and will run without rocm.
- file,csv
Both options can be used at the same time, generating a UI folder and a .csv.
- network [removed]
Network mode was removed, since it's functionality is included in file mode with the httpserver.py script generated inside the UI folder.
- input.txt
Required. Used to select specific compute units and other trace parameters.
For first time users, using the following input file:
@@ -394,14 +394,10 @@ Tool used to collect fine-grained hardware metrics. Provides ISA-level instructi
- BUFFER_SIZE=[size] // Sets size of the ATT buffer collection, per dispatch, in megabytes (shared among all shader engines).
- ISA_CAPTURE_MODE=[0,1,2] // Set codeobj capture mode during kernel dispatch.
- 0 = capture symbols only.
- 1 = capture symbols for file:// and make a copy of memory://
- 2 = Copy file:// and memory://
- ISA_DUMP_MODE=[0,1,2,3] // Set how captured codeobj information is dumped when a trace record arrives.
- 0 = Default. Dump everything.
- 1 = Dump only the code object containing the kernel address in the kernel dispatch packet.
- 2 = Dump a single kernel symbol matching the kernel dispatch packet.
- 3 = Disables ISA Dumping.
- By default, kernel names are truncated for ATT.To disable, please see the kernel name truncation section below.
- 1 = capture symbols for file:// and make a copy of memory://, dump captured copy as .out file.
- 2 = Copy file:// and memory://, dump copied codeobj as .out files.
- DISPATCH_RANGE=[begin],[end] // Continuously collect ATT data starting at "begin" and stop at "end". Alternative to DISPATCH= and KERNEL=.
- By default, kernel names are truncated for ATT. To disable, please see the kernel name truncation section below.
- Example for vectoradd.
@@ -450,6 +446,8 @@ Tool used to collect fine-grained hardware metrics. Provides ISA-level instructi
export ROCPROFILER_MAX_ATT_PROFILES=<max_collections>
```
Or, alternatively, use the continuous ATT mode (DISPATCH_RANGE parameter).
***
### Flush Interval
+22 -12
Просмотреть файл
@@ -438,21 +438,21 @@ if __name__ == "__main__":
"--mode",
help="""ATT analysis modes:\n
off: Only run ATT collection, disable analysis.\n
file: dump json files to disk.\n
network: Open att server over the network.""",
file: dump json files to disk.""",
type=str,
default="off",
)
args = parser.parse_args()
args.mode = args.mode.lower().split(',')
CSV_MODE = False
if args.mode.lower() == 'csv':
FILE_MODE = False
if 'csv' in args.mode:
CSV_MODE = True
elif args.mode.lower() == 'file':
args.dumpfiles = True
elif args.mode.lower() == "network":
args.dumpfiles = False
else:
if 'file' in args.mode:
FILE_MODE = True
if not CSV_MODE and not FILE_MODE:
print("Skipping analysis.")
quit()
@@ -482,10 +482,21 @@ if __name__ == "__main__":
for line in f:
att_kernel_f.append(line.split('\n')[0])
# returns element index of the file:// or memory:// filepath in the string
get_path_loc = lambda x: np.sum([len(m) for m in x.split(' ')[:3]])+3
# adds the OUTPUT_PATH env variable to a filepath if necessary
add_pathnv = lambda x: x[:get_path_loc(x)] + os.path.join(pathenv, x[get_path_loc(x):])
# returns the memory address in the string
get_addr = lambda x: int(x.split(' ')[0][2:], 16)
# Sets a preference for 'file' paths to be added before 'memory' paths. Sorts by addr.
get_addr_preference = lambda x: [0 if 'file' in x[get_path_loc(x):] else 1<<60][0]
# Get the GPU id in the string
gpu_id = int(att_kernel_f[0].split(' ')[2].split('GPU[')[1].split(']')[0])
# Eliminame first line in the att_kernel txt file and adds the OUTPUT_PATH as needed
att_kernel_f = [add_pathnv(p) if '.out' == p[-4:] else p for p in att_kernel_f[1:]]
# Sorts the list of codeobj by address, with 'file' given preference
att_kernel_f = sorted(att_kernel_f, key=lambda x: get_addr(x)+get_addr_preference(x))
assembly_code = deepcopy(args.assembly_code)
# Assembly parsing
@@ -526,7 +537,7 @@ if __name__ == "__main__":
gc.collect()
if bIsAuto:
codeservice = CodeobjService(att_kernel_f, SO.classify_asm_line)
codeservice = CodeobjService(gpu_id, att_kernel_f, SO.classify_asm_line)
else:
codeservice = None
@@ -563,7 +574,8 @@ if __name__ == "__main__":
if CSV_MODE:
from att_to_csv import dump_csv
dump_csv(code, trace_instance_name)
else:
if FILE_MODE:
drawinfo = {
"TIMELINES": gen_timelines(DBFILES),
"EVENTS": EVENTS,
@@ -573,11 +585,9 @@ if __name__ == "__main__":
"DispatchNames": {id: codeservice.getSymbolName(addr) for id, addr in kernel_addr.items()}
}
view_trace(
args,
code,
DBFILES,
analysed_filenames,
args.dumpfiles,
0,
gfxv,
drawinfo,
+50 -35
Просмотреть файл
@@ -53,24 +53,27 @@
#define C_API_BEGIN try {
#define C_API_END(returndata) \
} catch (std::exception& e) \
{ \
std::cerr << "Error: " << e.what() << std::endl; \
return returndata; \
} \
catch (std::string& s) \
{ \
std::cerr << "Error: " << s << std::endl; \
return returndata; \
} \
catch (...) \
{ \
return returndata; \
#define C_API_END(returndata) \
} catch (std::exception& e) \
{ \
std::cerr << "Codeobj API lookup error: " << e.what() << std::endl; \
return returndata; \
} \
catch (std::string& s) \
{ \
std::cerr << "Codeobj API lookup error: " << s << std::endl; \
return returndata; \
} \
catch (...) \
{ \
return returndata; \
}
CodeObjDecoderComponent::CodeObjDecoderComponent(const char* codeobj_data, uint64_t codeobj_size)
{
CodeObjDecoderComponent::CodeObjDecoderComponent(
const char* codeobj_data,
uint64_t codeobj_size,
uint64_t gpu_id
) {
m_fd = -1;
#if defined(_GNU_SOURCE) && defined(MFD_ALLOW_SEALING) && defined(MFD_CLOEXEC)
m_fd = ::memfd_create(m_uri.c_str(), MFD_ALLOW_SEALING | MFD_CLOEXEC);
@@ -113,21 +116,28 @@ CodeObjDecoderComponent::CodeObjDecoderComponent(const char* codeobj_data, uint6
size_t line_count;
if (dwarf_getsrclines(&die, &lines, &line_count)) continue;
std::shared_ptr<std::string> dwarf_line_number{nullptr};
for (size_t i = 0; i < line_count; ++i) {
Dwarf_Addr addr;
int line_number;
Dwarf_Line* line = dwarf_onesrcline(lines, i);
if (!line) continue;
if (!dwarf_lineaddr(line, &addr) && !dwarf_lineno(line, &line_number) && line_number)
m_line_number_map[addr] = {dwarf_linesrc(line, nullptr, nullptr), line_number};
if (line && !dwarf_lineaddr(line, &addr) && !dwarf_lineno(line, &line_number) && line_number)
{
std::string src = dwarf_linesrc(line, nullptr, nullptr);
dwarf_line_number = std::make_shared<std::string>(src + ':' + std::to_string(line_number));
}
if (dwarf_line_number.get())
m_line_number_map[addr] = dwarf_line_number;
}
cu_offset = next_offset;
}
// load_symbol_map();
}
disassembly = std::make_unique<DisassemblyInstance>(codeobj_data, codeobj_size, std::nullopt); // Can throw
// Can throw
disassembly = std::make_unique<DisassemblyInstance>(codeobj_data, codeobj_size, gpu_id);
try {
m_symbol_map = disassembly->GetKernelMap(); // Can throw
} catch(...) {}
@@ -169,15 +179,11 @@ CodeObjDecoderComponent::disassemble_instruction(uint64_t faddr, uint64_t vaddr)
throw std::exception();
char* cpp_line = nullptr;
auto it = m_line_number_map.find(vaddr);
if (it != m_line_number_map.end()) {
const std::string& file_name = it->second.first;
size_t line_number = it->second.second;
std::string cpp = file_name + ':' + std::to_string(line_number);
cpp_line = (char*)calloc(cpp.size() + 4, sizeof(char));
std::memcpy(cpp_line, cpp.data(), cpp.size() * sizeof(char));
}
auto it = m_line_number_map.find(vaddr);
if (it != m_line_number_map.end())
cpp_line = it->second->data();
size_t size = disassembly->ReadInstruction(faddr, vaddr, cpp_line);
return {disassembly->last_instruction, size};
}
@@ -217,8 +223,12 @@ void CodeObjDecoderComponent::disassemble_single_kernel(uint64_t kaddr) {
disassemble_kernel(v.faddr, vaddr);
}
CodeobjDecoder::CodeobjDecoder(const char* filepath, uint64_t loadbase, uint64_t mem_size):
loadbase(loadbase), load_end(loadbase + mem_size)
CodeobjDecoder::CodeobjDecoder(
const char* filepath,
uint64_t loadbase,
uint64_t mem_size,
uint64_t gpu_id
): loadbase(loadbase), load_end(loadbase + mem_size)
{
if (!filepath) throw "Empty filepath.";
@@ -237,13 +247,13 @@ CodeobjDecoder::CodeobjDecoder(const char* filepath, uint64_t loadbase, uint64_t
file.seekg(0, file.beg);
file.read(buffer.data(), buffer.size());
decoder = std::make_unique<CodeObjDecoderComponent>(buffer.data(), buffer.size());
decoder = std::make_unique<CodeObjDecoderComponent>(buffer.data(), buffer.size(), gpu_id);
}
else
{
std::unique_ptr<CodeObjectBinary> binary = std::make_unique<CodeObjectBinary>(filepath);
auto& buffer = binary->buffer;
decoder = std::make_unique<CodeObjDecoderComponent>(buffer.data(), buffer.size());
decoder = std::make_unique<CodeObjDecoderComponent>(buffer.data(), buffer.size(), gpu_id);
}
auto elf_segments = decoder->disassembly->getSegments();
@@ -297,11 +307,16 @@ CodeobjTableTranslation table;
extern "C"
{
PUBLIC_API int addDecoder(const char* filename, uint32_t id, uint64_t loadbase, uint64_t memsize)
{
PUBLIC_API int addDecoder(
const char* filename,
uint32_t id,
uint64_t loadbase,
uint64_t memsize,
uint64_t gpu_id
) {
C_API_BEGIN
table.addDecoder(filename, id, loadbase, memsize);
table.addDecoder(filename, id, loadbase, memsize, gpu_id);
return 0;
C_API_END(1)
+20 -7
Просмотреть файл
@@ -37,7 +37,7 @@ class CodeObjDecoderComponent
public:
std::optional<SymbolInfo> find_symbol(uint64_t address);
CodeObjDecoderComponent(const char* codeobj_data, uint64_t codeobj_size);
CodeObjDecoderComponent(const char* codeobj_data, uint64_t codeobj_size, uint64_t gpu_id);
~CodeObjDecoderComponent();
std::pair<instruction_instance_t, size_t>
@@ -48,7 +48,7 @@ public:
int m_fd;
std::map<uint64_t, std::pair<std::string, size_t>> m_line_number_map{};
std::map<uint64_t, std::shared_ptr<std::string>> m_line_number_map{};
std::map<uint64_t, SymbolInfo> m_symbol_map{};
std::string m_uri;
@@ -65,7 +65,8 @@ typedef struct {
class CodeobjDecoder
{
public:
CodeobjDecoder(const char* filepath, uint64_t loadbase, uint64_t memsize);
CodeobjDecoder(const char* filepath, uint64_t loadbase, uint64_t memsize, uint64_t gpu_id);
bool decode_single(uint64_t vaddr);
bool decode_single_at_offset(uint64_t vaddr, uint64_t voffset);
bool add_to_map(uint64_t faddr, uint64_t vaddr, uint64_t voffset);
@@ -111,9 +112,15 @@ class CodeobjList
public:
CodeobjList() = default;
virtual void addDecoder(const char* filepath, uint32_t id, uint64_t loadbase, uint64_t memsize)
virtual void addDecoder(
const char* filepath,
uint32_t id,
uint64_t loadbase,
uint64_t memsize,
uint64_t gpu_id
)
{
decoders[id] = std::make_shared<CodeobjDecoder>(filepath, loadbase, memsize);
decoders[id] = std::make_shared<CodeobjDecoder>(filepath, loadbase, memsize, gpu_id);
}
virtual bool removeDecoder(uint32_t id)
@@ -150,9 +157,15 @@ class CodeobjTableTranslation : protected CodeobjList
public:
CodeobjTableTranslation() = default;
void addDecoder(const char* filepath, uint32_t id, uint64_t loadbase, uint64_t memsize) override
virtual void addDecoder(
const char* filepath,
uint32_t id,
uint64_t loadbase,
uint64_t memsize,
uint64_t gpu_id
) override
{
this->Super::addDecoder(filepath, id, loadbase, memsize);
this->Super::addDecoder(filepath, id, loadbase, memsize, gpu_id);
auto ptr = decoders.at(id);
table.insert({ptr->begin(), static_cast<uint32_t>(ptr->size()), id, 0});
}
+13 -9
Просмотреть файл
@@ -70,6 +70,8 @@ if (amd_comgr_status_s status = call) {
return AMD_COMGR_STATUS_ERROR; \
}
std::unordered_map<uint64_t, std::string> DisassemblyInstance::agent_isa_name{};
CodeObjectBinary::CodeObjectBinary(const std::string& uri) : m_uri(uri) {
const std::string protocol_delim{"://"};
@@ -156,7 +158,7 @@ CodeObjectBinary::CodeObjectBinary(const std::string& uri) : m_uri(uri) {
DisassemblyInstance::DisassemblyInstance(
const char* codeobj_data,
uint64_t codeobj_size,
std::optional<std::string> input_isa
uint64_t gpu_id
)
{
buffer = std::vector<char>(codeobj_size, 0);
@@ -164,20 +166,22 @@ DisassemblyInstance::DisassemblyInstance(
THROW_COMGR(amd_comgr_create_data(AMD_COMGR_DATA_KIND_EXECUTABLE, &data));
THROW_COMGR(amd_comgr_set_data(data, buffer.size(), buffer.data()));
if (!input_isa)
std::string input_isa{};
if (agent_isa_name.find(gpu_id) == agent_isa_name.end())
{
input_isa = "amdgcn-amd-amdhsa--gfx1100";
size_t isa_size = 128;
input_isa.resize(isa_size);
THROW_COMGR(amd_comgr_get_data_isa_name(data, &isa_size, input_isa.data()));
agent_isa_name[gpu_id] = input_isa;
}
if (!input_isa)
else
{
input_isa = std::string();
input_isa->resize(128);
size_t isa_size = sizeof(input_isa->size());
THROW_COMGR(amd_comgr_get_data_isa_name(data, &isa_size, input_isa->data()));
input_isa = agent_isa_name.at(gpu_id);
}
THROW_COMGR(amd_comgr_create_disassembly_info(
input_isa->data(),
input_isa.data(),
&DisassemblyInstance::memory_callback, &DisassemblyInstance::inst_callback,
[](uint64_t address, void* user_data) {}, &info));
+3 -1
Просмотреть файл
@@ -51,7 +51,7 @@ class DisassemblyInstance {
DisassemblyInstance(
const char* codeobj_data,
uint64_t codeobj_size,
std::optional<std::string> input_isa
uint64_t gpu_id
);
~DisassemblyInstance();
@@ -61,6 +61,8 @@ class DisassemblyInstance {
static uint64_t memory_callback(uint64_t from, char* to, uint64_t size, void* user_data);
static void inst_callback(const char* instruction, void* user_data);
static amd_comgr_status_t symbol_callback(amd_comgr_symbol_t symbol, void* user_data);
// Per-gpu_id isa_name
static std::unordered_map<uint64_t, std::string> agent_isa_name;
std::optional<uint64_t> va2fo(uint64_t va);
std::vector<std::pair<uint64_t, uint64_t>> getSegments();
+13 -10
Просмотреть файл
@@ -33,7 +33,7 @@ attplugin.getInstructionFromID.restype = instruction_info_t
attplugin.getInstructionFromID.argtypes = [c_uint32, c_uint64]
attplugin.addDecoder.restype = c_int
attplugin.addDecoder.argtypes = [c_char_p, c_uint32, c_uint64, c_uint64]
attplugin.addDecoder.argtypes = [c_char_p, c_uint32, c_uint64, c_uint64, c_uint64]
attplugin.removeDecoder.restype = c_int
attplugin.removeDecoder.argtypes = [c_uint32, c_uint64]
@@ -48,15 +48,15 @@ def getOffset(addr):
return addr & OFFSET_MASK
class CodeobjInstance:
def __init__(self, line):
def __init__(self, gpu_id, line):
tokens = line.split(' ')
self.load_base = int(tokens[0], 16)
self.memsize = int(tokens[1], 16)
self.att_id = int(tokens[2])
self.fpath = tokens[3]
encoded = self.fpath.encode('utf-8')
self.error = attplugin.addDecoder(encoded, self.att_id, self.load_base, self.memsize)
path = self.fpath.encode('utf-8')
self.error = attplugin.addDecoder(path, self.att_id, self.load_base, self.memsize, gpu_id)
if self.error != 0:
print('Warning: Could not open', line)
raise
@@ -66,7 +66,7 @@ class CodeobjInstance:
class CodeobjService:
def __init__(self, att_kernel_txt, cfunc):
def __init__(self, gpu_id, att_kernel_txt, cfunc):
cfunc.restype = ctypes.c_int
cfunc.argtypes = [ctypes.c_char_p, ctypes.c_size_t]
@@ -77,7 +77,7 @@ class CodeobjService:
try:
if 'memory://' == line[0:len('memory://')]:
continue
service = CodeobjInstance(line)
service = CodeobjInstance(gpu_id, line)
self.services[service.att_id] = service
except:
pass
@@ -132,7 +132,10 @@ class CodeobjService:
return (self.classifier(info_inst.inst, len(inst)), inst, cpp, info_inst.size)
def getSymbolName(self, addr):
name = attplugin.getSymbolName(self.ToRawPC(addr))
if name:
return name.decode()
return "Addr #"+hex(self.ToRawPC(addr))
try:
name = attplugin.getSymbolName(self.ToRawPC(addr))
if name:
return name.decode()
return "Addr #"+hex(self.ToRawPC(addr))
except:
return "Addr #"+hex(addr)
+10 -150
Просмотреть файл
@@ -153,127 +153,6 @@ def extract_data(df, se_number):
return flight_count, wave_filenames, se_filename, allwaves_maxline
class NoCacheHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def end_headers(self):
self.send_my_headers()
http.server.SimpleHTTPRequestHandler.end_headers(self)
def send_my_headers(self):
self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
self.send_header("Pragma", "no-cache")
self.send_header("Expires", "0")
def do_GET(self):
if (
".png?" in self.path
and self.path.split("/")[-1] not in JSON_GLOBAL_DICTIONARY.keys()
):
selections = [int(s) != 0 for s in self.path.split(".png?")[-1]]
counters_json, imagebytes = GeneratePIC(
self.drawinfo, selections[1:], selections[0]
)
JSON_GLOBAL_DICTIONARY["graph_options.json"] = counters_json
JSON_GLOBAL_DICTIONARY[self.path.split("/")[-1]] = imagebytes[
self.path.split("/")[-1].split("?")[0]
]
if ".json" in self.path or ".png" in self.path:
try:
response_file = JSON_GLOBAL_DICTIONARY[self.path.split("/")[-1]]
except:
print("Invalid json request:", self.path)
print(JSON_GLOBAL_DICTIONARY.keys())
self.send_error(HTTPStatus.NOT_FOUND, "File not found")
return
self.send_response(HTTPStatus.OK)
self.send_header("Content-Length", str(len(response_file)))
if ".b" in self.path:
self.send_header("Content-type", "application/octet-stream")
response_file = BytesIO(response_file)
elif "timeline.png" in self.path:
self.send_header("Content-type", "image/png")
else:
self.send_header("Content-type", "application/json")
self.send_header("Last-Modified", self.date_time_string(time.time()))
self.end_headers()
self.copyfile(response_file, self.wfile)
elif self.path in ["/", "/styles.css", "/index.html", "/logo.svg"]:
http.server.SimpleHTTPRequestHandler.do_GET(self)
else:
print("Invalid request:", self.path)
self.send_error(HTTPStatus.NOT_FOUND, "File not found")
class RocTCPServer(socketserver.TCPServer):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)
def run_server(drawinfo):
Handler = NoCacheHTTPRequestHandler
Handler.drawinfo = drawinfo
os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)),"ui/"))
try:
with RocTCPServer((IPAddr, PORT), Handler) as httpd:
httpd.serve_forever()
except KeyboardInterrupt:
pass
def fix_space(line):
line = line.replace(" ", SP)
line = line.replace("\t", SP * 4)
return line
def WebSocketserver(websocket, path):
data = websocket.recv()
cpp, ln, _ = data.split(":")
ln = int(ln)
HL, EMP = "highlight", ""
content = None
print("loading...")
try:
f = open(cpp, "r", errors="replace")
content = "".join(
'<li class="line_'
+ str(i)
+ str(HL if i == ln else EMP)
+ '">'
+ str(i).ljust(5)
+ fix_space(l)
+ "</li>"
for i, l in enumerate(f.readlines(), 1)
)
except FileNotFoundError:
content = cpp + " not found!"
websocket.send(content)
def run_websocket():
start_server = websockets.serve(WebSocketserver, IPAddr, WebSocketPort)
try:
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
except KeyboardInterrupt:
pass
def assign_ports(ports):
ps = [int(port) for port in ports.split(",")]
if ps[0] <= 5000 or ps[1] <= 5000:
print("Need to have port values > 5000")
sys.exit(1)
elif ps[0] == ps[1]:
print(
"Can not use the same port for both web server and websocket server: " + ps[0]
)
sys.exit(1)
global IPAddr, PORT, WebSocketPort
PORT, WebSocketPort = ps[0], ps[1]
def call_picture_callback(return_dict, drawinfo):
response, imagebytes = GeneratePIC(drawinfo)
return_dict["graph_options.json"] = response
@@ -291,11 +170,9 @@ def call_picture_callback(return_dict, drawinfo):
def view_trace(
args,
code,
dbnames,
att_filenames,
bDumpOnly,
se_time_begin,
gfxv,
drawinfo,
@@ -380,30 +257,13 @@ def view_trace(
for k, v in return_dict.items():
JSON_GLOBAL_DICTIONARY[k] = v
if bDumpOnly == False:
JSON_GLOBAL_DICTIONARY["live.json"] = Readable({"live": 1})
if args.ports:
assign_ports(args.ports)
print("serving at ports: {0},{1}".format(PORT, WebSocketPort))
try:
PROCS = [
Process(target=run_server, args=[drawinfo]),
Process(target=run_websocket),
]
for p in PROCS:
p.start()
for p in PROCS:
p.join()
except KeyboardInterrupt:
print("Exitting.")
else:
os.makedirs(trace_instance_name + "_ui/", exist_ok=True)
JSON_GLOBAL_DICTIONARY["live.json"] = Readable({"live": 0})
os.system(
"cp "
+ os.path.join(os.path.abspath(os.path.dirname(__file__)), "ui")
+ "/* " + trace_instance_name + "_ui/"
)
for k, v in JSON_GLOBAL_DICTIONARY.items():
with open(os.path.join(trace_instance_name+"_ui", k), "w" if ".json" in k else "wb") as f:
f.write(v.read())
os.makedirs(trace_instance_name + "_ui/", exist_ok=True)
JSON_GLOBAL_DICTIONARY["live.json"] = Readable({"live": 0})
os.system(
"cp "
+ os.path.join(os.path.abspath(os.path.dirname(__file__)), "ui")
+ "/* " + trace_instance_name + "_ui/"
)
for k, v in JSON_GLOBAL_DICTIONARY.items():
with open(os.path.join(trace_instance_name+"_ui", k), "w" if ".json" in k else "wb") as f:
f.write(v.read())