Xcode 6 со Swift супер медленной печатью и автозаполнением

Это просто я или Xcode 6 (6.0.1) с Swift, кажется, очень медленный, когда вы печатаете свой код, особенно с автозаполнением?

Обычный класс Objective-C, даже если он находится внутри проекта Swift, работает почти так же, как и раньше, поэтому его убивает Swift.

Кто-нибудь еще испытывает такое же неудобство? У вас есть идеи, как улучшить производительность?

  • Я пытался играть с некоторыми настройками, но не повезло.
  • Я также, конечно, безуспешно пытался перезапустить Xcode и компьютер.
  • Другие тяжелые приложения не открыты.

Я использую Macbook Pro середины 2009 года (Intel Core 2 Duo с частотой 2,26 ГГц) с 8 ГБ ОЗУ и твердотельным накопителем HD, что не является чем-то новым, но все же не полным мусором.

Это позор, так как я был взволнован, чтобы начать использовать Swift, и теперь это действительно невыносимо.

Мысли / советы?

11 ответов

Решение
  • Выйти из Xcode и перезагрузить Mac не обязательно, но желательно.
  • Удалить содержимое папки ~ / Библиотека / Разработчик / Xcode / DerivedData
  • Удалить содержимое ~ / Library / Caches / com.apple.dt.Xcode

Это временное решение, но оно отлично работает.

Ниже сценария с помощью приложения Script Editor.

tell application "Terminal"
    do script "rm -frd ~/Library/Developer/Xcode/DerivedData/*"
    do script "rm -frd ~/Library/Caches/com.apple.dt.Xcode/*"
end tell

Кроме того, вы можете создать псевдоним для вашего терминала, например:

alias xcodeclean="rm -frd ~/Library/Developer/Xcode/DerivedData/* && rm -frd ~/Library/Caches/com.apple.dt.Xcode/*"

Вы можете добавить это к вашему ~/.bash_profile а затем введите xcodeclean в командной строке каждый раз, когда вы хотите очистить эти две папки.

Я также испытал 100%+ процессор при наборе "простого" кода. Несколько небольших хитростей для ускорения работы swift-parser в процессе структурирования кода.

Не используйте конкатинатор "+" в строках. Для меня это вызывает медлительность очень быстро. Каждое новое "+" приводит к сканированию синтаксического анализатора, и он должен повторно анализировать код каждый раз, когда вы добавляете новый символ где-то в теле функции.

Вместо:

var str = "This" + String(myArray.count) + " is " + String(someVar)

Используйте синтаксис шаблона, который кажется более эффективным для анализа в swift:

var str = "This \(myArray.count) is \(someVar)"

Таким образом, я в основном не замечаю никаких ограничений в строковых переменных "\(*)" .

Если у вас есть расчеты, которые используют + / * - разделите их на более мелкие части.

Вместо:

var result = pi * 2 * radius 

использовать:

var result  = pi * 2
    result *= radius

Это может выглядеть менее эффективно, но быстрый синтаксический анализатор в этом случае намного быстрее. Некоторые формулы не будут компилироваться, если им нужно много операций, даже если они математически верны.

Если у вас есть какие-то сложные вычисления, поместите их в функцию. Таким образом, синтаксический анализатор может анализировать его один раз, и ему не нужно повторять его каждый раз, когда вы что-то меняете в теле функции.

Потому что, если у вас есть вычисление в теле функции, то каким-то образом быстрый анализатор проверяет его каждый раз, если типы, синтаксис и т. Д. Все еще верны. Если линия превысит вычисление, то некоторые переменные внутри вашего вычисления / формулы могут измениться. Если вы поместите его во внешнюю функцию, то он будет проверен один раз, и swift будет рад, что он будет корректным и не будет повторно анализировать его постоянно, что вызывает высокую загрузку ЦП.

Таким образом, я набрал от 100% при каждом нажатии клавиши до низкой загрузки процессора во время набора текста. Например, эти 3 строки, вставленные в ваше тело функции, могут привести к быстрому сканированию.

