Xcode 6 z szybkim, bardzo wolnym pisaniem i autouzupełnianiem

114

Czy to tylko ja, czy Xcode 6 (6.0.1) ze Swift wydaje się być bardzo powolny podczas wpisywania kodu, zwłaszcza z autouzupełnianiem?

Normalna klasa Objective-C, nawet jeśli znajduje się w projekcie Swift, działa prawie tak samo jak poprzednio, więc to Swift ją zabija.

Czy ktoś inny doświadcza tej samej niedogodności? Czy masz pomysł, jak poprawić wydajność?

  • Próbowałem grać z niektórymi ustawieniami, ale bez powodzenia.
  • Oczywiście bez powodzenia próbowałem zrestartować Xcode i komputer.
  • Żadne inne ciężkie aplikacje nie są otwarte.

Używam Macbooka Pro z połowy 2009 roku (2,26 GHz Intel Core 2 Duo) z 8 GB pamięci RAM i dyskiem SSD HD, co wcale nie jest nowością, ale nadal nie jest kompletnym śmieciem.

Szkoda, ponieważ byłem podekscytowany, aby zacząć używać Swift, a teraz jest to naprawdę nie do zniesienia.

Myśli / wskazówki?

mllm
źródło
1
Mam takie same problemy jak ty. Często Xcode mówi mi: „SourceKit zakończony, edytor tymczasowo ograniczony”
idmean
Tak, to także inny problem, chociaż nie jestem pewien, czy są ze sobą powiązane. Był powolny, nawet gdy ten błąd się pojawił.
mllm
1
Jestem pewien, że są spokrewnieni. W wersji beta 5 widziałem ten komunikat jeszcze częściej i widziałem go zawsze, gdy sugestia nie działała. (Kiedy
wpisałem
1
Mam ten sam problem. Mój XCode zużywa ponad 300% procesora i spowalnia siatkówkę mojego macbooka do ślimaka. W dzisiejszych czasach piszę na ślepo i czekam na zakończenie xcode.
pkuhar
1
Mając te same problemy z 15,6-calowym MacBookiem Pro z końca 2011 r., 8 GB RAM i dyskiem SSD. 90% czasu zakończenia kodu zawiesza Xcode, kiedy sprawdzam monitor aktywności, widzę ~ 200% zużycia procesora. Zawieszenia trwają od kilku sekund do kilku minut
isair

Odpowiedzi:

86
  • Zamknij Xcode i uruchom ponownie komputer Mac nie są wymagane, ale preferowane.
  • Usuń zawartość folderu ~ / Library / Developer / Xcode / DerivedData
  • Usuń zawartość ~ / Library / Caches / com.apple.dt.Xcode

Jest to rozwiązanie tymczasowe, ale działa bardzo dobrze.

Poniżej skryptu za pomocą aplikacji 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

Alternatywnie możesz utworzyć alias dla swojego terminala w następujący sposób:

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

Możesz dodać to do swojego, ~/.bash_profilea następnie wpisać xcodecleanw wierszu poleceń za każdym razem, gdy chcesz wyczyścić te dwa foldery.

g8production - Daniele Gali8
źródło
Cóż, chociaż nie jest to bliskie doskonałości, wygląda na to, że Twoje rozwiązanie znacznie je poprawia. Zaznaczę, że rozwiązuje się tak samo, ponieważ po dość długim czasie jest to prawdopodobnie najlepsze, jakie można uzyskać. Z przyjemnością usłyszę o innych ... Wielkie dzięki!
mllm
Usunięcie całej zawartości z tych dwóch folderów zajęło mojemu laptopowi prawie minutę. Indeksowanie w Xcode zajmuje teraz mniej niż 30 sekund.
Eneko Alonso
Nie przyspieszyło to pisania i autouzupełniania, ale pomogło mi zwolnić sporo miejsca na komputerze Mac.
Scott Zhu,
Ta odpowiedź pomogła w kwestii autouzupełniania, stackoverflow.com/a/29849869/1213267
Scott Zhu,
13

Podczas pisania jakiegoś „prostego” kodu doświadczyłem również 100% + CPU. Kilka drobnych sztuczek, dzięki którym szybki parser będzie szybszy dzięki strukturze Twojego kodu.

Nie używaj konkatinatora „+” w łańcuchach. Dla mnie to bardzo szybko wyzwala powolność. Każde nowe „+” przenosi parser do przeszukiwania i musi ponownie przeanalizować kod za każdym razem, gdy dodajesz nowy znak gdzieś w treści funkcji.

Zamiast:

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

Użyj składni szablonu, która wydaje się znacznie wydajniejsza do analizowania w szybkim tempie:

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

W ten sposób zasadniczo nie zauważam ograniczenia w strlen z wbudowanymi zmiennymi "\ (*)".

Jeśli masz obliczenia, które używają + / * -, podziel je na mniejsze części.

Zamiast:

var result = pi * 2 * radius 

posługiwać się:

var result  = pi * 2
    result *= radius

Może wyglądać na mniej wydajne, ale szybki parser jest w ten sposób znacznie szybszy. Niektóre formuły się nie skompilują, jeśli mają wiele operacji, nawet jeśli są matematycznie poprawne.

Jeśli masz jakieś złożone obliczenia, umieść je w func. W ten sposób parser może go przeanalizować raz i nie musi go ponownie analizować za każdym razem, gdy zmieniasz coś w treści funkcji.

Ponieważ jeśli masz obliczenia w treści swojej funkcji, to w jakiś sposób szybki parser sprawdza je za każdym razem, czy typy, składnia itp. Są nadal poprawne. Jeśli linia zmieni się powyżej obliczenia, to niektóre zmienne w obliczeniu / wzorze mogły ulec zmianie. Jeśli umieścisz go w funkcji zewnętrznej, zostanie zweryfikowany raz i szybko jest zadowolony, że będzie poprawny i nie będzie go stale analizować, co powoduje wysokie zużycie procesora.

W ten sposób uzyskałem od 100% przy każdym naciśnięciu klawisza do niskiego poziomu procesora podczas pisania. Na przykład te 3 wiersze umieszczone w treści funkcji mogą doprowadzić do indeksowania 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 )

