1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2023 CEA, EDF
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Lesser General Public License for more details.
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 from collections import defaultdict
27 def GetRepresentationOfTimeDelta(cls,endTime, startTime):
28 if endTime is None and startTime is None:
30 td = endTime - startTime
32 ts_of_td = time.gmtime(td.total_seconds())
33 return "{}.{:06d}".format(time.strftime("%H:%M:%S",ts_of_td),td.microseconds)
36 def MemRepr(cls,memInByte):
38 UNITS=["B","kB","MB","GB"]
41 for i in range( len(UNITS) ):
43 oss = "{:03d}".format( int( (remain/1024)*1000 ) )
44 oss = "{}.{} {}".format(m,oss,UNITS[i])
50 return "{} {}".format(m,UNITS[3])
53 self._measure_time_resolution_ms = None
54 self._cpu_mem_during_exec = None
55 self._start_exec_time = None
56 self._end_exec_time = None
57 self._start_input_time = None
58 self._end_input_time = None
59 self._start_output_time = None
60 self._end_output_time = None
62 self._input_hdd_mem = None
64 self._output_hdd_mem = None
65 self._start_pos_log = None
66 self._stop_pos_log = None
69 def measureTimeResolution(self):
70 return self._measure_time_resolution_ms
72 @measureTimeResolution.setter
73 def measureTimeResolution(self, value):
74 self._measure_time_resolution_ms = value
77 def tracePosStart(self):
78 return self._start_pos_log
81 def tracePosStart(self,value):
82 self._start_pos_log = value
85 def tracePosStop(self):
86 return self._stop_pos_log
89 def tracePosStop(self,value):
90 self._stop_pos_log = value
93 def CPUMemDuringExec(self):
94 return self._cpu_mem_during_exec
96 @CPUMemDuringExec.setter
97 def CPUMemDuringExec(self,value):
98 self._cpu_mem_during_exec = value
101 def CPUMemDuringExecStr(self):
102 cpu = self._cpu_mem_during_exec[::2]
103 mem_rss = self._cpu_mem_during_exec[1::2]
104 return [(a,ScriptExecInfo.MemRepr(b)) for a,b in self._cpu_mem_during_exec]
108 return self._input_mem
111 def inputMem(self,value):
112 self._input_mem = value
115 def inputMemStr(self):
116 return ScriptExecInfo.MemRepr( self.inputMem )
120 return self._output_mem
123 def outputMem(self,value):
124 self._output_mem = value
127 def outputMemStr(self):
128 return ScriptExecInfo.MemRepr( self.outputMem )
131 def inputHDDMem(self):
132 return self._input_hdd_mem
135 def inputHDDMem(self,value):
136 self._input_hdd_mem = value
139 def inputHDDMemStr(self):
140 if self._input_hdd_mem is None:
141 return "not computed"
142 return " ".join( [ ScriptExecInfo.MemRepr( elt.getSizeOfFileRead() ) for elt in self._input_hdd_mem] )
145 def outputHDDMem(self):
146 return self._output_hdd_mem
149 def outputHDDMem(self,value):
150 self._output_hdd_mem = value
153 def outputHDDMemStr(self):
154 if self._output_hdd_mem is None:
155 return "not computed"
156 return " ".join( [ ScriptExecInfo.MemRepr( elt.getSizeOfFileRead() ) for elt in self._output_hdd_mem] )
159 def startInputTime(self):
160 return self._start_input_time
162 @startInputTime.setter
163 def startInputTime(self,value):
164 self._start_input_time = value
167 def endInputTime(self):
168 return self._end_input_time
171 def endInputTime(self,value):
172 self._end_input_time = value
175 def startExecTime(self):
176 return self._start_exec_time
178 @startExecTime.setter
179 def startExecTime(self,value):
180 self._start_exec_time = value
183 def endExecTime(self):
184 return self._end_exec_time
187 def endExecTime(self,value):
188 self._end_exec_time = value
191 def startOutputTime(self):
192 return self._start_output_time
194 @startOutputTime.setter
195 def startOutputTime(self,value):
196 self._start_output_time = value
199 def endOutputTime(self):
200 return self._end_output_time
202 @endOutputTime.setter
203 def endOutputTime(self,value):
204 self._end_output_time = value
207 def execTimeStr(self):
208 return ScriptExecInfo.GetRepresentationOfTimeDelta(self.endExecTime,self.startExecTime)
211 def inputTimeStr(self):
212 return ScriptExecInfo.GetRepresentationOfTimeDelta(self.endInputTime,self.startInputTime)
215 def outputTimeStr(self):
216 return ScriptExecInfo.GetRepresentationOfTimeDelta(self.endOutputTime,self.startOutputTime)
219 return """start exec time = {self.startExecTime}
220 end exec time = {self.endExecTime}
221 exec_time = {self.execTimeStr}
222 Measure time resolution = {self.measureTimeResolution} ms
223 CPU and mem monitoring = {self.CPUMemDuringExecStr}
224 input unpickling and ev load from disk time = {self.inputTimeStr}
225 output serialization and ev write to disk time = {self.outputTimeStr}
226 input memory size before exec (MemoryPeak 2x) = {self.inputMemStr}
227 input memory size from HDD = {self.inputHDDMemStr}
228 output memory size after exec (MemoryPeak 2x) = {self.outputMemStr}
229 output memory size from HDD = {self.outputHDDMemStr}
230 Start position in log = {self.tracePosStart}
231 End position in log = {self.tracePosStop}""".format(**locals())
233 class ScriptExecInfoDeco:
234 def __init__(self, eff, father):
236 self._father = father
242 def __getitem__(self,i):
245 return self._eff.__str__()
247 return self._eff.__repr__()
249 with open(self.father.father.logfile,"rb") as f:
251 return cont[self._eff.tracePosStart:self._eff.tracePosStop].decode()
253 class ScriptInfoAbstract:
254 def __init__(self, scriptPtr):
255 self._node_name = scriptPtr.getName()
256 self._code = scriptPtr.getCode()
257 self._exec = [pickle.loads(elt.getObj()) for elt in scriptPtr.listOfExecs()]
265 return self._node_name
272 def code(self,value):
276 return len( self._exec )
278 def __getitem__(self,i):
282 return """name = {self.nodeName}\ncode = {self.code}\nexecs = {self.execs}""".format(**locals())
285 return """ScriptInfo \"{self.nodeName}\"""".format(**locals())
287 class ScriptInfoClt(ScriptInfoAbstract):
288 def __init__(self, scriptPtr):
289 self._node_name = scriptPtr.getName()
290 self._code = scriptPtr.getCode()
291 self._exec = [pickle.loads(elt.getObj()) for elt in scriptPtr.listOfExecs()]
293 class ScriptInfo(ScriptInfoAbstract):
294 def __init__(self, nodeName, code, execs):
295 self._node_name = nodeName
299 class ScriptInfoDeco:
300 def __init__(self, eff, father):
302 self._father = father
308 def __getitem__(self,i):
309 return ScriptExecInfoDeco( self._eff[i], self )
311 return self._eff.__len__()
313 return self._eff.__str__()
315 return self._eff.__repr__()
317 class ContainerLogInfoAbstract:
320 with open(self.logfile,"rb") as f:
326 return self._ns_entry
330 return self._log_file
333 return len( self._scripts )
335 def __getitem__(self,i):
336 return ScriptInfoDeco( self._scripts[i], self)
339 return """NS entry = {self.ns_entry} LogFile = {self.logfile}""".format(**locals())
341 class ContainerLogInfoClt(ContainerLogInfoAbstract):
342 def __init__(self,contLogPtr):
343 self._log_file = contLogPtr.getLogFile()
344 self._ns_entry = contLogPtr.getContainerEntryInNS()
345 self._scripts = [ScriptInfoClt(elt) for elt in contLogPtr.listOfScripts()]
347 class ContainerLogInfo(ContainerLogInfoAbstract):
348 def __init__(self, nsEntry, logFile, scripts):
349 self._log_file = logFile
350 self._ns_entry = nsEntry
351 self._scripts = scripts
353 from abc import ABC, abstractmethod
355 class InOutputObjVisitorAbstract(ABC):
361 self._cur_obj = ObjMemModel()
365 self._data.append( self._cur_obj )
368 def getSizeOfFileRead(self):
369 return sum( [elt.getSizeOfFileRead() for elt in self._data] )
374 def setHDDMem(self, v):
377 def setFileName(self, fileName):
384 class InOutputObjVisitorIter:
385 def __init__(self, visitor):
386 self._visitor = visitor
390 if self._current >= len(self._visitor._data):
393 ret = self._visitor._data[ self._current ]
397 class InOutputObjVisitor(InOutputObjVisitorAbstract):
402 return self.getSizeOfFileRead()
405 return InOutputObjVisitorIter(self)
407 class ObjMemModel(InOutputObjVisitorAbstract):
411 self._file_name = None
413 def setHDDMem(self, v):
417 def setFileName(self, fileName):
418 self._file_name = fileName
421 def getSizeOfFileRead(self):
422 if hasattr(self,"_data"):
423 return super().getSizeOfFileRead()
428 return self.getSizeOfFileRead()
430 class FakeObjVisitor:
431 def setHDDMem(self, v):
437 class InOutputObjVisitorCM:
438 def __init__(self, visitor):
439 self._visitor = visitor
442 r = self._visitor.enter()
445 return FakeObjVisitor()
446 def __exit__(self,exctype, exc, tb):
448 self._visitor.leave()
452 def __init__(self,i):
456 def __iadd__(self,delta):
460 def unserializeInt(structData, offset):
461 from ctypes import c_int
463 sz = c_int.from_buffer_copy( structData[int(offset):int(offset)+sz_of_cint] ).value
467 def unserializeString(structData,offset):
468 sz = unserializeInt(structData,offset)
469 ret = structData[int(offset):int(offset)+sz].decode()
473 def unserializeContainerScriptExecPerfLog(structData, offset):
475 sz = unserializeInt(structData,offset)
478 inst = pickle.loads( structData[int(offset):int(offset)+sz] )
482 def unserializeContainerScriptPerfLog(structData, offset):
483 name = unserializeString(structData,offset)
484 code = unserializeString(structData,offset)
485 numberOfSessions = unserializeInt(structData,offset)
487 for _ in range(numberOfSessions):
488 session = unserializeContainerScriptExecPerfLog(structData,offset)
489 sessions.append( session )
490 return ScriptInfo(name,code,sessions)
492 def unserializeContainerPerfLog(structData, offset):
493 nsEntry = unserializeString(structData,offset)
494 logFile = unserializeString(structData,offset)
496 nbScripts = unserializeInt(structData,offset)
497 for _ in range(nbScripts):
498 script = unserializeContainerScriptPerfLog(structData,offset)
499 scripts.append( script )
500 return ContainerLogInfo(nsEntry,logFile,scripts)
502 def unserializeLogManager(structData):
503 offset = OffsetType(0)
504 numberOfScripts = unserializeInt(structData,offset)
506 for _ in range(numberOfScripts):
507 containerPerfLogInst = unserializeContainerPerfLog(structData,offset)
508 logManagerInst.append( containerPerfLogInst )
509 if int(offset) != len(structData):
510 raise RuntimeError("Something went wrong during unserialization phase.")
511 return logManagerInst