let fullPath =  "\(NSHomeDirectory())/Library/Preferences/com.apple.spaces.plist"
let spacesData  = NSDictionary(contentsOfFile: fullPath )! // as Dictionary<String, AnyObject>
let spaces : AnyObject   = spacesData["SpacesDisplayConfiguration"]!["Management Data"]!!["Monitors"]!![0]["Spaces"]!! 

println ( spaces )

но если я положу его в func и позвоню позже, swiftparser будет намного быстрее

// some crazy typecasting here to silence the parser
// Autodetect of Type from Plist is very rudimentary, 
// so you have to teach swift your types
// i hope this will get improved in swift in future
// would be much easier if one had a xpath filter with
// spacesData.getxpath( "SpacesDisplayConfiguration/Management Data/Monitors/0/Spaces" ) as Array<*> 
// and xcode could detect type from the plist automatically
// maybe somebody can show me a more efficient way to do it
// again to make it nice for the swift parser, many vars and small statements
func getSpacesDataFromPlist() -> Array<Dictionary<String, AnyObject>> {
  let fullPath =  "\(NSHomeDirectory())/Library/Preferences/com.apple.spaces.plist"

  let spacesData  = NSDictionary(contentsOfFile: fullPath )!    as Dictionary<String, AnyObject>
  let sdconfig    = spacesData["SpacesDisplayConfiguration"]    as Dictionary<String, AnyObject>
  let mandata     = sdconfig["Management Data"]                 as Dictionary<String, AnyObject> 
  let monitors    = mandata["Monitors"]                         as Array<Dictionary<String, AnyObject>> 
  let monitor     = monitors[0]                                 as Dictionary<String, AnyObject>
  let spaces      = monitor["Spaces"]                           as Array<Dictionary<String, AnyObject>>

  return spaces
}

func awakeFromNib() {
  ....
  ... typing here ...

  let spaces = self.getSpacesDataFromPlist()
  println( spaces) 
}

Swift и XCode 6.1 все еще очень глючные, но если вы будете следовать этим простым приемам, редактирование кода снова станет приемлемым. Я предпочитаю swift много, так как он избавляется от файлов.h и использует намного более чистый синтаксис. По-прежнему требуется много приведений типов, например "myVar as AnyObject", но это меньшее зло по сравнению со сложной структурой и синтаксисом проекта target-c.

Кроме того, я попробовал SpriteKit, который интересно использовать, но он довольно неэффективен, если вам не нужна постоянная перекраска со скоростью 60 кадров в секунду. Использование старых CALayers намного лучше для процессора, если ваши "спрайты" меняются не так часто. Если вы не измените.contents слоев, тогда CPU в основном простаивает, но если у вас приложение SpriteKit, работающее в фоновом режиме, то воспроизведение видео в других приложениях может заикаться из-за жесткого цикла обновления 60fps.

Иногда xcode выдает странные ошибки при компиляции, тогда это помогает перейти в меню "Product > Clean" и скомпилировать его снова, что является ошибочной реализацией кеша.

Другой отличный способ улучшить синтаксический анализ, когда xcode застревает в вашем коде, упоминается в другом посте stackru здесь. По сути, вы копируете все содержимое файла.swift во внешний редактор, а затем по функциям копируете его обратно и видите, где находится ваше узкое место. Это фактически помогло мне снова получить xcode с разумной скоростью, после того, как мой проект сошел с ума со 100% CPU. копируя ваш код обратно, вы можете реорганизовать его и попытаться сделать ваши функциональные тела короткими, а функции / формулы / выражения простыми (или разбить на несколько строк).

Автозаполнение не работает после Xcode 4. Пока Apple не решит исправить эту 2-летнюю ошибку, к сожалению, единственное решение - отключить завершение кода в настройках XCode (первый вариант на рисунке ниже).

Вы можете продолжить наслаждаться завершением вручную, набрав CTRL space или же ESC когда тебе это нужно.

Это единственное решение, которое работает каждый раз в 100% случаев.

введите описание изображения здесь

