Add Recipemanager that loads recipes from YAML
This commit is contained in:
@@ -0,0 +1,283 @@
|
||||
extends ExampleBase
|
||||
|
||||
## Number of iterations for each benchmark
|
||||
const ITERATIONS: int = 10
|
||||
|
||||
## Thread counts for multithreaded benchmarks
|
||||
const THREAD_COUNTS: Array = [1, 2, 4, 8, 16, 32, 64, 100]
|
||||
|
||||
## Path to the YAML file to benchmark
|
||||
const YAML_PATH: String = "res://addons/yaml/examples/data/supported_syntax.yaml"
|
||||
|
||||
func _init() -> void:
|
||||
icon = "⚡"
|
||||
|
||||
func run_examples() -> void:
|
||||
log_header("YAML Speed Benchmark")
|
||||
print(YAML.version())
|
||||
|
||||
run_example("Load YAML File", load_yaml_file_benchmark)
|
||||
run_example("Parse (No Style) Benchmark", parse_benchmark)
|
||||
run_example("Parse (With Style) Benchmark", parse_with_style_benchmark)
|
||||
run_example("Stringify (No Style) Benchmark", stringify_benchmark)
|
||||
run_example("Stringify (With Style) Benchmark", stringify_with_style_benchmark)
|
||||
run_example("Compare Results", compare_results)
|
||||
run_example("Parse (Threaded) Bechmark", parse_threaded)
|
||||
run_example("Stringify (Threaded) Benchmark", stringify_threaded)
|
||||
|
||||
var yaml_input: String
|
||||
var parse_times := []
|
||||
var style_parse_times := []
|
||||
var stringify_times := []
|
||||
var style_stringify_times := []
|
||||
var data = null
|
||||
var style = null
|
||||
|
||||
func load_yaml_file_benchmark() -> void:
|
||||
log_info("Loading YAML file: " + YAML_PATH)
|
||||
|
||||
var file := FileAccess.open(YAML_PATH, FileAccess.READ)
|
||||
if !file:
|
||||
log_error("Could not open file: " + YAML_PATH)
|
||||
return
|
||||
|
||||
yaml_input = file.get_as_text()
|
||||
log_success("File loaded, size: " + str(yaml_input.length()) + " characters")
|
||||
|
||||
var result := YAML.parse(yaml_input)
|
||||
data = result.get_data()
|
||||
|
||||
if LOG_VERBOSE:
|
||||
log_result("First 200 characters:\n" + yaml_input.substr(0, 200) + "...")
|
||||
|
||||
func parse_benchmark() -> void:
|
||||
if yaml_input.is_empty():
|
||||
log_error("No YAML input loaded")
|
||||
return
|
||||
|
||||
log_info("Running parse benchmark (" + str(ITERATIONS) + " iterations)...")
|
||||
|
||||
for i in range(ITERATIONS):
|
||||
var start := Time.get_ticks_usec()
|
||||
var result = YAML.parse(yaml_input)
|
||||
var elapsed := Time.get_ticks_usec() - start
|
||||
|
||||
if result.has_error():
|
||||
log_error("Iteration " + str(i + 1) + " failed: " + result.get_error())
|
||||
continue
|
||||
|
||||
parse_times.append(elapsed)
|
||||
log_info("Iteration " + str(i + 1) + ": " + str(elapsed) + " µs")
|
||||
|
||||
if parse_times.size() > 0:
|
||||
var avg = float(parse_times.reduce(func(a, b): return a + b)) / parse_times.size()
|
||||
log_success("Average parse time: " + str(avg) + " µs")
|
||||
else:
|
||||
log_error("No successful parse iterations")
|
||||
|
||||
func parse_with_style_benchmark() -> void:
|
||||
if yaml_input.is_empty():
|
||||
log_error("No YAML input loaded")
|
||||
return
|
||||
|
||||
log_info("Running parse with style benchmark (" + str(ITERATIONS) + " iterations)...")
|
||||
|
||||
for i in range(ITERATIONS):
|
||||
var start := Time.get_ticks_usec()
|
||||
var result = YAML.parse(yaml_input, YAML.create_security(), true)
|
||||
var elapsed := Time.get_ticks_usec() - start
|
||||
|
||||
if result.has_error():
|
||||
log_error("Iteration " + str(i + 1) + " failed: " + result.get_error())
|
||||
continue
|
||||
|
||||
if i == 0:
|
||||
style = result.get_style()
|
||||
|
||||
style_parse_times.append(elapsed)
|
||||
log_info("Iteration " + str(i + 1) + ": " + str(elapsed) + " µs")
|
||||
|
||||
if style_parse_times.size() > 0:
|
||||
var avg = float(style_parse_times.reduce(func(a, b): return a + b)) / style_parse_times.size()
|
||||
log_success("Average parse with style time: " + str(avg) + " µs")
|
||||
else:
|
||||
log_error("No successful parse with style iterations")
|
||||
|
||||
func stringify_benchmark() -> void:
|
||||
if data == null:
|
||||
log_error("No data available for stringify tests")
|
||||
return
|
||||
|
||||
log_info("Running stringify benchmark (" + str(ITERATIONS) + " iterations)...")
|
||||
|
||||
for i in range(ITERATIONS):
|
||||
var start := Time.get_ticks_usec()
|
||||
var result = YAML.stringify(data)
|
||||
var elapsed := Time.get_ticks_usec() - start
|
||||
|
||||
if result.has_error():
|
||||
log_error("Iteration " + str(i + 1) + " failed: " + result.get_error())
|
||||
continue
|
||||
|
||||
stringify_times.append(elapsed)
|
||||
log_info("Iteration " + str(i + 1) + ": " + str(elapsed) + " µs")
|
||||
|
||||
if stringify_times.size() > 0:
|
||||
var avg = float(stringify_times.reduce(func(a, b): return a + b)) / stringify_times.size()
|
||||
log_success("Average stringify time: " + str(avg) + " µs")
|
||||
else:
|
||||
log_error("No successful stringify iterations")
|
||||
|
||||
func stringify_with_style_benchmark() -> void:
|
||||
if data == null or style == null:
|
||||
log_error("No data or style available for stringify tests")
|
||||
return
|
||||
|
||||
log_info("Running stringify with style benchmark (" + str(ITERATIONS) + " iterations)...")
|
||||
|
||||
for i in range(ITERATIONS):
|
||||
var start := Time.get_ticks_usec()
|
||||
var result = YAML.stringify(data, style)
|
||||
var elapsed := Time.get_ticks_usec() - start
|
||||
|
||||
if result.has_error():
|
||||
log_error("Iteration " + str(i + 1) + " failed: " + result.get_error())
|
||||
continue
|
||||
|
||||
style_stringify_times.append(elapsed)
|
||||
log_info("Iteration " + str(i + 1) + ": " + str(elapsed) + " µs")
|
||||
|
||||
if style_stringify_times.size() > 0:
|
||||
var avg = float(style_stringify_times.reduce(func(a, b): return a + b)) / style_stringify_times.size()
|
||||
log_success("Average stringify with style time: " + str(avg) + " µs")
|
||||
else:
|
||||
log_error("No successful stringify with style iterations")
|
||||
|
||||
func compare_results() -> void:
|
||||
log_subheader("Performance Comparison")
|
||||
|
||||
# Collect all test results
|
||||
var all_tests = [
|
||||
{
|
||||
"name": "Parse (no style)",
|
||||
"times": parse_times
|
||||
},
|
||||
{
|
||||
"name": "Parse (with style)",
|
||||
"times": style_parse_times
|
||||
},
|
||||
{
|
||||
"name": "Stringify (no style)",
|
||||
"times": stringify_times
|
||||
},
|
||||
{
|
||||
"name": "Stringify (with style)",
|
||||
"times": style_stringify_times
|
||||
}
|
||||
]
|
||||
|
||||
# Calculate and print stats
|
||||
for test in all_tests:
|
||||
var times = test.times
|
||||
if times.is_empty():
|
||||
log_warning(test.name + ": No valid results")
|
||||
continue
|
||||
|
||||
var avg: float = float(times.reduce(func(a, b): return a + b)) / times.size()
|
||||
var min_time: int = times.min()
|
||||
var max_time: int = times.max()
|
||||
|
||||
log_info(test.name + ":")
|
||||
log_info(" Average: %.2f µs" % avg)
|
||||
log_info(" Min: %d µs" % min_time)
|
||||
log_info(" Max: %d µs" % max_time)
|
||||
|
||||
log_info("\nPerformance Insights:")
|
||||
|
||||
# Compare parse with and without style
|
||||
if !parse_times.is_empty() and !style_parse_times.is_empty():
|
||||
var avg_parse = float(parse_times.reduce(func(a, b): return a + b)) / parse_times.size()
|
||||
var avg_style_parse = float(style_parse_times.reduce(func(a, b): return a + b)) / style_parse_times.size()
|
||||
|
||||
var style_overhead = ((avg_style_parse / avg_parse) - 1.0) * 100.0
|
||||
log_info("Style detection adds approximately %.1f%% overhead to parsing" % style_overhead)
|
||||
|
||||
# Compare stringify with and without style
|
||||
if !stringify_times.is_empty() and !style_stringify_times.is_empty():
|
||||
var avg_stringify = float(stringify_times.reduce(func(a, b): return a + b)) / stringify_times.size()
|
||||
var avg_style_stringify = float(style_stringify_times.reduce(func(a, b): return a + b)) / style_stringify_times.size()
|
||||
|
||||
var style_overhead = ((avg_style_stringify / avg_stringify) - 1.0) * 100.0
|
||||
log_info("Using style adds approximately %.1f%% overhead to stringify" % style_overhead)
|
||||
|
||||
func parse_threaded() -> void:
|
||||
if yaml_input.is_empty():
|
||||
log_error("No YAML input loaded")
|
||||
return
|
||||
|
||||
log_subheader("Threaded Parse Benchmark")
|
||||
|
||||
for thread_count in THREAD_COUNTS:
|
||||
var threads: Array[Thread] = []
|
||||
|
||||
var start := Time.get_ticks_usec()
|
||||
|
||||
for i in range(thread_count):
|
||||
var thread := Thread.new()
|
||||
thread.start(_parse_thread_func.bind(yaml_input))
|
||||
threads.append(thread)
|
||||
|
||||
var total_parse_time := 0
|
||||
for thread in threads:
|
||||
total_parse_time += thread.wait_to_finish()
|
||||
|
||||
var wall_time := Time.get_ticks_usec() - start
|
||||
var avg_thread_time := float(total_parse_time / thread_count)
|
||||
|
||||
log_info("%d thread(s): wall=%d µs | avg thread=%d µs | throughput=%.1f parses/ms" % [
|
||||
thread_count,
|
||||
wall_time,
|
||||
avg_thread_time,
|
||||
thread_count / (wall_time / 1000.0)
|
||||
])
|
||||
|
||||
func stringify_threaded() -> void:
|
||||
if data == null:
|
||||
log_error("No data available for stringify tests")
|
||||
return
|
||||
|
||||
log_subheader("Threaded Stringify Benchmark")
|
||||
|
||||
for thread_count in THREAD_COUNTS:
|
||||
var threads: Array[Thread] = []
|
||||
|
||||
var start := Time.get_ticks_usec()
|
||||
|
||||
for i in range(thread_count):
|
||||
var thread := Thread.new()
|
||||
thread.start(_stringify_thread_func.bind(data))
|
||||
threads.append(thread)
|
||||
|
||||
var total_stringify_time := 0
|
||||
for thread in threads:
|
||||
total_stringify_time += thread.wait_to_finish()
|
||||
|
||||
var wall_time := Time.get_ticks_usec() - start
|
||||
var avg_thread_time := float(total_stringify_time / thread_count)
|
||||
|
||||
log_info("%d thread(s): wall=%d µs | avg thread=%d µs | throughput=%.1f stringifies/ms" % [
|
||||
thread_count,
|
||||
wall_time,
|
||||
avg_thread_time,
|
||||
thread_count / (wall_time / 1000.0)
|
||||
])
|
||||
|
||||
static func _parse_thread_func(input: String) -> int:
|
||||
var start := Time.get_ticks_usec()
|
||||
YAML.parse(input)
|
||||
return Time.get_ticks_usec() - start
|
||||
|
||||
static func _stringify_thread_func(input_data: Variant) -> int:
|
||||
var start := Time.get_ticks_usec()
|
||||
YAML.stringify(input_data)
|
||||
return Time.get_ticks_usec() - start
|
||||
Reference in New Issue
Block a user