Repository: excalidraw/excalidraw
File: packages/excalidraw/element/binding.ts (TypeScript)

Code before:
      startBinding: maybeCalculateNewGapWhenScaling(
        changedElement,
        element.startBinding,
        oldSize,
      ),
      endBinding: maybeCalculateNewGapWhenScaling(
        changedElement,
        element.endBinding,
        oldSize,
      ),
    };

    // `linearElement` is being moved/scaled already, just update the binding
    if (simultaneouslyUpdatedElementIds.has(element.id)) {
      mutateElement(element, bindings);
      return;
    }

    const updates = bindableElementsVisitor(
      elementsMap,
      element,
      (bindableElement, bindingProp) => {
        if (
          bindableElement &&
          isBindableElement(bindableElement) &&
          (bindingProp === "startBinding" || bindingProp === "endBinding")
        ) {
          const point = updateBoundPoint(
            element,
            bindingProp,
            bindings[bindingProp],
            bindableElement,
            elementsMap,
          );
          if (point) {
            return {
              index:
                bindingProp === "startBinding" ? 0 : element.points.length - 1,
              point,
            };
          }
        }

        return null;
      },
    ).filter(
      (
        update,
      ): update is NonNullable<{
        index: number;
        point: LocalPoint;

Review comment (suggestion):
This change will run updateBoundPoint(...) for all scene elements, which is a large amount of no-op for every movement of even a single arrow connected shape. Instead you should set up the condition that either the changed bindable element is true or the connected other end element.

Code after:
    if (!candidateElements || candidateElements.length === 0) {
      return null;
    }

    if (candidateElements.length === 1) {
      return candidateElements[0] as NonDeleted<ExcalidrawBindableElement>;
    }

    // Prefer the shape with the border being tested (if any)
    const borderTestElements = candidateElements.filter((element) =>
      bindingBorderTest(element, pointerCoords, elementsMap, zoom, false),
    );
    if (borderTestElements.length === 1) {
      return borderTestElements[0];
    }

    // Prefer smaller shapes
    return candidateElements
      .sort(
        (a, b) => b.width ** 2 + b.height ** 2 - (a.width ** 2 + a.height ** 2),
      )
      .pop() as NonDeleted<ExcalidrawBindableElement>;
  }

  const hoveredElement = getElementAtPositionForBinding(
    elements,
    (element) =>
      isBindableElement(element, false) &&
      bindingBorderTest(
        element,
        pointerCoords,
        elementsMap,
        zoom,
        // disable fullshape snapping for frame elements so we
        // can bind to frame children
        (fullShape || !isBindingFallthroughEnabled(element)) &&
          !isFrameLikeElement(element),
      ),
  );

  return hoveredElement as NonDeleted<ExcalidrawBindableElement> | null;
};

const getElementAtPositionForBinding = (
  elements: readonly NonDeletedExcalidrawElement[],
  isAtPositionFn: (element: NonDeletedExcalidrawElement) => boolean,
) => {
  let hitElement = null;
  // We need to to hit testing from front (end of the array) to back (beginning of the array)
  // because array is ordered from lower z-index to highest and we want element z-index
  // with higher z-index