|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: B T
Length: 69153 (0x10e21)
Types: TextFile
Names: »B«
└─⟦180fe333a⟧ Bits:30000405 8mm tape, Rational 1000, SW CATALOG, 10_20_0
└─⟦180fe333a⟧ Bits:30000537 8mm tape, Rational 1000, SW Catalog 10_20_0
└─⟦5cb1d1d7f⟧ »DATA«
└─⟦3b1ee7bd8⟧
└─⟦this⟧
with Type_Definitions, Time_Library_1, Time_Library_2, Read_Log;
with Report_Library, Clocks, Calendar, Text_Io;
with Simple_Paginated_Output, String_Pkg, Dynarray_Pkg, Heap_Sort;
with System;
------------------------
package body Profile_Pkg is
------------------------
use Type_Definitions; --| Global type declarations
-----------------
procedure Profile
( --| Performance Analyzer report generator
Log_File_Name : in Filename; --| The name of the log file
Report_File_Name : in
Filename --| The name of Output report file
) is
--| Overview
--| Profile is the Report Generator for the Ada Performance Analyzer
--| Its purpose is to report execution timing and performance
--| information about computer programs written in the Ada language that
--| have been instrumented by the Ada Source Instrumenter. Execution data
--| is dynamically recorded at runtime by the instrumented program in an
--| Execution Log File (ELF). Profile reads the information recorded in
--| the ELF and prepares a summarizes it in a meaningful format.
--|
--| The report file generated by Profile contains three reports:
--|
--| 1) Test Configuration Report
--| This report includes information necessary to correlate the
--| report with a specific test or execution of the target
--| Ada program. Specifically,
--| - the name of the program being analyzed
--| - the date and time the log file was created
--| - the name of the log file
--| - the date and time the report was created
--| - a test ID specified by the user
--|
--| 2) Net Execution Time Report
--| This report includes the "net" time spent in each program unit.
--| The time reported for each unit does not include time spent in
--| other program units called by that unit if they have been
--| instrumented by the Source Instrumenter.
--|
--| 3) Cumulative Execution Time Report
--| This report includes the "cumulative" time spent in each program
--| unit. The time reported for each unit includes all time spent in
--| that unit and all other program units called by that unit whether
--| or not the other program units have been instrumented by the
--| Source Instrumenter.
--|
--| 4) Call Summary Report
--| The Call Summary Report reports the the number of program
--| units called by each unit executed.
--|
--| Each of the reports includes the following information about each
--| program unit:
--|
--| 1) Compilation unit name
--|
--| 2) Program unit name
--|
--| 3) Program unit number - a unique ID assigned to each program unit
--| by the Source Instrumenter to allow for overloaded procedure
--| names. The same program unit number is printed in the listing
--| file generated by the Source Instrumenter.
--|
--| 4) The program unit type: Procedure, Function, Task, or Generic.
--|
--| 5) The total number of times the unit was executed.
--|
--| 6) The maximum, minimum, and average execution times for
--| a single execution of the unit
--|
--| 7) The total accumulated execution time for all executions
--| of the unit.
--|
--| 8) The percentage of the program's total execution time
--| spent in the unit.
--| Requires
--| Each Ada program unit about which information is to be recorded
--| by ProfileM, the Performance Analyzer Runtime Monitor (RTM), and
--| to be reported by ProfileR must have been instrumented by the Ada
--| Source Instrumenter prior to compilation, linking, and execution.
--| An Ada program unit is a procedure, function, task, or generic.
--| N/A: Errors, Raises, Modifies
-- Version : 0.20
-- Last Modified : 06/04/85
-- Author : Jeff England
-- Initial Release : 02/08/85
package New_Float_Io is new Text_Io.Float_Io (Float);
use Report_Library; --| Ada Testing and Analysis Tools
use Simple_Paginated_Output; --| Output writer uses Text_IO
use String_Pkg; --| String handling pkg for STRING_TYPEs
use Read_Log; --| Performs all input from the Execution Log File
--| for all Ada Testing and Analysis Tools
use Calendar; --| Predefined library package for dates and times
Tool_Version : constant String := "Profile 1.0 ";
--| The tool version number is inserted in the report title
--| and displayed at the user's console when Profile is executed
Format_Options : Options --| Formatting options for reports
:= (80, --| Characters Per Line
60, --| Page size
Profile_Tool, --| The tool name
Tool_Version); --| The tool version number
Report : Paginated_File_Handle; --| "handle" for output report
Program_Name : Ada_Name; --| Name of program under test
Test_Ident : Test_Identifier; --| Test ID assigned by user
Test_Time : Time; --| Time and date of test
Report_Line : String_Pkg.String_Type;
Overhead_Time : Calendar.Day_Duration := 0.00;
Blank_Line : constant String (1 .. 80) := (1 .. 80 => ' ');
Dashes : constant String (1 .. 80) := (1 .. 80 => '-');
type Sort_Keys is
( --| Specifies the sort order for reports
Total_Execution_Time, --| for Total Execution Times Report
Unit_Name --| for Net and Cumulative Execution Times Report
--| and Call Summary Report
);
type Time_Clocks is
record
Accum_Time :
Day_Duration; --| Total cumulative time (all execs)
Max_Time : Day_Duration; --| Maximum execution time (1 exec)
Min_Time : Day_Duration; --| Minimum execution time (1 exec)
Error : String (1 .. 2); --| Expected error in reported times
end record;
type Unit_Clocks is
record
--| records execution time for each unit
Unit_Id : Program_Unit_Unique_Identifier;
Nest : Natural; --| nesting level (recursion)
Max_Nest : Natural; --| maximum nesting level (recursion)
Execs : Natural; --| the number of times a executed
Last_Start : Time; --| last time this unit started
Sons : Natural; --| number of calls made by this unit
Grandsons : Natural; --| number of calls made by sons
Clock_Fault : Boolean; --| indicates a clock fault occured
Dangling_Unit :
Boolean; --| indicates whether execution ended
Net_Clock : Time_Clocks; --| net time spent in this unit
Cum_Clock : Time_Clocks; --| cum time spent in this unit
end record;
subtype Unit_Nums is Natural;
package Program_Clocks is new Dynarray_Pkg (Unit_Clocks);
Program_Clock : Program_Clocks.Darray;
--| The program clock is a dynamic array containing a
--| separate Unit_Clock for each Ada program unit
Program_Start_Time : Calendar.Time; --| Time of first "Entering_Unit"
Last_Time : Calendar.Time; --| Time of last "Exiting_Unit"
Total_Time : Day_Duration; --| Total program execution time
Number_Of_Units : Unit_Nums := 0; --| Total number of Ada program units
Error : String (1 .. 2); --| Expected error in reported times
Percent : String (1 .. 2); --| Percent of total execution time
------------------------
procedure Get_Unit_Clock
( --| Gets the Unit_Clock and the Program_Clock
--| Array index of the Unit_ID
Unit_Id : in Program_Unit_Unique_Identifier;
--| A unique ID assigned by the source instrumenter
Program_Clock : in out Program_Clocks.Darray;
--| A dynamic array with Net and Cum times for all units
Unit_Clock : in out Unit_Clocks;
--| The unit clock for Unit_ID
Unit_Num : out Unit_Nums
--| The array index into Program_Clock
) is
--| Effects
--| Searches the Program_Clock array for the Unit_Clock assigned to
--| Unit_ID. If a match is found then then the Unit_Clock and the
--| array index of Unit_Clock, Unit_Num, are returned. If no match
--| is found, i.e., this is the first occurrence of Unit_ID, then
--| a new Unit_Clock is created and added to the Program_Clock array.
--| The new Unit_Clock and the new Array_Index are then returned to
--| the calling program.
--| Requires
--| The Program_Clock array must have been previously created by the
--| calling program.
--| Modifies
--| If the Unit_Clock corresponding to Unit_ID is not arready in
--| the Program_Clock array, then it is added to the array and
--| Number_of_Units is incremented by 1.
--| N/A: Raises, Errors
use Program_Clocks; --| for Fetch, Equal, and Add_High
Found : Boolean := False;
begin
--| Search the Program_Clock array for the Unit_Clock
--| corresponding to this Unit_ID
for Array_Index in 1 .. Length (Program_Clock) loop
exit when Found;
Unit_Clock := Fetch (Program_Clock, Array_Index);
if Equal (Unit_Clock.Unit_Id.Enclosing_Unit_Identifier,
Unit_Id.Enclosing_Unit_Identifier) and
Unit_Clock.Unit_Id.Program_Unit_Number =
Unit_Id.Program_Unit_Number then
Found := True;
Unit_Num := Array_Index;
end if;
end loop;
if not Found then
--| Start a new clock for this unit
Unit_Clock.Unit_Id := Unit_Id;
Unit_Clock.Nest := 0;
Unit_Clock.Max_Nest := 0;
Unit_Clock.Execs := 0;
Unit_Clock.Sons := 0;
Unit_Clock.Grandsons := 0;
Unit_Clock.Clock_Fault := False;
Unit_Clock.Dangling_Unit := False;
Unit_Clock.Net_Clock.Accum_Time := 0.0;
Unit_Clock.Net_Clock.Max_Time := 0.0;
Unit_Clock.Net_Clock.Min_Time := 86399.0;
Unit_Clock.Net_Clock.Error := " ";
Unit_Clock.Cum_Clock.Accum_Time := 0.0;
Unit_Clock.Cum_Clock.Max_Time := 0.0;
Unit_Clock.Cum_Clock.Min_Time := 86399.0;
Unit_Clock.Cum_Clock.Error := " ";
--| Add the new Unit_Clock to the Program_Clock array
Add_High (Program_Clock, Unit_Clock);
--| Set the unit number for new unit clock
Unit_Num := Length (Program_Clock);
end if;
end Get_Unit_Clock;
------------------------------
procedure Update_Current_Clock
( --| Updates the unit clock for the
--| currently terminating unit
Current : in Clocks.Unit_Start_Times;
--| Starting time and stop watch for the current unit
Stop_Time : in Calendar.Time;
--| The ending time for this unit
Current_Unit_Clock : in out Unit_Clocks
--| The unit clock for Unit_ID
) is
--| Effects
--| This procedure updates the unit clock for the currently
--| terminating program unit. Net and cumulative
--| execution times for the current execution of the
--| unit is added to the accumulated net and cumulative execution
--| times for all executions of the unit. The net and cumulative
--| execution times for the current execution of the unit are
--| compared to the maximum and minimum times for all executions
--| of the unit and the program clock is updated with the overall
--| maximum and minimum times. In addition, the terminating unit's
--| sons and grandsons are added to total accumulated sons and
--| grandsons for all executions of the unit
--| Modifies
--| The unit clock for the current unit is updated with the current
--| times. The Program_Clock array is not modified.
--| N/A: Raises, Requires, Errors
use Time_Library_2; --| for Maximum, Minimum
use Calendar; --| for "+" and "-" of times and durations
use Clocks; --| for MORE_UNITS
Elapsed_Time : Calendar.Day_Duration;
Net_Time : Calendar.Day_Duration;
Previous : Clocks.Unit_Start_Times; --| Previous unit starting time
begin
--| Calculate the elapsed execution time for the current unit
Elapsed_Time := Stop_Time - Current.Start_Time;
--| Update the cum clock for the current unit. If the current
--| unit is the same as the previous unit then the unit is
--| recursive and its accumulated cum time should not be
--| updated until the top level exits.
if More_Units then
Previous := Previous_Unit;
if Current.Unit_Num /= Previous.Unit_Num then
Current_Unit_Clock.Cum_Clock.Accum_Time :=
Current_Unit_Clock.Cum_Clock.Accum_Time + Elapsed_Time;
end if;
else
Current_Unit_Clock.Cum_Clock.Accum_Time :=
Current_Unit_Clock.Cum_Clock.Accum_Time + Elapsed_Time;
end if;
Current_Unit_Clock.Cum_Clock.Max_Time :=
Maximum (Current_Unit_Clock.Cum_Clock.Max_Time, Elapsed_Time);
Current_Unit_Clock.Cum_Clock.Min_Time :=
Minimum (Current_Unit_Clock.Cum_Clock.Min_Time, Elapsed_Time);
--| Update the net clock for the current unit
if Current_Unit_Clock.Unit_Id.Unit_Type = Task_Type then
Net_Time := Stop_Time - Current.Start_Time;
else
Net_Time := Stop_Time - Current_Unit_Clock.Last_Start +
Current.Stop_Watch;
end if;
Current_Unit_Clock.Net_Clock.Accum_Time :=
Current_Unit_Clock.Net_Clock.Accum_Time + Net_Time;
Current_Unit_Clock.Net_Clock.Max_Time :=
Maximum (Current_Unit_Clock.Net_Clock.Max_Time, Net_Time);
Current_Unit_Clock.Net_Clock.Min_Time :=
Minimum (Current_Unit_Clock.Net_Clock.Min_Time, Net_Time);
--| Update the offspring for this unit
Current_Unit_Clock.Sons := Current_Unit_Clock.Sons + Current.Sons;
Current_Unit_Clock.Grandsons :=
Current_Unit_Clock.Grandsons + Current.Grandsons;
end Update_Current_Clock;
-----------------------
procedure Read_Log_File
( --| Read and process the log file data
Program_Clock : in out Program_Clocks.Darray;
--| A dynamic array with Net and Cum times for all units
Number_Of_Units : out
Unit_Nums; --| Total number of program units
Total_Time : out
Day_Duration --| Total program execution time
) is
--| Effects
--| Reads the timing and execution data stored in the log file.
--| Only Unit_Start and Unit_Stop log file keys are processed
--| by Profile. Breakpoints, and variable trace keys are ignored.
--| Unit_ID's are stored in a dynamic array and assigned a unit
--| number by the package Log_In. The unit number is also used
--| as an index into the Program_Clock for storing the Net and
--| cumulative execution times for each unit.
--| Algorithm
--| When a new unit begins execution:
--| - push starting time onto stack
--| - stop net clock for calling unit
--| - start net clock for this unit
--| When a unit ends execution:
--| - stop net clock for this unit
--| - calculate max and min net times for all executions of this unit
--| - add net time for current execution to the accumulated
--| net time for all executions of this unit
--| - pop starting time from the stack
--| - calculate cum execution time ( Stop_Time - Start_Time )
--| - calculate max and min cum times for all executions of this unit
--| - add cum time for current execution to the accumulated
--| cum time for all executions of this unit
--| N/A: Raises, Requires, Modifies, Errors
use Clocks;
use Program_Clocks; --| for Create, Store
Program_Started : Boolean := False;
Key : Logfile_Keys;
Unit_Num : Unit_Nums;
Unit_Id : Program_Unit_Unique_Identifier;
Start_Time : Calendar.Time;
Stop_Time : Calendar.Time;
Elapsed_Time : Calendar.Day_Duration;
Time_Of_Day : Calendar.Day_Duration;
Twenty_Four_Hours : constant Calendar.Day_Duration := 86400.00;
Time_Zero : Calendar.Day_Duration := 0.0;
Unit_Clock : Unit_Clocks;
Current_Unit_Clock : Unit_Clocks;
Previous_Unit_Clock : Unit_Clocks;
Current : Unit_Start_Times;
Previous : Unit_Start_Times;
Clock_Fault : Boolean;
First_Unit : Boolean;
Test_Date : Time;
--| This is initially set to the time of the
--| test with 0.00 seconds. If the test
--| begins on one day and ends on another
--| Test_Date is incremented by 24 hours.
begin
--| Create the dynamic clock structures for unit starting times
Create_Clocks;
--| Create a dynamic array of unit clocks to keep track of time
--| for each Ada program unit
Create (1, 20, --| Start with elements 1..20.
100, --| 100% of Add's are at high end of array.
20, --| Expand the array by 20% when necessary.
Program_Clock); --| The name of the array is Program_Clock.
--| Establish the date of the test. This date will be incremented
--| if a new time is less than the last recorded time, indicating
--| that execution of the target test program began before midnight
--| and ended after midnight.
Test_Date := Test_Time - Seconds (Test_Time);
Last_Time := Test_Time;
while not End_Of_Log loop
Get_Next_Key (Key);
case Key is
---------------
when Unit_Start =>
Get_Unit_Time (Unit_Id, Time_Of_Day);
Start_Time := Test_Date + Time_Of_Day;
if Start_Time < Last_Time then
Test_Date := Test_Date + Twenty_Four_Hours;
-- It's a new day
Start_Time := Test_Date + Time_Of_Day;
end if;
if not Program_Started then
Program_Start_Time := Start_Time;
Program_Started := True;
end if;
Last_Time := Start_Time;
Get_Unit_Clock (Unit_Id, Program_Clock,
Current_Unit_Clock, Unit_Num);
Current := (Unit_Num, Start_Time, Time_Zero, 0, 0);
Current_Unit_Clock.Nest := Current_Unit_Clock.Nest + 1;
if Current_Unit_Clock.Nest >
Current_Unit_Clock.Max_Nest then
Current_Unit_Clock.Max_Nest :=
Current_Unit_Clock.Nest;
end if;
Current_Unit_Clock.Execs :=
Current_Unit_Clock.Execs + 1;
--| If the current unit is not a task then stop the net clock
--| for the previous unit
if Unit_Id.Unit_Type /= Task_Type and More_Units then
Pause_Unit (Previous);
Previous_Unit_Clock :=
Fetch (Program_Clock, Previous.Unit_Num);
Elapsed_Time := Start_Time -
Previous_Unit_Clock.Last_Start;
Previous.Stop_Watch :=
Previous.Stop_Watch + Elapsed_Time;
Previous.Sons := Previous.Sons + 1;
Restart_Unit (Previous);
--| It is possible that the current unit has been called by
--| a task and that the previous unit has not really
--| stopped executing. If this is the case, then the current
--| unit will terminate out of sequence and generate a clock
--| fault. To insure that the net clock for the previous unit
--| is updated properly if a clock fault occurs, Last_Start
--| for the previous unit must be updated to the current time.
Previous_Unit_Clock.Last_Start := Start_Time;
Store (Program_Clock, Previous.Unit_Num,
Previous_Unit_Clock);
end if;
--| Start the net clock for the current unit
Current_Unit_Clock.Last_Start := Start_Time;
Store (Program_Clock, Current.Unit_Num,
Current_Unit_Clock);
Start_Unit (Unit_Id, Current);
--------------
when Unit_Stop =>
Get_Unit_Time (Unit_Id, Time_Of_Day);
Stop_Time := Test_Date + Time_Of_Day;
if Stop_Time < Last_Time then
Test_Date := Test_Date + Twenty_Four_Hours;
-- It's a new day
Stop_Time := Test_Date + Time_Of_Day;
end if;
Last_Time := Stop_Time;
Get_Unit_Clock (Unit_Id, Program_Clock,
Current_Unit_Clock, Unit_Num);
Current_Unit_Clock.Nest := Current_Unit_Clock.Nest - 1;
Stop_Unit (Unit_Num, Unit_Id, Current, Clock_Fault);
--| Check to see if a clock fault occurred. If so, then
--| clear the fault and set the clock fault flag for all
--| non-task program units that were activated after the
--| unit in which the fault occurred.
if Clock_Fault then
Current_Unit_Clock.Clock_Fault := True;
while More_Clock_Faults loop
Unit_Num := Next_Clock_Fault;
Unit_Clock := Fetch (Program_Clock, Unit_Num);
Unit_Clock.Clock_Fault := True;
Store (Program_Clock, Unit_Num, Unit_Clock);
end loop;
end if;
--| If a clock fault did not occur and the terminating unit is
--| not a task then restart the net clock for the previous unit
if not Clock_Fault and
Unit_Id.Unit_Type /= Task_Type then
if More_Units then
Pause_Unit (Previous);
Previous_Unit_Clock :=
Fetch (Program_Clock, Previous.Unit_Num);
Previous_Unit_Clock.Last_Start := Stop_Time;
Store (Program_Clock, Previous.Unit_Num,
Previous_Unit_Clock);
Previous.Grandsons :=
Previous.Grandsons +
Current.Grandsons + Current.Sons;
Restart_Unit (Previous);
end if;
end if;
--| Update Max, Min, and accumulated net and cum times
--| for the current program unit
Update_Current_Clock
(Current, Stop_Time, Current_Unit_Clock);
Store (Program_Clock, Current.Unit_Num,
Current_Unit_Clock);
--------------------
when Timing_Overhead =>
Overhead_Time := Accumulated_Overhead;
-----------
when others =>
Flush_Logfile_Record (Key);
end case;
end loop;
--| Check to see if there are any unterminated (dangling) program units
--| left in the dynamic clock structures. If so, they must be terminated
--| and their clocks must be updated. Any tasks that are left in the
--| structure are assumed to still be active and are terminated as of
--| the last time recorded. For non-task program units, only the last
--| unit started is assumed to still be active. Other program units
--| must be "restarted" instantaneously as of the last time recorded
--| and then stopped again at the same time. This will force the net
--| clock to be updated properly with only the time remaining on
--| Current.Stop_Watch.
First_Unit := True;
while More_Tasks or More_Units loop
if More_Tasks then
Current := Dangling_Task;
else
Current := Dangling_Unit;
end if;
Current_Unit_Clock := Fetch (Program_Clock, Current.Unit_Num);
if Current_Unit_Clock.Unit_Id.Unit_Type /= Task_Type and
not First_Unit then
Current_Unit_Clock.Last_Start := Last_Time;
end if;
Update_Current_Clock (Current, Last_Time, Current_Unit_Clock);
Current_Unit_Clock.Dangling_Unit := True;
Store (Program_Clock, Current.Unit_Num, Current_Unit_Clock);
if Current_Unit_Clock.Unit_Id.Unit_Type /= Task_Type then
First_Unit := False;
end if;
end loop;
--| Calculate total program execution time
Total_Time := Last_Time - Program_Start_Time;
--| The dynamic clock structures are no longer needed. Destroy them.
Clocks.Destroy_Clocks;
--| Calculate the total number of program units
Number_Of_Units := Length (Program_Clock);
end Read_Log_File;
--------------
procedure Sort ( --| Sort the Program Clock Array
Program_Clock : in out Program_Clocks.Darray;
Size : in Natural;
Sort_Key : in Sort_Keys) is
--| Effects
--| This procedure sorts the Program Clock dynamic array. The
--| array is sorted by cumulative times in descending order.
--| If Sort_Key = Total_Execution_Time then the array is sorted in
--| descending order by total accumulated cumulative execution time.
--| If Sort_Key = Unit_Name then the array is sorted in Ascending
--| order by program unit name, compilation unit name, and program
--| unit number.
--| Modifies
--| The elements of Program_Clock are reordered according to the
--| specified sort key.
--| N/A: Raises, Requires, Errors
use Program_Clocks;
type Times is array (Integer range <>) of Unit_Clocks;
Execution_Times : Times (1 .. Size);
--------------
function Order ( --| Return true if Left <= Right in specified order
Left : in Unit_Clocks;
Right : in Unit_Clocks) return Boolean is
--| Effects
--| Returns true if the Left element is precedes the right element
--| in the desired sort order. This procedure provides the "<="
--| function used by the generic procedure Heap_Sort.
--|
--| When the sort key is Total_Execution_Time then the order is
--| 1) Total accumulated cumulative execution time - descending
--| 2) Program unit name (fully qualified) - ascending
--| 3) Program unit number - ascending
--| When the sort key is Unit_Name then the order is
--| 1) Program unit name (fully qualified) - ascending
--| 2) Program unit number - ascending
--| 3) Total accumulated cumulative execution time - descending
--| N/A: Raises, Requires, Modifies, Errors
use Calendar; --| for ">="
Left_Name :
Ada_Name; --| Temporary variable for program unit name
Right_Name :
Ada_Name; --| Temporary variable for program unit name
begin
case Sort_Key is
when Total_Execution_Time =>
if Left.Cum_Clock.Accum_Time =
Right.Cum_Clock.Accum_Time then
Find_Unit_Name (Left.Unit_Id, Left_Name);
Find_Unit_Name (Right.Unit_Id, Right_Name);
if Value (Left_Name) = Value (Right_Name) then
return Left.Unit_Id.Program_Unit_Number <=
Right.Unit_Id.Program_Unit_Number;
else
return Value (Left_Name) <= Value (Right_Name);
end if;
else
return Left.Cum_Clock.Accum_Time >=
Right.Cum_Clock.Accum_Time;
end if;
when Unit_Name =>
Find_Unit_Name (Left.Unit_Id, Left_Name);
Find_Unit_Name (Right.Unit_Id, Right_Name);
if Value (Left_Name) = Value (Right_Name) then
return Left.Unit_Id.Program_Unit_Number <=
Right.Unit_Id.Program_Unit_Number;
else
return Value (Left_Name) <= Value (Right_Name);
end if;
end case;
end Order;
procedure Sort is new Heap_Sort
(Unit_Clocks, Order, Integer, Times);
-------------
begin
-- Sort
--| Build an array of accumulated times and Program_Clock
--| dynamic array indices.
for I in Execution_Times'Range loop
Execution_Times (I) := Fetch (Program_Clock, I);
end loop;
Sort (Execution_Times);
--| Sort the array in descending order
--| Reorder the elements of Program_Clock to correspond to the new
--| ordering of array indices.
for I in Execution_Times'Range loop
Store (Program_Clock, I, Execution_Times (I));
end loop;
end Sort;
----------------------------------
procedure Calculate_Expected_Error
( --| Calculate Expected error in
--| recorded times
Program_Clock : in out Program_Clocks.Darray;
--| A dynamic array with net and cum times for all units
Number_Of_Units : in
Unit_Nums --| The total number of program units
) is
--| Effects
--|
--| This procedure calculates an expected error in the recorded
--| time for a program unit as a percentage of both "net" and
--| "cum"execution times for each program unit in the
--| program clock array. Expected errors are stored as two
--| character strings in the appropriate unit clock for each
--| program unit for later use by the report generation procedures.
--|
--| If no faults occurred then an expected error in the range 0..99
--| is calculated as a function of the number of times a unit executed
--| its execution time as a percentage of total program execution
--| time, and the total number of clock periods the program under test
--| executed.
--| Errors
--| If a clock fault occurred during execution of a program unit or
--| if the program unit did not terminate normally, then it is not
--| possible to calculate an expected error. When this occurs then
--| flags are inserted into the expected error to indicate which
--| fault occurred. A " C" indicates a clock fault occurred. A " D"
--| indicates the unit was a "dangling" unit, i.e., it did not
--| terminate normally. A "CD" indicates that both faults occurred.
--| Modifies
--| Program_Clock.Net_Clock.Error and Program_Clock.Net_Clock.Error
--| are set to the appropriate expected error.
--| N/A: Raises, Errors,
use Program_Clocks; --| for Fetch and Store
use Time_Library_2; --| for Minimum and Maximum
Unit_Clock : Unit_Clocks;
Max_Error : Natural;
Error : Integer range 0 .. 130;
type Errors is
record
Percent_Of_Total : Float range 0.0 .. 100.0;
Fifty_Periods : Integer range 0 .. 130;
One_Hundred_Periods : Integer range 0 .. 73;
Five_Hundred_Periods : Integer range 0 .. 50;
Five_Thousand_Periods : Integer range 0 .. 20;
end record;
type Expected_Errors is array (1 .. 31) of Errors;
Expected_Error : Expected_Errors :=
((1.0, 130, 73, 50, 20), (2.0, 82, 52, 27, 11),
(3.0, 54, 46, 17, 8), (4.0, 47, 40, 13, 7),
(5.0, 43, 35, 11, 6), (6.0, 41, 31, 10, 5),
(7.0, 38, 28, 9, 4), (8.0, 36, 26, 9, 4), (9.0, 34, 25, 8, 3),
(10.0, 32, 23, 8, 3), (11.0, 31, 22, 8, 3),
(12.0, 30, 20, 7, 3), (13.0, 28, 18, 7, 3),
(14.0, 27, 17, 7, 2), (15.0, 26, 16, 6, 2),
(16.0, 24, 15, 6, 2), (17.0, 23, 13, 6, 2),
(18.0, 22, 12, 6, 2), (19.0, 21, 11, 5, 2),
(20.0, 20, 10, 5, 2), (25.0, 17, 8, 5, 2), (30.0, 14, 7, 4, 2),
(35.0, 12, 6, 4, 2), (40.0, 11, 6, 4, 2), (45.0, 10, 6, 3, 2),
(50.0, 8, 5, 3, 1), (60.0, 8, 5, 3, 1), (70.0, 7, 5, 2, 1),
(80.0, 7, 5, 2, 1), (90.0, 6, 5, 1, 1), (100.0, 6, 4, 1, 1));
Error_Range : Integer range Expected_Error'Range;
Total_Program_Time : Float; --| Total program execution time
Percent_Of_Total :
Float; --| Percent of total program execution time
Clock_Tick : Float; --| System.Tick converted to float
Periods : Natural;
--| Number of clock periods program executed
-------------------------
function Percent_Of_Error ( --| Return Expected error as a percent
--| of program unit execution time
Activations : in
Natural; --| Number of times a unit was activated
Unit_Time : in
Calendar.Day_Duration --| Total unit execution time
) return String is
--| Effects
--| This function performs a table lookup if the expected error
--| in the recorded total execution time for a program unit.
--| have been calculated as a function of:
--|
--| 1) total program execution time
--| 2) total program unit execution time
--| 3) the number of times the program unit executed
--| 4) the number of clock periods the test program executed
--| N/A: Raises, Modifies, Errors
Execution_Time : Float; --| Program unit execution time
begin
-- Percent_of_Error
if Total_Program_Time = 0.0 or
Unit_Time = 0.0 or Activations = 0 then
return "**";
else
Execution_Time := Float (Unit_Time);
Percent_Of_Total := Execution_Time /
Total_Program_Time * 100.0;
--| The maximum possible error is equal to the basic clock period
--| times the number of times the unit executed
Max_Error := Integer
((Float (Activations) *
Clock_Tick * 100.0) / Execution_Time);
Error_Range := Expected_Error'Last;
for I in 1 .. Expected_Error'Last - 1 loop
if Percent_Of_Total <
(Expected_Error (I).Percent_Of_Total +
Expected_Error (I + 1).Percent_Of_Total) / 2.0 then
Error_Range := I;
exit;
end if;
end loop;
case Periods is
when 5000 =>
Error := Expected_Error (Error_Range).
Five_Thousand_Periods;
when 500 =>
Error := Expected_Error (Error_Range).
Five_Hundred_Periods;
when 100 =>
Error := Expected_Error (Error_Range).
One_Hundred_Periods;
when others =>
Error := Expected_Error (Error_Range).Fifty_Periods;
end case;
--| The calculated error cannot be greater than Max_Error.
--| If it is then adjust it.
if Error > Max_Error then
Error := Max_Error;
end if;
--| Do not return a string greater than 2 characters
if Error >= 100 then
return "**";
else
return String_Of (Error, 2);
end if;
end if;
end Percent_Of_Error;
begin
-- Calculate_Expected_Error
--| To simplify mathematical calculations, total program execution
--| time and System.Tick are converted to floating point types.
Total_Program_Time := Float (Total_Time);
--| Total program execution time
Clock_Tick := Float (System.Tick);
--| Calculate the number of clock periods in total program execution
--| time and then normalize Periods to 50, 100, 500 or 5000
Periods := Integer (Total_Program_Time / Clock_Tick);
if Periods in 0 .. 74 then
Periods := 50;
elsif Periods in 75 .. 299 then
Periods := 100;
elsif Periods in 300 .. 2749 then
Periods := 500;
else
Periods := 5000;
end if;
for Unit_Num in 1 .. Number_Of_Units loop
--| Fetch the appropriate unit clock from the program clock array
Unit_Clock := Fetch (Program_Clock, Unit_Num);
--| Never happens:
--|
--| 1. MAXIMUM times can never be = zero if ACCUMULATED time is > zero
--| 2. MAXIMIM times can never be > than ACCUMULATED times
--| 3. MINIMUM times can never be > than MAXIMUM times
--| 4. NET times can never be > than CUM times
--|
--| If any of these conditions exists due to round off errors
--| then the times must be adjusted
if Unit_Clock.Net_Clock.Accum_Time > 0.00 then
Unit_Clock.Net_Clock.Max_Time :=
Maximum (Unit_Clock.Net_Clock.Max_Time, 0.01);
Unit_Clock.Cum_Clock.Max_Time :=
Maximum (Unit_Clock.Cum_Clock.Max_Time, 0.01);
end if;
Unit_Clock.Net_Clock.Max_Time :=
Minimum (Unit_Clock.Net_Clock.Max_Time,
Unit_Clock.Net_Clock.Accum_Time);
Unit_Clock.Cum_Clock.Max_Time :=
Minimum (Unit_Clock.Cum_Clock.Max_Time,
Unit_Clock.Cum_Clock.Accum_Time);
Unit_Clock.Net_Clock.Min_Time :=
Minimum (Unit_Clock.Net_Clock.Min_Time,
Unit_Clock.Net_Clock.Max_Time);
Unit_Clock.Cum_Clock.Min_Time :=
Minimum (Unit_Clock.Cum_Clock.Min_Time,
Unit_Clock.Cum_Clock.Max_Time);
Unit_Clock.Net_Clock.Accum_Time :=
Minimum (Unit_Clock.Net_Clock.Accum_Time,
Unit_Clock.Cum_Clock.Accum_Time);
Unit_Clock.Net_Clock.Min_Time :=
Minimum (Unit_Clock.Net_Clock.Min_Time,
Unit_Clock.Cum_Clock.Min_Time);
Unit_Clock.Net_Clock.Max_Time :=
Minimum (Unit_Clock.Net_Clock.Max_Time,
Unit_Clock.Cum_Clock.Max_Time);
--| Check to see if a clock fault occurred during execution of
--| this unit. If so, insert a "C" into the expecred error
--| for both the net and cum clocks.
if Unit_Clock.Clock_Fault then
Unit_Clock.Net_Clock.Error (1) := 'C';
Unit_Clock.Cum_Clock.Error (1) := 'C';
end if;
--| Check to see if a this unit was left dangling at program
--| termination. If so, insert a "D" into the expected error
--| for both the net and cum clocks.
if Unit_Clock.Dangling_Unit then
Unit_Clock.Net_Clock.Error (2) := 'D';
Unit_Clock.Cum_Clock.Error (2) := 'D';
end if;
--| If no faults occurred then calculate an expected error in
--| the range 0..99 as a function of the number of times the unit
--| executed, the unit's execution time as a percentage of
--| total program execution time, and the total number of clock
--| periods the program under test executed.
if not Unit_Clock.Clock_Fault and
not Unit_Clock.Dangling_Unit then
Unit_Clock.Net_Clock.Error :=
Percent_Of_Error (Unit_Clock.Execs + Unit_Clock.Sons,
Unit_Clock.Net_Clock.Accum_Time);
Unit_Clock.Cum_Clock.Error :=
Percent_Of_Error (Unit_Clock.Execs,
Unit_Clock.Cum_Clock.Accum_Time);
end if;
--| Pretty it up a bit. If the confidence level contains only
--| one character then right justify it.
if Unit_Clock.Net_Clock.Error (2) = ' ' then
Unit_Clock.Net_Clock.Error :=
" " & Unit_Clock.Net_Clock.Error (1 .. 1);
Unit_Clock.Cum_Clock.Error := Unit_Clock.Net_Clock.Error;
end if;
--| Put the updated clock back into the array
Store (Program_Clock, Unit_Num, Unit_Clock);
end loop;
end Calculate_Expected_Error;
------------------------
function New_Report_Line ( --| Create a new report line
Unit_Id : in Program_Unit_Unique_Identifier
--| Program unit for this line
) return String_Type is
Report_Line : String_Type;
Unit_Name : Ada_Name;
Program_Unit_Number : String (1 .. 3);
--| Effects
--| Starts a new report line. Each of the execution reports
--| begins with the same information in the same report columns.
--| This function starts a new report line that contains the
--| following information:
--|
--| 1) Col 1-29: Fully qualified Program Unit Name
--| 2) Col 31-33: Program Unit Number
--| N/A: Raises, Requires, Modifies, Errors
Index : Positive;
begin
--| Start a new report line
Report_Line := Create (Blank_Line);
--| Get the program unit name from Read_Log
Find_Unit_Name (Unit_Id, Unit_Name);
--| If the program unit name is longer than the report
--| field, 29 characters, then output pieces of it until
--| it fits within the field
while Length (Unit_Name) > 29 loop
--| If the current section of the name is qualified then break
--| the name at the last qualifier. Otherwise break it after
--| the 29th character
for I in reverse 1 .. 29 loop
Index := I;
exit when Fetch (Unit_Name, I) = '.';
end loop;
if Index = 1 then
Index := 29;
end if;
--| Insert the first section of characters
Report_Line := Replace (Report_Line,
Substr (Unit_Name, 1, Index), 1);
--| Output the current line
Put_Line (Report, Report_Line);
--| Start a new line
Report_Line := Create (Blank_Line);
--| Indent the remainder of the name 2 spcaes
Unit_Name := " " & Substr (Unit_Name, Index + 1,
Length (Unit_Name) - Index);
end loop;
--| Insert the program unit name at character position 1
Report_Line := Replace (Report_Line, Unit_Name, 1);
--| Get the program unit number from the unit ID and convert
--| it to a string of length 3
Program_Unit_Number := String_Of (Unit_Id.Program_Unit_Number, 3);
--| Put leading zeros on the program unit number to pretty it up
for Digit in 1 .. 3 loop
if Program_Unit_Number (Digit) = ' ' then
Program_Unit_Number (Digit) := '0';
end if;
end loop;
--| Insert the program unit into character position 31
Report_Line := Replace (Report_Line, Program_Unit_Number, 31);
return Report_Line;
end New_Report_Line;
-------------------------
function Percent_Of_Total ( --| Return the percent of total execution time
Total_Time : in Day_Duration;
--| Total Execution time for the program
Partial_Time : in Day_Duration
--| Total Execution time for the program unit
) return String is
--| Effects
--| Returns ( Partial_Time / Total_Time ) * 100. The percentage is
--| returned a two character string.
--| If Percent in 0.0..94.99 then returns "nn" where nn is the percentage
--| If Percent in 95.0 .. 99.99 then returns " *"
--| If Percent >= 100.0 then returns "**"
--| N/A: Raises, Modifies, Errors
Percent : Float;
Pct : Integer;
begin
if Partial_Time = 0.0 then
return " 0";
else
Percent := Float (Partial_Time) / Float (Total_Time) * 100.0;
if Percent >= 95.50 and Percent <= 100.00 then
return " *";
elsif Percent < 95.50 then
return String_Of (Integer (Percent), 2);
else
return "**";
end if;
end if;
end Percent_Of_Total;
-------------------------------------
procedure Print_Total_Execution_Times
( --| Print Total Execution Time Report
Program_Clock : in Program_Clocks.Darray;
--| A dynamic array with Net and Cum times for all units
Number_Of_Units : in
Unit_Nums; --| Total number of program units
Total_Time : in
Day_Duration --| Total program execution time
) is
use Program_Clocks; --| for Fetch
use Time_Library_1; --| for Wall_Clock_of
Total_Times_Title : constant String := "TOTAL EXECUTION TIMES";
Total_Times_Columns : constant String :=
" UNIT NAME " & " PU# T # EXEC NET " &
" %T %E CUMULATIVE %T %E";
Total_Times_Dashes : constant String :=
"---------------------------" & "-- --- - ------ -----------" &
" -- -- ----------- -- --";
Unit_Clock : Unit_Clocks;
begin
String_Pkg.Mark;
--| Add an execution time summary to the test configuration report
Skip_Line (Report, 2);
Put_Line (Report, Dashes);
Skip_Line (Report, 3);
Put_Line (Report,
Center ("=========================================", 80));
Put_Line
(Report,
Center ("Test Program Start Time: " &
Wall_Clock_Of (Seconds (Program_Start_Time)), 80));
Put_Line
(Report,
Center
("Test Program Stop Time: " &
Wall_Clock_Of (Seconds (Last_Time + Overhead_Time)), 80));
Put_Line (Report,
Center ("Total Test Execution Time: " &
Wall_Clock_Of (Total_Time + Overhead_Time), 80));
Put_Line (Report, Center ("Estimated Profile Overhead: " &
Wall_Clock_Of (Overhead_Time), 80));
Put_Line (Report, Center ("Adjusted Test Execution Time: " &
Wall_Clock_Of (Total_Time), 80));
Put_Line (Report,
Center ("=========================================", 80));
--| Summarize the execution time on the current output device to let
--| the user know the program is still running.
Text_Io.Put ("Test Program Start Time: ");
Text_Io.Put_Line (Wall_Clock_Of (Seconds (Program_Start_Time)));
Text_Io.Put ("Test Program Stop Time: ");
Text_Io.Put_Line (Wall_Clock_Of
(Seconds (Last_Time + Overhead_Time)));
Text_Io.Put ("Total Test Execution Time: ");
Text_Io.Put_Line (Wall_Clock_Of (Total_Time + Overhead_Time));
if Overhead_Time /= 0.00 then
Text_Io.Put_Line ("Estimated Profile Overhead: " &
Wall_Clock_Of (Overhead_Time));
Text_Io.Put_Line ("Adjusted Test Execution Time: " &
Wall_Clock_Of (Total_Time));
else
--| If no estimated overhead was found in the log file then
--| the program under test must have terminated abnormally
Text_Io.New_Line;
Text_Io.Put (Value (Program_Name));
Text_Io.Put_Line (" terminated abnormally");
end if;
Put_Page (Report);
--| Start the total execution times report on a new page
--| Set up a new header for the report
Set_Header (Report, 4, Center
(Total_Times_Title, Format_Options.Cpl));
Set_Header (Report, 6, Make_Persistent (Total_Times_Columns));
Set_Header (Report, 7, Make_Persistent (Total_Times_Dashes));
--| Print the timing data for each program unit
for Unit_Num in 1 .. Number_Of_Units loop
Unit_Clock := Fetch (Program_Clock, Unit_Num);
Report_Line := New_Report_Line (Unit_Clock.Unit_Id);
case Unit_Clock.Unit_Id.Unit_Type is
when Procedure_Type =>
Report_Line := Replace (Report_Line, "P", 35);
when Function_Type =>
Report_Line := Replace (Report_Line, "F", 35);
when Task_Type =>
Report_Line := Replace (Report_Line, "T", 35);
when Generic_Type =>
Report_Line := Replace (Report_Line, "G", 35);
when Package_Type =>
Report_Line := Replace (Report_Line, "K", 35);
end case;
Report_Line := Replace (Report_Line,
String_Of (Unit_Clock.Execs, 7), 36);
Report_Line :=
Replace
(Report_Line,
Wall_Clock_Of (Unit_Clock.Net_Clock.Accum_Time), 44);
Percent := Percent_Of_Total (Total_Time,
Unit_Clock.Net_Clock.Accum_Time);
Report_Line := Replace (Report_Line, Percent, 56);
Report_Line := Replace (Report_Line,
Unit_Clock.Net_Clock.Error, 59);
Report_Line :=
Replace
(Report_Line,
Wall_Clock_Of (Unit_Clock.Cum_Clock.Accum_Time), 63);
Percent := Percent_Of_Total (Total_Time,
Unit_Clock.Cum_Clock.Accum_Time);
Report_Line := Replace (Report_Line, Percent, 75);
Report_Line := Replace (Report_Line,
Unit_Clock.Cum_Clock.Error, 78);
Put_Line (Report, Report_Line);
end loop;
String_Pkg.Release;
end Print_Total_Execution_Times;
--------------------------
procedure Print_Unit_Stats
( --| Print statistics for one program unit
Unit_Id : in Program_Unit_Unique_Identifier;
--| A Unique ID assigned by the source instrumenter
Executions : in
Natural; --| Number of times unit executed
Time_Clock : in
Time_Clocks --| Cum, Max, and Min for this unit
) is
--| Effects
--| This procedure prints the runtime statistics for one program
--| unit. The same procedure is used for printing unit statistics
--| for both "Net Execution Times" and Cumulative Execution Times."
--| The following information is printed for each program unit:
--|
--| 1) Compilation unit name
--| 2) Program unit name
--| 3) Program unit number assigned by the Source Instrumenter
--| 4) The program unit type: Procedure, Function, Task, Generic, Package
--| 5) The total number of times the unit was executed.
--| 6) The max, min, and average execution times for each execution
--| 7) The total accumulated execution time for the unit
--| 8) The percentage of total program execution time
--| N/A: Raises, Requires, Modifies, Errors
use Time_Library_1; --| for Wall_Clock_of
Average_Time :
Day_Duration; --| The average execution of a program unit
begin
String_Pkg.Mark;
Report_Line := New_Report_Line (Unit_Id);
Report_Line := Replace (Report_Line, String_Of (Executions, 7), 34);
Report_Line := Replace (Report_Line,
Wall_Clock_Of (Time_Clock.Max_Time), 42);
Report_Line := Replace (Report_Line,
Wall_Clock_Of (Time_Clock.Min_Time), 54);
Average_Time := Day_Duration (Float (Time_Clock.Accum_Time) /
Float (Executions));
Report_Line := Replace (Report_Line,
Wall_Clock_Of (Average_Time), 66);
Report_Line := Replace (Report_Line, Time_Clock.Error, 78);
Put_Line (Report, Report_Line);
String_Pkg.Release;
end Print_Unit_Stats;
-------------------------------------
procedure Print_Net_Execution_Times
( --| Print Net Execution Times
Program_Clock : in Program_Clocks.Darray;
--| A dynamic array with Net and Cum times for all units
Number_Of_Units : in Unit_Nums
--| The total number of program units
) is
use Program_Clocks; --| for Fetch
Net_Report_Title : constant String := "NET EXECUTION TIMES";
Max_Min_Columns : constant String :=
" UNIT NAME P" &
"U# # EXEC MAXIMUM MINIMUM" & " AVERAGE %E";
Max_Min_Dashes : constant String :=
"----------------------------- -" &
"-- ------ ----------- ---------" & "-- ----------- --";
Unit_Clock : Unit_Clocks;
begin
Put_Page (Report);
-- Start the report on a new page
Set_Header (Report, 4, Center
(Net_Report_Title, Format_Options.Cpl));
Set_Header (Report, 6, Make_Persistent (Max_Min_Columns));
Set_Header (Report, 7, Make_Persistent (Max_Min_Dashes));
for Unit_Num in 1 .. Number_Of_Units loop
Unit_Clock := Fetch (Program_Clock, Unit_Num);
Print_Unit_Stats (Unit_Clock.Unit_Id, Unit_Clock.Execs,
Unit_Clock.Net_Clock);
end loop;
end Print_Net_Execution_Times;
-------------------------------------
procedure Print_Cum_Execution_Times
( --| Print Cumulative Execution Times
Program_Clock : in Program_Clocks.Darray;
--| A dynamic array with Net and Cum times for all units
Number_Of_Units : in Unit_Nums
--| The total number of program units
) is
use Program_Clocks; --| for Fetch
Cum_Report_Title : constant String := "CUMULATIVE EXECUTION TIMES";
Unit_Clock : Unit_Clocks;
begin
Put_Page (Report);
-- Start the report on a new page
Set_Header (Report, 4, Center
(Cum_Report_Title, Format_Options.Cpl));
for Unit_Num in 1 .. Number_Of_Units loop
Unit_Clock := Fetch (Program_Clock, Unit_Num);
Print_Unit_Stats (Unit_Clock.Unit_Id, Unit_Clock.Execs,
Unit_Clock.Cum_Clock);
end loop;
end Print_Cum_Execution_Times;
-----------------------------------
procedure Print_Call_Summary_Report
( --| Print a summary of units called
Program_Clock : in Program_Clocks.Darray;
--| A dynamic array with Net and Cum times for all units
Number_Of_Units : in Unit_Nums
--| The total number of program units
) is
use Program_Clocks; --| for Fetch
Unit_Clock : Unit_Clocks;
Call_Report_Columns : constant String :=
" UNIT NAME " & " PU# T EXECS ABEND M" &
"AX RL SONS GRANDSONS";
Call_Report_Dashes : constant String :=
"---------------------------" & "-- --- - ------- ------- --" &
"----- --------- ---------";
begin
String_Pkg.Mark;
Put_Page (Report);
--| Start the total execution times report on a new page
--| Set up a new header for the report
Set_Header (Report, 4,
Center ("CALL SUMMARY REPORT", Format_Options.Cpl));
Set_Header (Report, 6, Call_Report_Columns);
Set_Header (Report, 7, Call_Report_Dashes);
for Unit_Num in 1 .. Number_Of_Units loop
Unit_Clock := Fetch (Program_Clock, Unit_Num);
Report_Line := New_Report_Line (Unit_Clock.Unit_Id);
case Unit_Clock.Unit_Id.Unit_Type is
when Procedure_Type =>
Report_Line := Replace (Report_Line, "P", 35);
when Function_Type =>
Report_Line := Replace (Report_Line, "F", 35);
when Task_Type =>
Report_Line := Replace (Report_Line, "T", 35);
when Generic_Type =>
Report_Line := Replace (Report_Line, "G", 35);
when Package_Type =>
Report_Line := Replace (Report_Line, "K", 35);
end case;
Report_Line := Replace (Report_Line,
String_Of (Unit_Clock.Execs, 8), 36);
Report_Line := Replace (Report_Line,
String_Of (Unit_Clock.Nest, 8), 44);
Report_Line := Replace (Report_Line,
String_Of (Unit_Clock.Max_Nest, 8), 52);
--| Tasks never have sons or grandsons. Therefore, if the unit is
--| a task then do not print the sons or grandsons. For all other
--| units they should be printed.
if Unit_Clock.Unit_Id.Unit_Type = Task_Type then
Report_Line := Replace (Report_Line, "0", 69);
Report_Line := Replace (Report_Line, "0", 79);
else
Report_Line := Replace (Report_Line,
String_Of (Unit_Clock.Sons, 9), 61);
Report_Line :=
Replace (Report_Line,
String_Of (Unit_Clock.Grandsons, 9), 71);
end if;
Put_Line (Report, Report_Line);
end loop;
String_Pkg.Release;
end Print_Call_Summary_Report;
-------------------------------
begin
-- Profile Main Program
--| Identify the tool name and version number
Text_Io.New_Line;
Text_Io.Put_Line (Tool_Version & "Ada Performance Analyzer");
--| Open the log file and get the test configuration data
Open_Log (Log_File_Name, Program_Name, Test_Ident, Test_Time);
if Timing_Data then
--| Display the Test Configuration data on the current output device
--| and query the user as to whether he/she wishes to continue
--| processing the log file.
Put_Test_Configuration_Data (Program_Name, Test_Time, Test_Ident);
if Query ("Do you wish to continue (Y/N)? ") then
--| Open the report file and set up the report formatting options
Open_Report_File (Report, Report_File_Name, Format_Options);
--| Print the Test Configuration Report
Print_Test_Configuration_Report
(Report, Program_Name, Log_File_Name, Test_Time, Test_Ident);
--| Read in the logfile and process the timing data
Read_Log_File (Program_Clock, Number_Of_Units, Total_Time);
--| Calculate expected errors in reported times
Calculate_Expected_Error (Program_Clock, Number_Of_Units);
--| Sort the Program_Clock by total cumulative execution time
Sort (Program_Clock, Number_Of_Units, Total_Execution_Time);
--| Print Total Execution Time Report
Print_Total_Execution_Times (Program_Clock,
Number_Of_Units, Total_Time);
--| Sort the Program_Clock by program unit name
Sort (Program_Clock, Number_Of_Units, Unit_Name);
--| Print Net Execution Time Report
Print_Net_Execution_Times (Program_Clock, Number_Of_Units);
--| Print Cumulative Execution Time Report
Print_Cum_Execution_Times (Program_Clock, Number_Of_Units);
--| Print the Call Summary Report
Print_Call_Summary_Report (Program_Clock, Number_Of_Units);
--| Close the report file
Close_Paginated_File (Report);
end if;
else
Put_Test_Configuration_Data (Program_Name, Test_Time, Test_Ident);
Text_Io.Put (Value (Log_File_Name));
Text_Io.Put_Line (" does not contain timing data");
end if;
--| Close the log file
Close_Log;
end Profile;
end Profile_Pkg;