ale jeśli wstawię go do funkcji func i zadzwonię później, swiftparser jest znacznie szybszy

// 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 i XCode 6.1 są nadal bardzo błędne, ale jeśli zastosujesz się do tych prostych sztuczek, edycja kodu znów stanie się akceptowalna. Wolę szybki, ponieważ pozbywa się plików .h i używa znacznie czystszej składni. Wciąż jest wiele potrzebnych do rzutowania typów, takich jak "myVar as AnyObject", ale to jest mniejsze zło w porównaniu ze złożoną strukturą i składnią projektu obiektywnego c.

Inne doświadczenie, wypróbowałem SpriteKit, który jest przyjemny w użyciu, ale jest dość nieefektywny, jeśli nie potrzebujesz ciągłego malowania przy 60 klatkach na sekundę. Używanie starych CALayers jest o wiele lepsze dla procesora, jeśli twoje "duszki" nie zmieniają się tak często. Jeśli nie zmienisz zawartości .contents warstw, procesor jest w zasadzie bezczynny, ale jeśli masz aplikację SpriteKit działającą w tle, odtwarzanie wideo w innych aplikacjach może zacząć się zacinać z powodu sztywnej pętli aktualizacji 60 klatek na sekundę.

Czasami xcode wyświetla dziwne błędy podczas kompilacji, wtedy pomocne jest przejście do menu „Produkt> Wyczyść” i ponowne skompilowanie. Wydaje się, że jest to błędna implementacja pamięci podręcznej.

