blazium-engine / blazium

Blazium Engine – Multi-platform 2D and 3D game engine
https://blazium.app/
MIT License
149 stars 19 forks source link

Made Node.find_children faster. #66

Closed MisterPuma80 closed 3 days ago

MisterPuma80 commented 3 days ago

Makes Node.find_children faster. Improved version of https://github.com/blazium-engine/blazium/pull/59 . Should also be thoroughly tested before merging.

This uses LocalVector instead of TypedArray. Was 2X faster than https://github.com/blazium-engine/blazium/pull/59 on my machine.

Using this test script: https://github.com/blazium-engine/blazium/pull/59#issuecomment-2422265577

Screenshot from 2024-10-18 12-38-07

Norrox commented 3 days ago

image

i used this code

extends Node

var root_node: Node
const TOTAL_NODES = 400
const MAX_CHILDREN_PER_NODE = 4
const NUM_ITERATIONS = 100
const SEARCH_PATTERNS = ["Child*", "Grandchild*", "GreatGrandchild*"]

func _ready():
    seed(42)
    # Setup: Create a branching tree of nodes
    root_node = Node.new()
    root_node.name = "Root"
    add_child(root_node)  # Add to scene tree to enable find_children
    create_tree(root_node, 0)
    print("Tree created with %d nodes" % count_nodes(root_node))

    # Start the continuous benchmark
    run_benchmark()

func create_tree(parent: Node, depth: int):
    if count_nodes(root_node) >= TOTAL_NODES:
        return

    var num_children = randi() % (MAX_CHILDREN_PER_NODE + 1)
    for i in range(num_children):
        var child = Node.new()
        if depth == 0:
            child.name = "Child%d" % i
        elif depth == 1:
            child.name = "Grandchild%d" % i
        else:
            child.name = "GreatGrandchild%d" % i
        parent.add_child(child)
        create_tree(child, depth + 1)

func count_nodes(node: Node) -> int:
    var count = 1  # Count the node itself
    for child in node.get_children():
        count += count_nodes(child)
    return count

func run_benchmark():
    while true:
        var start_time = Time.get_ticks_usec()
        var total_found = 0

        for i in range(NUM_ITERATIONS):
            # Randomly select a search pattern
            var pattern = SEARCH_PATTERNS[randi() % SEARCH_PATTERNS.size()]

            # Test find_children performance
            var children = root_node.find_children(pattern, "Node", true, false)
            total_found += children.size()

        var end_time = Time.get_ticks_usec()
        var total_time = (end_time - start_time) / 1000000.0  # Convert to seconds

        # Print results
        print("\nBenchmark Results:")
        print("Timestamp: %s" % Time.get_datetime_string_from_system())
        print("Total time: %.4f seconds" % total_time)
        print("Average time per iteration: %.4f milliseconds" % (total_time * 1000 / NUM_ITERATIONS))
        print("Average children found per iteration: %.2f" % (float(total_found) / NUM_ITERATIONS))

        # Wait for 2 seconds before the next run
        await get_tree().create_timer(2.0).timeout

func _exit_tree():
    # Clean up
    if is_instance_valid(root_node):
        root_node.queue_free()
MisterPuma80 commented 3 days ago

Can you try the test again please @jss2a98aj ?

jss2a98aj commented 3 days ago

Can you try the test again please @jss2a98aj ?

The results are quite good image