mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
perf(resolver): stop walking a Swift type's bases once the answer is open
A name that is not a type's own member asks each of its bases, so a type with many conforming extensions cost bases x names: 16,000 `extension A: P` took 157 s in resolve. Past the chain's bound of 128, every further base answers open, so the loop goes on only to reach the answer it already has. It now stops there, once the bound has passed and the answer is already open. Nothing past that point can change the result: a base can no longer be found or be ambiguous, and an open answer returns the same whatever `declared` or `result` hold. The `extension_only` scan also stops at its first declared record. complexity_swift_type_bases_are_near_linear: 3.84 on the old walk, 2.00 now. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
1 parent
eccd026782
commit
6802d8e8b6
2 files changed
+18
-2
No files matched your search
@@ -41,6 +41,7 @@
|
||||
#include "source_adapter_internal.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "stats.h"
|
||||
#include "syntax_index.h"
|
||||
|
||||
#define SWIFT_TYPE_RECORD "&type"
|
||||
@@ -1221,8 +1222,8 @@ static swift_lookup_t swift_find_member(swift_ctx_t *ctx, const char *type_key,
|
||||
}
|
||||
/* Only extensions here: what the extension spells is declared elsewhere, or outside. */
|
||||
bool extension_only = true;
|
||||
for (const cbm_source_decl_t *record = records; record; record = record->next)
|
||||
extension_only &= (record->flags & CBM_SOURCE_DECL_F_ADAPTED) != 0;
|
||||
for (const cbm_source_decl_t *record = records; record && extension_only; record = record->next)
|
||||
extension_only = (record->flags & CBM_SOURCE_DECL_F_ADAPTED) != 0;
|
||||
bool declared = false;
|
||||
if (extension_only && !bases_only) {
|
||||
const char *hash = strchr(type_key, '#');
|
||||
@@ -1255,8 +1256,12 @@ static swift_lookup_t swift_find_member(swift_ctx_t *ctx, const char *type_key,
|
||||
/* An extension of a type outside the project has no declaration here. */
|
||||
const char *base_owner = type_key;
|
||||
for (const cbm_source_decl_t *record = records; record; record = record->next) {
|
||||
cbm_resolve_stats_add(CBM_RESOLVE_STAT_LOOKUP_PROBES, 1);
|
||||
declared |= !(record->flags & CBM_SOURCE_DECL_F_ADAPTED);
|
||||
open |= (record->flags & CBM_SOURCE_DECL_F_OPEN) != 0;
|
||||
/* Past the chain's bound every further base answers open, and the answer is open now. */
|
||||
if (open && chain->overflow)
|
||||
break;
|
||||
for (const char *const *base = record->bases; base && *base; base++) {
|
||||
const char *parent = swift_lookup_type(ctx, base_owner, *base);
|
||||
if (!parent) {
|
||||
|
||||
@@ -3263,6 +3263,16 @@ TEST(complexity_source_same_named_definitions_are_near_linear) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* `extension A: P` many times over: a name found in none of A's bases asks each of them. */
|
||||
CX_LINE3(cx_line_swift_extension_base,
|
||||
"protocol P%d {}\nextension A: P%d {\n func m_%d() { base() }\n}\n")
|
||||
TEST(complexity_swift_type_bases_are_near_linear) {
|
||||
ASSERT_TRUE(cx_source_shape_is_near_linear(CBM_LANG_SWIFT, "bases.swift",
|
||||
"class A { func base() {} }\n",
|
||||
cx_line_swift_extension_base, ""));
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* A barrel library re-exports the project, and every library that imports it read its whole
|
||||
* export list again. */
|
||||
static uint64_t cx_dart_barrel_work(int libraries) {
|
||||
@@ -3457,6 +3467,7 @@ SUITE(complexity) {
|
||||
RUN_TEST(complexity_syntax_index_prev_siblings_answer_as_tree_sitter_does);
|
||||
RUN_TEST(complexity_prev_sibling_walk_is_linear);
|
||||
RUN_TEST(complexity_source_same_named_definitions_are_near_linear);
|
||||
RUN_TEST(complexity_swift_type_bases_are_near_linear);
|
||||
RUN_TEST(complexity_dart_barrel_exports_are_near_linear);
|
||||
RUN_TEST(complexity_go_route_bindings_are_near_linear);
|
||||
RUN_TEST(complexity_flat_preceding_label_is_linear);
|
||||
|
||||
Reference in new issue
Block a user