Kolejny świetny sposób na ulepszenie analizowania, gdy xcode utknie w kodzie, jest wspomniany w innym poście dotyczącym stackoverflow tutaj . Zasadniczo kopiujesz całą zawartość z pliku .swift do zewnętrznego edytora, a następnie kopiujesz ją z powrotem za pomocą funkcji i sprawdzasz, gdzie jest twoje wąskie gardło. To faktycznie pomogło mi przywrócić xcode do rozsądnej szybkości po tym, jak mój projekt oszalał ze 100% procesorem. kopiując swój kod z powrotem, możesz go refaktoryzować i starać się, aby ciała funkcji były krótkie, a funkcje / formuły / wyrażenia proste (lub podzielone na kilka wierszy).

Daniel Unterberger
źródło
Bardzo dokładna odpowiedź. Może niektóre sugestie są świetne jako „pierwsza pomoc”, ale tak naprawdę, czy nie spodziewamy się, że Xcode po prostu zadziała bez przechodzenia przez ogromny kłopot?
mllm
1
niestety xcode 6.1 + swift jest dość niestabilny, więc te „hacki” są potrzebne. Apple powinno naprawić Swift i Xcode. Ale szybki jest bardzo przyjemny w programowaniu, więc na krótką metę jest to jedyny sposób, aby utrzymać użycie procesora na dystans.
Daniel Unterberger
Zrobiłem wszystkie możliwe zmiany, które proponujesz, ale niestety moje autouzupełnianie nadal jest do niczego. Wątpię, czy klauzule również mogą sprawiać kłopoty. Mam na myśli powrót (a == b)? x: y
Ilker Baltaci
Cóż, pisanie kodu w określony sposób, aby uszczęśliwić IDE, jest prawdziwym nonsensem
Andrey Gordeev
10

Autouzupełnianie jest zepsute od czasu Xcode 4. Dopóki Apple nie zdecyduje się naprawić tego dwuletniego błędu, niestety jedynym rozwiązaniem jest wyłączenie uzupełniania kodu w preferencjach XCode (pierwsza opcja na poniższym zdjęciu).

Możesz nadal cieszyć się uzupełnianiem ręcznie, wpisując CTRL spacelub ESCgdy jest to potrzebne.

To jedyne rozwiązanie, które sprawdza się za każdym razem w 100% przypadków.

wprowadź opis obrazu tutaj

Inną rzeczą, którą niedawno odkryłem, jest: jeśli używasz wtyczek w Xcode, nie rób tego. Usuń je wszystkie. Pogłębiają problem.

kaczka
źródło
5

Czy używasz Spotify? Zainstalowałem Yosemite GM z Xcode 6.1 GM na iMacu w połowie 2009 roku (2,66 GHz) z tym samym problemem. Odkryłem, że proces o nazwie „SpotifyWebHelper” jest zawsze oznaczony na czerwono jako nie odpowiada, więc wyłączyłem opcję „start z sieci” w spotify i teraz wydaje się, że Xcode działa znacznie lepiej.

Eugenio Baglieri
źródło
Interesujące, ale dla mnie nie jest to związane ze Spotify ... Jednak może to pokazać, że jest to tylko „zwykły” problem z wydajnością - co oznacza - wyczyść więcej zasobów i będzie działać lepiej. To smutne, ponieważ nie mam już zasobów do zapewnienia (oprócz pieniędzy na nowy komputer Mac).
mllm
2

Dowiedziałem się, że zwykle dzieje się to, gdy:

  • mają długie wyrażenia w jednym oświadczeniu (zobacz tę odpowiedź )
  • mieszać wiele operatorów niestandardowych w jednym wyrażeniu

Wydaje się, że drugi przypadek został rozwiązany w jednym z najnowszych wydań xcode. Przykład: zdefiniowałem 2 niestandardowe operatory <&&> i <||> i użyłem w wyrażeniu takim jak a <&&> b <&&> c <||> d. Podział na wiele linii rozwiązał problem:

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

Mam nadzieję, że Twoje przypadki są objęte jednym z dwóch powyższych ... proszę o komentarz w każdym przypadku

