Проверка Swift Type слишком длинна на очень короткой функции

Я установил флаг компилятора Swift -warn-long-function-bodies в 90 миллисекунд, чтобы увидеть, какие функции в моем проекте слишком долго компилируются (из-за проверки типа).

У меня есть следующий метод:

func someKey(_ sectionType: SectionType, row: Int) -> String {
    let suffix = row == 0 ? "top" : "content"
    return "\(sectionType)_\(suffix)"
}

(SectionType - это перечисляемое по строкам перечисление)

Как он выше, он занимает 96 мс на MacBook Pro 2017. Первое, что я пробовал, - обходить интерполяцию строк и использовать \(sectionType.rawValue) вместо \(sectionType), но теперь она дает мне 106 мс. Неверный ход...

Затем я изменил:

let suffix = row == 0 ? "top" : "content"

в

let suffix = "top"

Предупреждение исчезает, поэтому троянский оператор вызывает проблемы.

Я попробовал это вместо:

let suffix: String = { // Note the type annotation!
    if row == 0 {
        return "top"
    }
    return "content"
}()

... но теперь это замыкание, которое занимает 97 мс (вся функция, 101).

Я даже попытался сделать более явным:

    let suffix: String = {
        if row == 0 {
            return String("top")
        } else {
            return String("content")
        }
    }()

... и я получаю замыкание: 94ms; функция: 98 мс.

Что происходит?

Мой лимит на 90 миллисекунд слишком мал? Я знаю, что была (есть?) Ошибка проверки типов с словарем, но это кажется совсем другим...?

Моя среда - это Xcode 8.3.2 (8E2002), Swift: Apple Swift version 3.1 (swiftlang-802.0.53 clang-802.0.42)


Но подождите! Там больше...

Я пробовал это тело функции:

func someKey(_ sectionType: SectionType, row: Int) -> String {
    if row == 0 {
        return "\(sectionType.rawValue)_top"
    } else {
        return "\(sectionType.rawValue)_content"
    }
}

... и требуется 97 мс ~ 112 мс!?


Добавление: Я пересадил функцию и перечисление в чистый, минимальный проект (приложение с одним представлением) установил одно и то же предупреждение, но этого не происходит. Я уверен, что проект в целом влияет на этот метод каким-то образом, но пока не может понять, как еще...


Добавление 2: я тестировал статическую версию моей функции: используйте фиксированный суффикс "верх" независимо от значения row (это занимает менее 90 мс и не вызывает никаких предупреждений), , но добавил следующий блок if:

func someKey(_ sectionType: SectionType, row: Int) -> String {
    if row == 0 {
        print("zero")
    } else {
        print("non-zero")
    }

    let suffix: String = "top"
    return "\(sectionType)_\(suffix)"
}

Это возвращает меня к 96 ~ 98 мс! Итак, проблема возникает при сравнении строки с нолем?


Обходной путь: Я продолжал играть с моим кодом и каким-то образом обнаружил, что если я заменил блок if выражением switch, проблема исчезнет:

func someKey(_ sectionType: SectionType, row: Int) -> String {
    let suffix: String = {
        switch row {
        case 0:
            return "top"
        default:
            return "content"
        }
    }()
    return "\(sectionType)_\(suffix)"
}

(я не буду отвечать на свой вопрос, потому что я не считаю это объяснением того, что происходит на самом деле)

Ответ 1

Я думаю, что это троичный оператор.

У меня были похожие результаты в Xcode 11 (~ 93 мс), но время компиляции уменьшается до ~ 23 мс с:

func someKey(_ sectionType: SectionType, row: Int) -> String {

    var suffix = "top"

    if row != 0 {
        suffix = "content"
    }

    return "\(sectionType)_\(suffix)"
}

Изменяя логику в этой строке, я думаю, мы можем доказать это троичной логикой, потому что метод сокращается до ~ 1 мс. Я только что сделал строку булевой.

func someKey(_ sectionType: SectionType, row: Bool) -> String {
    let suffix = row ? "top" : "content"
    return "\(sectionType)_\(suffix)"
}

Равным образом (без каламбура) изменение троичной логики на let suffix = row != 0 ? "top" : "content" вдвое сокращает время компиляции. Что сравнимо с моим первым блоком кода. |= быстрее для Swift понять, чем ==.