1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
# Copyright (c) 2020, Manfred Moitzi
# License: MIT License
import sys
import time
from datetime import datetime
from pathlib import Path
from ezdxf.acc import USE_C_EXT
from ezdxf.render.forms import ellipse
if USE_C_EXT is False:
print("C-extension disabled or not available.")
sys.exit(1)
from ezdxf.math._construct import (
has_clockwise_orientation as py_has_clockwise_orientation,
)
from ezdxf.acc.construct import (
has_clockwise_orientation as cy_has_clockwise_orientation,
)
from ezdxf.math._construct import (
intersection_line_line_2d as py_intersection_line_line_2d,
)
from ezdxf.acc.construct import (
intersection_line_line_2d as cy_intersection_line_line_2d,
)
from ezdxf.version import __version__
from ezdxf.acc.vector import Vec2
def open_log(name: str):
parent = Path(__file__).parent
p = parent / "logs" / Path(name + ".csv")
if not p.exists():
with open(p, mode="wt") as fp:
fp.write(
'"timestamp"; "pytime"; "cytime"; '
'"python_version"; "ezdxf_version"\n'
)
log_file = open(p, mode="at")
return log_file
def log(name: str, pytime: float, cytime: float):
log_file = open_log(name)
timestamp = datetime.now().isoformat()
log_file.write(
f'{timestamp}; {pytime}; {cytime}; "{sys.version}"; "{__version__}"\n'
)
log_file.close()
def profile1(func, *args) -> float:
t0 = time.perf_counter()
func(*args)
t1 = time.perf_counter()
return t1 - t0
def profile(text, log_name, pyfunc, cyfunc, *args):
pytime = profile1(pyfunc, *args)
cytime = profile1(cyfunc, *args)
ratio = pytime / cytime
print(f"Python - {text} {pytime:.3f}s")
print(f"Cython - {text} {cytime:.3f}s")
print(f"Ratio {ratio:.1f}x")
log(log_name, pytime, cytime)
def profile_py_has_clockwise_orientation(vertices, count):
for _ in range(count):
py_has_clockwise_orientation(vertices)
def profile_cy_has_clockwise_orientation(vertices, count):
for _ in range(count):
cy_has_clockwise_orientation(vertices)
def profile_py_intersection_line_line_2d(count):
line1 = [Vec2(0, 0), Vec2(2, 0)]
line2 = [Vec2(1, -1), Vec2(1, 1)]
for _ in range(count):
py_intersection_line_line_2d(line1, line2)
def profile_cy_intersection_line_line_2d(count):
line1 = [Vec2(0, 0), Vec2(2, 0)]
line2 = [Vec2(1, -1), Vec2(1, 1)]
for _ in range(count):
cy_intersection_line_line_2d(line1, line2)
def profile_py_no_intersection_line_line_2d(count):
line1 = [Vec2(0, 0), Vec2(2, 0)]
line2 = [Vec2(0, 1), Vec2(2, 1)]
for _ in range(count):
py_intersection_line_line_2d(line1, line2)
def profile_cy_no_intersection_line_line_2d(count):
line1 = [Vec2(0, 0), Vec2(2, 0)]
line2 = [Vec2(0, 1), Vec2(2, 1)]
for _ in range(count):
cy_intersection_line_line_2d(line1, line2)
RUNS = 100_000
ellipse_vertices = list(ellipse(count=100, rx=10, ry=5))
print(f"Profiling 2D construction tools as Python and Cython implementations:")
profile(
f"detect {RUNS}x clockwise orientation of {len(ellipse_vertices)} vertices:",
"c2d_has_clockwise_orientation",
profile_py_has_clockwise_orientation,
profile_cy_has_clockwise_orientation,
ellipse_vertices,
RUNS,
)
profile(
f"detect {RUNS}x real 2D line intersections:",
"c2d_intersection_line_line_2d",
profile_py_intersection_line_line_2d,
profile_cy_intersection_line_line_2d,
RUNS,
)
profile(
f"detect {RUNS}x no 2D line intersections:",
"c2d_no_intersection_line_line_2d",
profile_py_no_intersection_line_line_2d,
profile_cy_no_intersection_line_line_2d,
RUNS,
)
|