Hat jemand ein bvernünftiges foreach-makro?

  • Original von mattik
    Original von gritsch
    ... dann hab ich das optimiert (erste 4 zeichen in 2 UInt64 variablen geschoben und dann werden jeweils diese verglichen). Dann läuft das um einiges schneller.


    Mag sein. Aber ich möchte nicht derjenige sein, der Deinen Code weiterpflegen muss...


    leiber nicth der eine menshc der es weiterpflegen muss als dass es tausende von benutzern sind die nur wegen nem umsorteiren ne sekunde warten müssen...
  • du hast das outlineview in dem du sagen wir mal die ersten 30 rows siehst. dann muss erstmal rausgefunden werden welche überhaupt die ersten 30 sind weil das ja von der sortierung abhängt. dazu muss man dann schon mal das ganze durchsortieren. irgendwie muss CD das ja auch machen. also müssen dann schon mal die 50.000 einträge gefetcht werden (natürlich nur bestimmte ettribute) und anhand dessen sortiert werden und erst danach die ersten 30 einträge vollständig geladen werden. sehr sinnvoll oder?

    Ob es wohl einen Grund gibt, dass Relationen in NSSets landen?

    Ja, übrigens ist es sehr sinnvoll. Insbesondere müssen nämlich nicht die verwiesenen Objekte geladen werden. Das ist sinnvoll

    Es müssen übrigens nicht alle Eintrgäge gefetcht werden. Das ist soagr falsch, auch wenn ihr "Core Data ist ein DBMS"-Jünger nicht verstehen wollt. Nehmen wir folgende homogene Baum-Struktur:

    Quellcode

    1. 3000 Top-Level-Objekte
    2. Item
    3. Item
    4. ----
    5. Item
    6. Item
    7. Item
    8. Item
    9. Item
    10. Item
    11. Item
    12. Item
    13. Item
    14. Item
    15. Item
    16. ----
    17. Item
    18. Item
    19. 1000 TopLevel-Objekte
    Alles anzeigen


    Die Striche zeigen jetzt sozusagen die Darstellung in dem Tableview, also den Ausschnitt. Demzufolge haben wir etwa 4.000 TLOs. Nehmen wir an, in der Liste befinden sich in etwa weitere 46.000 Objekt als Subitems, Subbsubitems usw.

    Wenn man Core Data jetzt nicht vergewaltuigt und eien Fetch darauf loslässt, so muss es keinesfalls bei einer Sortierung die 50.000 Objekte laden. Da es einen *Objekt-Graphen* modelliert, holt es sich ausschließlich die 4.000 TLOs und sortiert nur *diese* Denn als Graph-Modeller kennt Core Data die Struktur *ohne* sämtliche Objekte laden zu müssen. Wenn es diese sortiert hat, muss es dann nur noch jene Subitems laden, die sichtbar sind. Es läuft also auf ein Laden von etwas mehr als 4.000 Objekten hinaus.

    Wenn jetzt allerdings jemand hingeht und mittels eines Fetches sucht, welche Objekte TLOs sind (parant-verweis 0) und diese dann sortiert, so wird in der Tat Core Data versagen. Das liegt aber nicht an Core Data, sondern daran, dasss jemand Core Data nicht verstanden hat.

    [Sortierung und Suchen]:
    Selbstverständlich kannst du dir einen solchen Hash auch in Core Data bauen. Dazu leitest du das ManagedObject ab und baust dir den bei den entsprechenden KVC-Methoden. Wo liegt da jetzt denn das Problem?

    Übrigens, und da wird es mit SQ
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • ich bezeichne das als CoreData und es versteht mich jeder (selbst du) und somit werde ich daran auch nichts ändern.

    du scheint aber nicht richtig zu lesen was ich schreibe. Ich habe geschrieben dass ich 50k einträge habe die jeweils ca 5 subItems haben. Die items und subitems liegen in zwei verschiedenen tabellen weil sie komplett andere attribute haben (die subitems "erben" die von den items mit). Folglich ist da nix mit 4000 sortieren und fertig.

    bei meiner sortierfunktion geh ich zuerst ALLE elemente durch, fülle anhand eines selectors (für ein bestimmtes attribut) die 2 genannten UInt64 variablen und lass erst dann den sortieralgho ran. Erklär mir mal wie ich das mit einem MO und KVO machen soll?

    außerdem hast du mir nicht beschrieben wie man das mit dem tippen von buchstaben hinbiegt ;)
  • Dann musst du eben nur 50.000 statt 250.000 laden. Denn auch wenn die Subitems aufgeklapppt sind, müssen sie nicht geladen werden. Die Zahlen sind doch völllig gleichgültig. Das geht mit 1 Objekt, mit 524, mit 16291 oder mit 16281102. Ebenso ist es völlig gleichgültig, ob die in verschiedenen Tabellen liegen. Das alles bekommt Core Data in den Griff. -- Solange du nicht anfängst, einen Fetch darauf zu machen, was man eben schon laut Doku nicht machen soll.

    Und wie ist das bei dir? Lädst du auch nur 50.000, wenn du den Outline-View anzeigst?

    Ich hatte dir beschrieben, wie du die Hashtabelle anlegst. In dem verweis auf die 50.000 Einträge leitest du die KVC-Methoden ab und baust dir die Einträge. Dann musst du übrigens nicht einmal allle 50.000 Einträge laden, sondern nur diese Tabelle.

    Mit dem V läuft es ebenso. Ich kann kein Problem erkennen.
    +++
    Ach, noch viel einfacher. Wieso selbst programmieren, wenn es Core Data doch schon kann. Ich mache mir einfach im haltenden Objekt eine zweite Relationship zu einer Entität "HashMO". In den KVC-Methoden des haltenden Objektes setze ich dann einfach den entsprechenden Eintrag in dem HashMO. fertig und aus die Maus.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Tom9811
    Dann musst du eben nur 50.000 statt 250.000 laden. Denn auch wenn die Subitems aufgeklapppt sind, müssen sie nicht geladen werden. Die Zahlen sind doch völllig gleichgültig. Das geht mit 1 Objekt, mit 524, mit 16291 oder mit 16281102. Ebenso ist es völlig gleichgültig, ob die in verschiedenen Tabellen liegen. Das alles bekommt Core Data in den Griff. -- Solange du nicht anfängst, einen Fetch darauf zu machen, was man eben schon laut Doku nicht machen soll.

    Und wie ist das bei dir? Lädst du auch nur 50.000, wenn du den Outline-View anzeigst?

    Ich hatte dir beschrieben, wie du die Hashtabelle anlegst. In dem verweis auf die 50.000 Einträge leitest du die KVC-Methoden ab und baust dir die Einträge. Dann musst du übrigens nicht einmal allle 50.000 Einträge laden, sondern nur diese Tabelle.

    Mit dem V läuft es ebenso. Ich kann kein Problem erkennen.


    dann soll ich also deiner meinung nach (im moment ca 30) hash-tabellen erstellen und vor allem warten? das sind ja schon 30 inserts. also 30fache zeit beim hinzufügen eines elementes in die datenbank. Und die zahl 30 steigt mit der zeit und sinkt bestimmt nicht...
  • Ob du die sofort erzeugst oder auf Anfrage, bleibt doch dir überlassen. Du kannst das beim -awakeFromInsert auf Vorrat machen oder bei den entsprechenden Add-Methoden, wenn dir der entsprechende Eintrag fehlt.

    Du kannst da auch deine eigene Implementierung reinschreiben. Einfach eine Instanzvariable anlegen, die du brauchst und los geht's. Das sind doch ganz normale Objekte, *keine Tabellenzeilen*. Mach das, was du auch in jedem anderen Objekt machen würdest. Du kannst doch den Code, der das Hashing enthält, aus deinem bisherigen Wrapper so 1:1 übernehmen. Ich nehme an, du hast so etwas:

    Quellcode

    1. @interface Wrapper : NSObject {
    2. UInt32 hash[30];
    3. }
    Und das füllst du dann auf. Bei Core Data sieht das dann so aus:

    Quellcode

    1. @interface Wrapper : NSManagedObject {
    2. UInt32 hash[30];
    3. }
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • dann mal eine frage die garnix mehr mit dem thread zu tun hat. und zwar wie handled man denn updates? Also man stelle sich vor es wird CD verwendet und alles in eine SQLite-DB gespeichert. Programm wird ausgeliefert und nach nem halben jahr wenn man die nächste version releasen will bekommt man mit dass man doch noch ne column braucht in einer bestimmten table (mit einem bestimmten wert natürlich). Wie kann man das dann handlen dass die bereits vorhandene DB geupdated wird?
  • Original von gritsch
    leiber nicth der eine menshc der es weiterpflegen muss als dass es tausende von benutzern sind die nur wegen nem umsorteiren ne sekunde warten müssen...

    Für die ersten 95% Performanz gibt es normalerweise einen sauberen Ansatz. Mit den restlichen 5% bin ich vorsichtig - eine Sekunde länger auf ein Umsortieren zu warten ist manchmal besser als 6 Monate auf das dringend notwendige Bugfix, weil die Programmierer durch ihre Optimierung ein unhandhabbares Codeknäuel produziert haben.

    Passiert nur anderen? Pustekuchen. Ich kann zur Zeit ein Lied davon singen: Gerade jetzt arbeite ich an einer Feuerwehraktion, weil Kollegen aus Performancegründen ein redundantes Modell gebaut haben und sich das nun durch interne Inkonsistenzen rächt. Und in dem Laden wissen die Leute normalerweise, was sie tun. Das System war ursprünglich gar nicht für die Weiterentwicklung ausgelegt, aber im Leben kommt es manchmal halt anders als geplant...
    Multigrad - 360°-Produktfotografie für den Mac
  • Wenn du die Zeit, die du in deine Implementierung gesteckt hast, dazu verwendet hättest, wooanders Optimieruungen vorzunehmen, müssten die User nicht eine Sekunde warten.

    Soll heißen: Es gibt im Laufzeitverhalten eine nicht zu unterschätzende Ressource, nämlich die Arbeitszeit des Entwicklers. Und in der Regel fokussieren sich Performance-Fragen nicht darauf, ob System a oder System b schneller ist, sondern darauf, ob die Zeit-Investition des Entwicklers in System a oder System b mehr bringt.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Ich hab mal einen Test gemacht mit 500000 Array-Einträgen:

    "fast Objective-C dispatch" aus

    Quellcode

    1. for-Schleife: 0.050533
    2. Enumerator: 0.04352
    3. for-Schleife mit IMP: 0.036898
    4. IMP-Enumerator: 0.030244


    "fast Objective-C dispatch" an

    Quellcode

    1. for-Schleife: 0.046042
    2. Enumerator: 0.040175
    3. for-Schleife mit IMP: 0.036273
    4. IMP-Enumerator: 0.031438


    "fast ObjC dispatch" an 1 Mio. Einträge

    Quellcode

    1. for-Schleife: 0.09171899999999999
    2. Enumerator: 0.09646399999999999
    3. for-Schleife mit IMP: 0.07196900000000001
    4. IMP-Enumerator: 0.057531


    "fast ObjC dispatch" an 2 Mio. Einträge

    Quellcode

    1. for-Schleife: 0.183548
    2. Enumerator: 0.15647
    3. for-Schleife mit IMP: 0.143701
    4. IMP-Enumerator: 0.114054


    "fast ObjC dispatch" an 3 Mio. Einträge

    Quellcode

    1. for-Schleife: 0.275115
    2. Enumerator: 0.331427
    3. for-Schleife mit IMP: 0.215473
    4. IMP-Enumerator: 0.169926


    Komische Ergebnisse. Source-Code hängt unten dran. Mach ich was falsch, oder warum ist das alles so wirr?

    Getestet auf Dual G4 1,25 Ghz.
  • Original von Tom9811
    Ach, *abwink* vom Thread-Thema sind wir schon lange entfernt.

    Für Versioning von Core Data Models gibt es ein eigenes Kapitel:
    developer.apple.com/documentat…rticles/cdVersioning.html

    Wie machst du es denn?


    aha, habs mal durchgelesen. also wenn nur ne column zu adden ist dann gehts ja mit alter table. kann man ja auch nen default-wert angeben und wenns was spezielles sein muss dann berechne ich es eben für jedes item (meist aus der datei auslesen die ich mit der row referenziere).
    Natürlich hab ich dazu die info in der table stehen um welche version es sich handelt. um genau zu sein sogar die dbVersion, die version des programmes das die datenbank zuletzt geöffnet hat und einiges mehr - man weis ja nie was man mal braucht (unter anderem auch plattformangaben etc)
  • naja, ich hab da einige zeit damit verbracht und unter anderem auch hier nen thread gestartet. Ich hab alles rausgeholt was apple bietet aber es ist dann eben an der vompare-funktion von strings gescheitert. Shark hat mir das gesagt ;)
    ich weis nicht genau welchen sortieralgo apple verwendet beim sortieren von arrays deshalb kann ich auch nichts zu den durchscnittlcihen anzahlen der vergleiche sagen aber jedenfalls waren es sehr viele. da konnte man wirklich nicht anderst optimieren (sonst hätte mir doch einer im forum nen tipp gegeben ;-))
  • @nuke: bitte aus der forschleife das anlegen der string-variable rausnehmen.

    @all: ich hab das beispiel von mattik mal auf das umgestellt was ich bereits vorher im thread beschrieben habe. zuerst das ergebnis, dann der quellcode. (übrigens, die ganze alloc-init-release geschichte ist nicht von mir sondern nuke ;-))

    2006-11-13 21:00:41.142 ArrayTest[761] Initialisierung fertig
    2006-11-13 21:00:41.245 ArrayTest[761] for-Schleife: 0.09513099999999999
    2006-11-13 21:00:42.748 ArrayTest[761] enumerator: 1.48961


    Quellcode

    1. #import <Foundation/Foundation.h>
    2. #import <sys/time.h>
    3. NSArray* createArray(int cnt)
    4. {
    5. // NSLog(@"Generiere Array mit %i Eintraegen",cnt);
    6. NSMutableArray *mar = [[NSMutableArray alloc] init];
    7. int i = 0;
    8. for(i;i<=cnt;++i) {
    9. NSString *txt = [[NSString alloc] initWithFormat:@"Test %i",i];
    10. [mar addObject:[NSArray arrayWithObject:txt]];
    11. }
    12. NSArray *ar = [[NSArray alloc] initWithArray:mar copyItems:YES];
    13. [mar release];
    14. // NSLog(@"Fertig");
    15. return ar;
    16. }
    17. int main (int argc, const char * argv[]) {
    18. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    19. unsigned cnt = 500000;
    20. NSString *value;
    21. NSArray *tmpArray;
    22. unsigned count, i;
    23. struct timeval tvS, tvE;
    24. NSArray *ar = createArray(cnt);
    25. NSEnumerator *tmpEnu, *enu = [ar objectEnumerator];
    26. NSLog(@"Initialisierung fertig");
    27. gettimeofday(&tvS,NULL);
    28. while(tmpArray = [enu nextObject])
    29. {
    30. count = [tmpArray count];
    31. for(i; i<count; ++i)
    32. {
    33. value = [tmpArray objectAtIndex:i];
    34. }
    35. }
    36. gettimeofday(&tvE,NULL);
    37. NSLog(@"for-Schleife: %0.16g", tvE.tv_sec - tvS.tv_sec + ((tvE.tv_usec - tvS.tv_usec)/1.0E6));
    38. //###########for###############
    39. enu = [ar objectEnumerator];
    40. gettimeofday(&tvS,NULL);
    41. while(tmpArray = [enu nextObject])
    42. {
    43. tmpEnu = [tmpArray objectEnumerator];
    44. while(value = [tmpEnu nextObject])
    45. {
    46. }
    47. }
    48. gettimeofday(&tvE,NULL);
    49. NSLog(@"enumerator: %0.16g", tvE.tv_sec - tvS.tv_sec + ((tvE.tv_usec - tvS.tv_usec)/1.0E6));
    50. //###########for###############
    51. [ar autorelease];
    52. [pool release];
    53. return 0;
    54. }
    Alles anzeigen
  • Original von gritsch
    @tom und mattik: ihr habt bei dem thread ja selbst mitgeholfen ;)

    Hehe, interessant zu sehen, was man damals so geschrieben hat... aber damit ist wenigstens gezeigt, dass wir mehr oder weniger wissen wovon wir reden. Und außerdem hattest Du ja damals nach dem _wie_ gefragt, nicht nach dem _ob_ ;)
    Multigrad - 360°-Produktfotografie für den Mac
  • Ist zufällig mal die Festplatte angesprungen?

    Nein, es kann da mit VM etwas zusammen hängen, mit Aufräumarbeiten usw. Entweder man macht das richtig sauber oder man wiederholt den Text n-Mal, wirft Ausreißer weg und bildett dann Durchschnitt. So einfach ist das leider alles nicht. Aber Tendenzen sind doch zu erkennen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?