PythonPart line profiling with line_profile

Performance profiling of the lines with line_profiler is supported by the PythonParts framework class ProfileUtil such as

ProfileUtil.profile(modify_element_property_local, page, name, value,
                    profiler_type = ProfilerType.LINE_PROFILE)

The profiling results are shown in the Allplan trace window like

Function: select_elements at line 1046

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
1046                                               @use_line_profiler
1047                                               def select_elements(self):
1048
1049         3          0.2      0.1      0.0          point, radius = calculate_point_to_select()
1050         3          0.1      0.0      0.0          world_point = AllplanGeo.Transform(point, trans_matrix)
1051         3          0.0      0.0      0.0          view_world_projection = coord_input.GetViewWorldProjection()
1052         3          0.0      0.0      0.0          new_point = view_world_projection.WorldToView(world_point)
1053
1054                                                   # Big polygon for Crane
1055         3          0.0      0.0      0.0          polygon1 = AllplanGeo.Polygon2D()
1056         3          0.0      0.0      0.0          diff_angle = math.pi*2/36
1057         3          0.0      0.0      0.0          angle = diff_angle/2
1058         3          0.0      0.0      0.0          rad = radius/math.cos(angle)
1059       111          0.0      0.0      0.0          for _ in range(0, 36):
1060       108          0.2      0.0      0.0              polygon1 += AllplanGeo.Point2D(rad * math.cos(angle), rad * math.sin(angle))
1061       108          0.0      0.0      0.0              angle += diff_angle
1062         3          0.0      0.0      0.0          polygon1 += polygon1[0]
1063
1064         3          0.0      0.0      0.0          move_matrix = AllplanGeo.Matrix2D()
1065         3          0.0      0.0      0.0          move_matrix.SetTranslation(AllplanGeo.Vector2D(new_point))
1066         3          0.0      0.0      0.0          crane_polygon = AllplanGeo.Transform(polygon1, move_matrix)
1067
1068         3          0.0      0.0      0.0          condition = AllplanIFW.SelectElementsService.eSelectCondition.SELECT_ALL
1069         3          0.0      0.0      0.0          selected_filter = AllplanIFW.SelectionQuery()
1070
1071         6        691.7    115.3     99.9          elements = AllplanIFW.SelectElementsService.SelectByPolygon(doc, crane_polygon, view_world_projection,
1072         3          0.0      0.0      0.0                                                                         condition, selected_filter)
1073
1074         3          0.0      0.0      0.0          return elements

line_profile

The installation is done with the help of the PythonPart InstallPythonPackage or by following steps below:

  • open https://pypi.org/project/line_profiler/

  • select Download files and download the package

  • unpack the files and copy the folder line_profiler to the Allplan folder ..\Prg\Python\lib\site-packages

Inside the PythonParts script the profiling can be included e.g. in the function modify_element_property as follows

PROFILE_FUNCTION = True
...

def modify_element_property(self, page, name, value):
    ...

    if PROFILE_FUNCTION:
        return ProfileUtil.profile(modify_element_property_local, page, name, value,
                                   profiler_type = ProfilerType.LINE_PROFILE))
    else:
        return modify_element_property_local(page, name, value)

def modify_element_property_local(self, page, name, value):
    ...

Each function whose lines are to be included in the line profiling must be decorated as follows

@use_line_profiler                  # temporary, must be removed again after line profiling
def select_elements(self):