os x stehen geblieben

  • Original von Tom9811
    Ich kann dir nicht folgen:
    Ob Objective-C so etwas kann, weiß ich nicht, aber ich habe so meine Zweifel.

    Ok, die Doku sagt, man kann NSMutableDictionary die Speichergröße vorher mitteilen.

    Wo ist der Zusammenhang zu std:vector?

    Also, Jens verwendet ein NSMutableDictionary, das C++ Äquivalent wäre eine std::map oder std::multimap, denen kann ich aber sagen wie sie bitte den Speicher allozieren sollen.

    Womit wir gleich mittendrin wären. Man schreibt meist nur std::map, aber in Wahrheit ist das nur ein Typedef für:

    Quellcode

    1. using namespace std;
    2. template map<class Key, class T,
    3. class Compare = less<Key>,
    4. class Allocator = allocator<pair< const Key,T> > >
    Und den Allokator kann man selbst definieren, womit man problemlos auch auf statischen Speicher eine map verwenden kann. Das gilt für alle Containerklassen in der C++ Standardlibrary.

    Cocoa kennt so etwas scheinbar nicht, jedenfalls ist mir bei den Collections nichts Vergleichbares aufgefallen, aber in diesem Punkt wirst Du Dich besser auskennen.
  • Ich weiß, was Jens verwendet. Deine Beiträge bezogen sich aber nicht auf C++ und std:vector, sondern auf NSMutableDictionary und Objective-C.

    Um es noch einmal zusammenzufassen:
    In Objective-C geht Placement new. Das hat nichts mit std:vector zu tun.
    Collections in Cocoa allozieren *gar keine* Objekte. Das hat nichts mit std:vector zu tun.
    Die Größe der Collections in Cocoa hat nichts mit der Anzahl der allozierten Objekte zu tun, weil Collections in Cocoa *gar keine* Objekte allozieren. Das hat nichts mit std:vector zu tun.

    Ich verstehe auch immer noch nicht, wie du nach drei oder vier Beiträgen *auf einmal* auf std:vector kommst.
    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"?
  • bis lang habe ich das parsen immer in einem worker thread (über DO) gemacht. also ein dictionary pro packet. die dicts hatte ich in einem array gesammelt und wenn alle packets da drin sind habe ich den array über den DO-proxy zum haupthread geschickt. dort dann die dicts weiterverarbeitet (array controller und outline view objekte) und in den array controller geladen.


    Das ist vielleicht einfach ein wenig zu viel für DO. Letztendlich läuft das ja auf ne Kopie deines Arrays raus. Schick doch mal die einzelnen Pakete rüber und pack sie da ins Array, das wird den Hauptthread kaum überfordern die in ein Array zu packen.

    BTW: Ist es wenigstens eine TCP verbindung, die dein DO benutzt, ich meine es sollten ja alle im Netz was davon haben ;)

    Aber ich würde mir an deiner Stelle wirklich mehr Gedanken drum machen, wie du das in kleinere Häppchen verpackst. Selbst wenn du die 1.5GB in nem Array handelst willst du das ja irgendwie Verarbeiten, wahrscheinlich anzeigen. 500000 Einträge in einer TableView sind zu viel. Ich meine jetzt nicht den Rechner, sondern den User.
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • Original von kressevadder
    bis lang habe ich das parsen immer in einem worker thread (über DO) gemacht. also ein dictionary pro packet. die dicts hatte ich in einem array gesammelt und wenn alle packets da drin sind habe ich den array über den DO-proxy zum haupthread geschickt. dort dann die dicts weiterverarbeitet (array controller und outline view objekte) und in den array controller geladen.


    Das ist vielleicht einfach ein wenig zu viel für DO. Letztendlich läuft das ja auf ne Kopie deines Arrays raus. Schick doch mal die einzelnen Pakete rüber und pack sie da ins Array, das wird den Hauptthread kaum überfordern die in ein Array zu packen.

    BTW: Ist es wenigstens eine TCP verbindung, die dein DO benutzt, ich meine es sollten ja alle im Netz was davon haben ;)

    Aber ich würde mir an deiner Stelle wirklich mehr Gedanken drum machen, wie du das in kleinere Häppchen verpackst. Selbst wenn du die 1.5GB in nem Array handelst willst du das ja irgendwie Verarbeiten, wahrscheinlich anzeigen. 500000 Einträge in einer TableView sind zu viel. Ich meine jetzt nicht den Rechner, sondern den User.


    hi, also einzelne packete rueber habe ich probiert war nicht so doll weil dann die app nicht mehr auf 100% laeuft und die verarbeitung der packete langsamer wird wenn sie im vordergrund ist (die threads spielen ja ping pong und im main thread laueft ja die GUI ...).

    ich werde aber demnaechst haeppchen weise vorgehen (immer 10000 oder sowas) und noch ein paar speicheroptimierungen probieren. jetzt sind erstmal noch ne paar protocols dran :)

    gruss
    j.
    malloc: *** vm_allocate(size=1665622016) failed (error code=3)
  • Ich gehe auch davon aus, dass Cocoa malloc() schickt. Das bedeutet aber nicht zwingend, dass pro Objekterzeugung ein malloc() geschickt wird. Es würde mich auch wundern, da viele der üblicherweise allozierten Objekte nur wenige Bytes im Speicher belegen.

    Wenn der Kernel natürlich bereits derlei Intelligenz entwickelt, wäre es überflüssig. Wenn es eine Zwischenschicht macht ebenso. Ich mutmaße, dass jede Schicht ihren Senf beiträgt.

    Deshalb sagte ich ja auch, dass man sich das mal genauer anschauen müsste.
    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"?
  • Nein, ich meinte schon die Arbeit im Workerthread zu machen. Also das Parsen in ein Dictionary schon dort machen. Aber statt eines dicken Arrays mit den PaketDictionarys rüberzugeben, gibst du jedes Dictionary einzeln rüber. Das sollte eigentlich dann kein Problem sein, der Hauptthread muss ja nur noch den Zeiger ins Array schubsen.

    Ähnlich mache ich das. Im Nebenthread läuft der Sniffer. Hier werden die Rohdaten in Paket Dictionarys aufbereitet und dann rüber zum Haupthread. Allerdings mache ich das in dem Fall über shared memory mit einem Delegate, ist glaube ich performanter als über nen Port mit DO.
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • Original von kressevadder
    Nein, ich meinte schon die Arbeit im Workerthread zu machen. Also das Parsen in ein Dictionary schon dort machen. Aber statt eines dicken Arrays mit den PaketDictionarys rüberzugeben, gibst du jedes Dictionary einzeln rüber. Das sollte eigentlich dann kein Problem sein, der Hauptthread muss ja nur noch den Zeiger ins Array schubsen.

    Ähnlich mache ich das. Im Nebenthread läuft der Sniffer. Hier werden die Rohdaten in Paket Dictionarys aufbereitet und dann rüber zum Haupthread. Allerdings mache ich das in dem Fall über shared memory mit einem Delegate, ist glaube ich performanter als über nen Port mit DO.


    yep so hatte ich es schon probiert...immer nur das packet dict rueber und dort dann in den array. war wirklich nicht toll von der performance und die app hat die 100% nur erreicht wenn sie im hintergrund war.....ansonsten so bei 25% rumgemacht (und das bei den 450 000 packets). werde da demnaechst mal normale thread comunication anschauen.

    was hat es da mit shared memory und dem delegate aufsich? vorallem mit dem shared memory?

    gruss
    j.
    malloc: *** vm_allocate(size=1665622016) failed (error code=3)
  • Er meint, so habe ich ihn verstanden, dass du ein Kommunikations-Objekt hast, übder das die Daten herübregeschickt werden.

    Quellcode

    1. MyComm* comm = [[[MyComm alloc] initWithLock:lock] autorelease];
    2. [[NSThread detachNewThread:@selector(…) target:… object:comm];
    3. // Worker, in SChleife ackernd
    4. [comm lock];
    5. [comm addDictionary:newData];
    6. [comm unlock]
    7. // Main, zwischendurch
    8. [comm lock];
    9. if( [comm hasNewData] ) {
    10. // Daten abholen
    11. }
    12. [comm unlock];
    Alles anzeigen
    Du musst bei dieser Lösung lediglich aufpassen, dass du den Zugriff lockst. Sonst gibt es Kauderwelch.
    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
    Er meint, so habe ich ihn verstanden, dass du ein Kommunikations-Objekt hast, übder das die Daten herübregeschickt werden.

    Quellcode

    1. MyComm* comm = …
    2. [[NSThread detachNewThread:@selector(…) target:… object:comm];
    3. // Worker, in SChleife ackernd
    4. [comm addDictionary:newData];
    5. // Main, zwischendurch
    6. if( [comm hasNewData] ) {
    7. }

    Du musst bei dieser Lösung lediglich aufpassen, dass du den Zugriff lockst. Sonst gibt es Kauderwelch.


    ah ja so shared memory. yep verstanden - danke!
    malloc: *** vm_allocate(size=1665622016) failed (error code=3)
  • Original von Tom9811
    Ich gehe auch davon aus, dass Cocoa malloc() schickt. Das bedeutet aber nicht zwingend, dass pro Objekterzeugung ein malloc() geschickt wird. Es würde mich auch wundern, da viele der üblicherweise allozierten Objekte nur wenige Bytes im Speicher belegen.
    Ich halte die Wahrscheinlichkeit, daß für jede explizite (also nicht die über @"string" und @protocoll()) Objekterzeugung ein malloc() geschickt wird für etwa 120%.

    Das mit den kleinen Objekten mit wenigen Bytes wird genau in free() und malloc() berücksichtigt und schon optimiert. Warum soll -alloc (bzw. NSAllocateObject) das dann nochmal optimieren?

    Übrigens: es gibt auch die Funktion NSAllocateMemoryPages() wenn das mal jemand braucht.

    -- hns
  • Na, es gibt Fälle, in denen du aus deinem Code hreaus weißt, was du genau brauchst, malloc() das nicht wissen kann. In diesen Fällen kann man sich die Verwaltungsstruktur der darunterliegenden Schicht (irgendwie muss sie es ja nachhalten) sparen.

    Beispiel: Du hsat ein Objekt, welches einen Speicherblock wrappt. Dieser wird bei der Allocierung/Initialisierung erzeugt und ist danach wenigstens in seiner Größe immutable. Jetzt knnst du zwei Speicherbereiche anfordern, was die Anlage zweier Einträge in die Verwaltungsstruktur bedeutet. Das st aber nicht nötig. Da du zum jetzigen Zeitpunkt die Gesamtgröße kennst, ist es naheiegend, gleich den Gesamtspeicher anzufordern und einfach den Zeiger auf den Block zu errechnen. Dann wird nur ein Eintrag in eine Verwaltungsstruktur erzeugt. Ich hbe das etwa so gemacht, als ich (in C) eine allgemeine Struktur hatte, an der eine speziellere hing. Die Größe der Spezielleren war davon abhängig, welchen Typ ich in der allgemeinen hatte. Davon abhängig habe ich einen Block geholt und den Zeiger auf die speziellere einfach auf BlockAnfang + sizeof( Allgemeine ) gesetzt. Et voilá!

    Diese Information hat die darunter liegende Schicht nicht. Sie hat nur das Objekt. Da kannst du also nichts delegieren. Das darunter liegene malloc() wird natürlich wiederum gepackt haben, da die insgesamt 378 Bytes oder was auch immer natürlich nicht jedesmal vom System geholt wurden. Wie gesagt: Jeder gibt seinen Senf dazu.

    Wie gesagt 2: Ob es Cocoa so macht (NSString wäre dafür etwa ein Kandidat), müsste man genauer untersuchen.

    BTW: Es wird übrigens ganz gewiss nicht für jedes +alloc ein malloc() aufgrufen. Schon deshalb, weil nicht jedes +alloc überhaupt zur Allozierung eines Objektes führt. Das ist aber zugegebenermaßen schräg und nicht das Thema.
    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"?