с помощью чего можно замерить скорость выполнения этого кода?
```
    public async Task<Dictionary<long, bool>> HasDefectsWithStatusesAsync(
        long[] rootIds,
        ICollection<DefectStatus> defectStatuses,
        CancellationToken token)
    {
        await using var dataConnection = Context.CreateLinqToDBConnection();

        // Создаем CTE для каждого rootId в массиве
        var cte = dataConnection.GetCte<TechnologicalPlace>(cte =>
            dataConnection.GetTable<TechnologicalPlace>()
                .Where(tp => rootIds.Contains(tp.Id))
                .Select(tp => new TechnologicalPlace()
                {
                    Id = tp.Id,
                    ParentTechnologicalPlaceId = tp.ParentTechnologicalPlaceId
                }).AsQueryable()
                .Concat(
                    dataConnection.GetTable<TechnologicalPlace>()
                        .InnerJoin(cte,
                            (childTp, c) => childTp.ParentTechnologicalPlaceId == c.Id,
                            (childTp, c) => new TechnologicalPlace
                            {
                                Id = childTp.Id,
                                ParentTechnologicalPlaceId = childTp.ParentTechnologicalPlaceId
                            }
                        )
                )
        );

        // Получаем все ID технологических мест (включая дочерние)
        var allPlaceIds = cte
            .Select(x => x.Id);

        // Группируем дефекты по TechnologicalPlaceId и проверяем наличие нужных статусов
        var defectsByPlace = await dataConnection.GetTable<Defect>()
            .Where(d => d.TechnologicalPlaceId.HasValue && allPlaceIds.Contains(d.TechnologicalPlaceId.Value) && defectStatuses.Contains(d.Status))
            .GroupBy(d => d.TechnologicalPlaceId.Value)
            .DisableGuard()
            .Select(g => new { PlaceId = g.Key, HasDefects = g.Any() })
            .ToListAsyncLinqToDB(token);

        // Создаем словарь с результатами
        var result = new Dictionary<long, bool>();

        foreach (var rootId in rootIds)
        {
            // Проверяем, есть ли дефекты для данного rootId или его дочерних элементов
            result[rootId] = defectsByPlace.Any(x => x.PlaceId == rootId) ||
                             allPlaceIds.Any(id => id != rootId && defectsByPlace.Any(d => d.PlaceId == id));
        }

        return result;
    }
```

или как оптимизировть следующий алогоритм

```
var topLevels = await technologicalPlaceRepository.GetTopLevel(cancellationToken);
        
        var targetTopLevels = new List<TechnologicalPlace>();
        
        var dictTp = await technologicalPlaceRepository.HasDefectsWithStatusesAsync(topLevels.Select(x => x.Id).ToArray(),
            StatusExtensions.ToList(request.IsOnControl, request.IsInactive, request.IsOnDisabled),
            cancellationToken);
        
        targetTopLevels.AddRange(topLevels
            .Where(x => dictTp[x.Id]));
        
        return targetTopLevels.Select(x => new TechnologicalPlaceAndDefectDto
        {
            ObjectName = nameof(TechnologicalPlace),
            Id = x.Id,
            Name = x.Name,
            IsRktg = x.Statuses.IsRktg(),
            IsRcmn = x.Statuses.IsRcmn(),
            IsRnad = x.Statuses.IsRnad(),
            IsParent = true
        }).ToArray();

// technologicalPlaceRepository
    public Task<TechnologicalPlace[]> GetTopLevel(CancellationToken cancellationToken)
    {
        return Context.Set<TechnologicalPlace>()
            .Include(x => x.ExternalStatusesTechnologicalPlaces)
            .ThenInclude(s => s.ExternalObjectStatus)
            .Where(x => x.ParentTechnologicalPlaceId == null && x.IsDirectionTechnologicalPlacesSet)
            .ToArrayAsyncEF(cancellationToken);
    }


```