Antonio
źródło
5
Niestety zdarza się to również w zupełnie nowym, czystym projekcie, w którym nie ma nic i wpisując coś tak prostego, jak "var s: Stri ...". Jak tylko zacznę wpisywać St ... będzie działać wolno podczas wyszukiwania sugestii ukończenia.
mllm
To zdecydowanie dla mnie argumenty. Powoduje to posiadanie więcej niż jednego operandu w tej samej linii. Dziękuję za odpowiedź. To powinna być właściwa odpowiedź
Kesava
2

Miałem te same problemy nawet w Xcode 6.3

  • bardzo wolne autouzupełnianie
  • bardzo wolne indeksowanie
  • ogromne zużycie procesora przez swift i SourceKitService
  • ogromne zużycie pamięci przez SourceKitService

Wszystko to działo się nawet przy stosunkowo niewielkim projekcie. Wypróbowałem wszystkie poprawki, które znalazłem:

  • usuwanie ~ / Library / Developer / Xcode / DerivedData / *
  • usuwanie ~ / Library / Caches / com.apple.dt.Xcode / *
  • usuń wszystkie "+" łączące łańcuchy z kodu
  • usunięto wszystkie podejrzane deklaracje słownikowe

Żadne z nich nie pomogło w moim projekcie.

To, co faktycznie rozwiązało mój problem, to:

  • umieszczanie każdego końca każdej klasy we własnym pliku
  • umieszczanie każdego rozszerzenia we własnym pliku (Class + ExtName.swift)
  • umieszczanie „szybkich metod spoza klasy” w swoim własnym pliku

Teraz mam prawie zerowe zużycie procesora, niskie zużycie pamięci i przyzwoicie szybkie uzupełnianie.

Matej Ukmar
źródło
2

Ogólnie rzecz biorąc, przeniesienie folderu pamięci podręcznej (DerivedData) na dysk SSD (szczególnie w moim przypadku - zewnętrzna pamięć masowa podłączona do wyjścia Thunderbolt) znacznie poprawiło wydajność mojego Xcode. Czas kompilacji i ogólne zastanawianie się nad aplikacją są około 10 razy szybsze. Przeniesiono również cały folder git na dysk SSD, co znacznie poprawiło wydajność git.

brkeyal
źródło
Właściwie w pierwotnym problemie już zaktualizowałem swój komputer Mac z dyskiem SSD i wszystko z niego biegło, w tym. system operacyjny i nadal były problemy
mllm
2

To było uciążliwe do XCode 7.2.

Apple naprawiło to w XCode 7.3 i teraz działa jak marzenie. Jest super szybki i znacznie potężniejszy, ponieważ wydaje się działać trochę jak rozmyte wyszukiwanie plików: nie musisz w rzeczywistości wpisywać dokładnego początku metody / właściwości, aby pojawiła się na liście propozycji.

Bioche
źródło
2

Zwinięcie wszystkich metod trochę pomaga.

Command-alt-shift-left arrow wystarczy ...

Aby złożyć / rozwinąć obecne metody lub jeśli struktury używają:

Fold: komenda-alt-strzałka w lewo

Rozwiń: polecenie-alt-strzałka w prawo

rowdyruckus
źródło
1

SourceKitServiceradzi sobie również z komentarzami w kodzie, a osadzone komentarze również go spowalniają.

więc jeśli możesz sobie pozwolić na usunięcie ogromnej ilości osadzonych komentarzy, takich jak ten:

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

to również może pomóc.


UWAGA: w moim przypadku mój Xcode 7.3.1 (7D1014) dosłownie zablokował mi wpisywanie dowolnej litery, gdy plik miał około 700 linii komentarza z osadzonymi komentarzami. początkowo usunąłem ten blok z tego .swiftpliku i Xcode znów ożył. Próbowałem dodać swoje komentarze część po części, usuwając osadzone komentarze, było to nadal wolniejsze niż zwykle, ale wykazywało znacznie lepszą wydajność, jeśli nie było osadzonych komentarzy.

holex
źródło
1

Miałem ten sam problem, w którym pisanie było opóźnione w określonej klasie i okazało się, że

/* Long multiline comments */

spowolnił pisanie.

Aziz Akgul
źródło