Xcode 6 с быстрым супер медленным вводом и автозаполнением


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

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

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

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

Я использую MacBook Pro середины 2009 года (2,26 ГГц Intel Core 2 Duo) с 8 ГБ оперативной памяти и SSD HD, который не является новейшей вещью вообще, но все еще не полный мусор.

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

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

11 107

11 ответов:

  • выход из Xcode и перезагрузка Mac не требуются, но предпочтительны.
  • удалить контент папки ~ / Библиотека / Разработчик / Xcode / DerivedData
  • удалить контент ~ / Library/Caches / com.яблоко.Второзаконие.Xcode

это временное решение, но работает очень хорошо.

ниже сценария с помощью приложения редактора сценариев.

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%+ CPU при вводе некоторого "простого" кода. Некоторые небольшие трюки, чтобы сделать swift-парсер быстрее, как вы структурируете свой код.

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

вместо:

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

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

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

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

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

вместо:

var result = pi * 2 * radius 

использование:

var result  = pi * 2
    result *= radius

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

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

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

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

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", но это меньшее зло по сравнению со сложной структурой и синтаксисом проекта objective-C.

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

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

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

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

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

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

enter image description here

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

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

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

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

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

  • удаление ~ / Library / Developer/Xcode/DerivedData/*
  • удаление ~/Library/кэш/ком.яблоко.Второзаконие.Xcode/*
  • удалить все " + " строки объединения из кода
  • удалены все подозрительные объявления словарь

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

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

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

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

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

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

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

сворачивание всех методов немного помогает.

command-alt-shift-Стрелка влево будет делать трюк...

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

Fold: command-alt-стрелка влево

развернуть: command-alt-стрелка вправо

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

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

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

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

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

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

Так что если вы можете позволить себе удалить массивный blob встроенных комментариев, как это:

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

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


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

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

/* Long multiline comments */

замедление ввода.