Недавно я обнаружил еще одну вещь: если вы используете плагины в Xcode, не делайте этого. Убери их всех. Они усугубляют проблему.

Вы используете Spotify? Я установил Yosemite GM с Xcode 6.1 GM на iMac в середине 2009 года (2,66 ГГц) с той же проблемой. Я обнаружил, что процесс с именем "SpotifyWebHelper" всегда помечается красным, как не отвечающий, поэтому я отключил опцию "начать с веб" в Spotify и теперь XCode, кажется, работает значительно лучше.

У меня были такие же проблемы даже в Xcode 6.3

  • супер медленные автодополнения
  • супер медленная индексация
  • огромное использование процессора swift и SourceKitService
  • огромное использование памяти SourceKitService

Все это происходило даже в относительно небольших проектах. Я перепробовал все исправления, которые смог найти:

  • удаление ~/ Библиотека / Разработчик /Xcode/DerivedData/*
  • удаление ~/Library/Caches/com.apple.dt.Xcode/*
  • удалить все "+" объединения строк из кода
  • убрал все подозрительные словарные объявления

Ничто из этого не помогло в моем проекте.

Что на самом деле решило мою проблему:

  • помещая каждый конец каждого класса в свой собственный файл
  • размещение каждого расширения в своем собственном файле (Class+ExtName.swift)
  • размещение "вне класса быстрых методов" в своем собственном файле

Теперь у меня практически нулевое использование процессора, низкое использование памяти и довольно быстрое завершение работы.

Как правило, перемещение папки кэша (DerivedData) на SSD-диск (особенно в моем случае - внешнее хранилище, подключенное к выходу Thunderbolt) значительно улучшило мою производительность Xcode. Время компиляции и общие вопросы вокруг приложения примерно в 10 раз быстрее. Также перемещена вся папка git на SSD, что значительно улучшило производительность git.

Свертывание всех методов мало помогает.

Команда-Alt-Shift-стрелка влево будет добиваться цели...

Чтобы сложить / развернуть текущие методы или если структуры используют:

Сложите: команда-Alt-стрелка влево

Развернуть: команда-Alt-стрелка вправо

Я узнал, что обычно происходит, когда вы:

  • иметь длинные выражения в одном выражении (см. этот ответ)
  • смешать несколько пользовательских операторов в одном выражении

Второй случай, кажется, исправлен в одном из последних выпусков xcode. Пример: я определил 2 пользовательских оператора <&&> и <||>и использовал их в выражении типа a <&&> b <&&> c <||> d, Разделение на несколько строк решило проблему:

let r1 = a <&&> b
let r2 = r1 <&&> c
let r3 = r2 <||> d

Я надеюсь, что ваши дела покрываются одним из 2 выше... пожалуйста, оставьте комментарий в любом случае

Это была боль до XCode 7.2.

Apple исправила это в XCode 7.3, и теперь это работает как шарм. Он очень быстрый и намного более мощный, так как кажется, что он работает как нечеткий поиск файлов: вам не нужно вводить точное начало метода / свойства, чтобы оно появилось в списке предложений.

SourceKitService также немного неудобно иметь дело с комментариями в коде, а встроенные комментарии также замедляют его.

так что, если вы можете позволить себе убрать массивное пятно встроенных комментариев, например:

/*
 * comment 
    /*
     * embedded comment
     */
 */

это определенно может помочь.


ПРИМЕЧАНИЕ: в моем случае мой Xcode 7.3.1 (7D1014) был буквально заблокирован, и я печатал любое письмо, когда в файле было около 700 строк комментариев со встроенными комментариями. Первоначально я удалил этот блок из этого.swiftфайл и Xcode снова стали живыми. Я пытался добавлять свои комментарии обратно по частям, удаляя встроенные комментарии, они все еще были медленнее, чем обычно, но показали значительно лучшую производительность, если не было встроенных комментариев.

У меня была та же проблема, когда типирование запаздывало в определенном классе и оказалось, что

/* Long multiline comments */

замедлял набор текста.

Другие вопросы по тегам