Ruft new[] x mal new auf?
-
Hi
Spiele gerade ein bischen mit dem Überladen von new und new[] rum.
Bisher hatte ich nur new überladen und dadrin mal gezählt, wie oft es aufgerufen wird und wieviel Speicher belegt wird.Jetzt habe ich noch zusätzlich new[] überladen und plötzlich wird new viel seltener aufgerufen, belegt weniger Speicher etc.
Da frag ich mich, ob new[] intern vielleicht einfach x mal new aufruft. Ist das so definiert? Soll das so sein? Das ist doch verdammt ineffizient! Außerdem, wie kann new[] dann garantieren, dass alle Adressen der angeforderten Objekte linear ansteigend sind und nicht wild im Speicher verstreut? Ich meine, OK, der virtuelle Speicher mag da vielleicht für sorgen, aber so sicher kann man sich da ja auch nicht sein.
Ich benutze übrigens VS .NET.
Sehe ich das dann richtig, dass ich alleine durch das überladen von new[] und durch das anfordern von Speicher in einem PHYSIKALISCHEN Block schon bessere "locality of reference" bekomme?
Jan.
-
die implementation von new[] ist den compilerherstellern freigestellt, der standard sagt dazu nichts.
-
Jan2 schrieb:
Spiele gerade ein bischen mit dem Überladen von new und new[] rum.
Bisher hatte ich nur new überladen und dadrin mal gezählt, wie oft es aufgerufen wird und wieviel Speicher belegt wird.nette beschäftigung. was genau haste überladen?
Jetzt habe ich noch zusätzlich new[] überladen und plötzlich wird new viel seltener aufgerufen, belegt weniger Speicher etc.
kann kaum sein. da muß ein mißverständnis vorliegen.
Da frag ich mich, ob new[] intern vielleicht einfach x mal new aufruft.
eigentlich nicht. also keine funktion namens operator new. aber natürlich oft einen operator new. aber der sollte der operator new(size_t,void*) sein und der tut nix außer den konstruktor aufrufen.
Sehe ich das dann richtig, dass ich alleine durch das überladen von new[] und durch das anfordern von Speicher in einem PHYSIKALISCHEN Block schon bessere "locality of reference" bekomme?
das siehst du ganz falsch. nachdem du einen op new[] aufgerufen hast, hast di die daten in einem linearen block vorliegen.
-
Also, um etwas genauer zu sein:
Ich hab den globalen operator new (und delete) überladen.
void* operator new (size_t size);
void operator delete (void* Ptr);Der zählt, wie oft er aufgerufen wurde, wieviel Speicher er belegt hat und welche Speichergrößen wie oft angefordert wurden (1 Byte, 2 Byte, ...).
Danach hab ich noch den globalen operator new[] überladen.
void* operator new[] (size_t size);
void operator delete[] (void* ptr);Der tut im Grund dasselbe. Allerdings unterscheide ich bei meiner Statistik, ob new oder new[] aufgerufen wurde.
Bevor ich new[] überladen hatte, hat new etwa 80 MB belegt und wurde dementsprechend oft aufgerufen. Nachdem ich new[] überladen habe, der den ganzen Speicherblock via malloc anfordert (und nicht an new weitergibt), änderte sich meine Statistik drastisch, denn auf einmal wurde über new nur noch 19 MB belegt, dafür aber über new[] 61 MB. new wurde natürlich auch viel seltener aufgerufen, etc.
Das führt mich zu der Annahme, dass der Visual Studio default operator new[] einfach den operator new aufruft, für jedes Element in einem Array.
eigentlich nicht. also keine funktion namens operator new. aber natürlich oft einen operator new. aber der sollte der operator new(size_t,void*) sein und der tut nix außer den konstruktor aufrufen.
Du meinst damit einen operator new einer Klasse, kann das sein?
das siehst du ganz falsch. nachdem du einen op new[] aufgerufen hast, hast di die daten in einem linearen block vorliegen.
Dass die Daten lineare Adressen haben stimmt auf jeden Fall, sonst würde ja einiger Code abstürzen (so was a la Ptr++).
Aber das sind ja nur Adressen im virtuellen Speicher. Wenn ich ein Array nicht im ganzen anfordere, sondern in x Teilen, dann hindert das Windows ja nicht daran jedes Teil (physikalisch) an unterschiedlichen Stellen abzulegen, wo halt gerade Platz ist. Auch wenn es einfach jedesmal die virtuelle Adresse nur um eins erhöht. Und wenn es um Performance geht, dann sollten die Daten ja auch physikalisch an der gleichen Stelle liegen.
Jan.
-
Jan2 schrieb:
Also, um etwas genauer zu sein:
Ich hab den globalen operator new (und delete) überladen.
void* operator new (size_t size);
void operator delete (void* Ptr);
Der zählt, wie oft er aufgerufen wurde, wieviel Speicher er belegt hat und welche Speichergrößen wie oft angefordert wurden (1 Byte, 2 Byte, ...).ok. also die funktion namens operator new, die man aufruft mit void* p=::operator new(100);
Bevor ich new[] überladen hatte, hat new etwa 80 MB belegt und wurde dementsprechend oft aufgerufen. Nachdem ich new[] überladen habe, der den ganzen Speicherblock via malloc anfordert (und nicht an new weitergibt), änderte sich meine Statistik drastisch, denn auf einmal wurde über new nur noch 19 MB belegt, dafür aber über new[] 61 MB. new wurde natürlich auch viel seltener aufgerufen, etc.
aha.
Das führt mich zu der Annahme, dass der Visual Studio default operator new[] einfach den operator new aufruft, für jedes Element in einem Array.
mich nicht. wir reden hier nicht über die new-operatoren, sondern über die speicherbereitstellenden funktionen, die wie malloc wirken und von den operatoren aufgerufen werden.
ich denke mir, die haben das so gemacht:
void* operator new(size_t size){
return malloc(size);
}
void* operator new[](size_t size){
return operator new(size);
}eigentlich nicht. also keine funktion namens operator new. aber natürlich oft einen operator new. aber der sollte der operator new(size_t,void*) sein und der tut nix außer den konstruktor aufrufen.
Du meinst damit einen operator new einer Klasse, kann das sein?
weiß nicht mehr.
Dass die Daten lineare Adressen haben stimmt auf jeden Fall, sonst würde ja einiger Code abstürzen (so was a la Ptr++).
Aber das sind ja nur Adressen im virtuellen Speicher. Wenn ich ein Array nicht im ganzen anfordere, sondern in x Teilen, dann hindert das Windows ja nicht daran jedes Teil (physikalisch) an unterschiedlichen Stellen abzulegen, wo halt gerade Platz ist. Auch wenn es einfach jedesmal die virtuelle Adresse nur um eins erhöht. Und wenn es um Performance geht, dann sollten die Daten ja auch physikalisch an der gleichen Stelle liegen.
falsch. jeden datenzugriff jagt der prozessor durchs adressmapping. jeden. also isses gerade mal egal, ob die sachen physikalisch beisammen sind oder nicht. es gibt für's ram keinen schreib-lese-kopf, der sich bewegen müßte und der daher was von lokalität hätte. es gibt sowas nur für die auslagerungsdatei. ich gehe nicht davon aus, daß du jetzt optimieren willst, was passiert, wenn das ram alle ist?
-
Naja, es gibt aber einen Cache im Prozessor und der lädt nunmal immer ganze Bereiche aus dem RAM. Wenn also die Daten quer im RAM verteilt sind, dann muss der Prozessor ständig Daten in den Cache nachladen und wieder verwerfen. DESHALB ist es von Vorteil, wenn die Daten im RAM an gleicher Stelle liegen, wenn sie auch gleichzeitig verwendet werden sollen.
Jan.
-
ich glaube nicht das der Prozessor wild Daten aus dem Ram in den Cache läd. Der Prozessor läd die Daten die grade benötigt werden und vllt noch Daten die er benötigen wird. Da ist es egal wo die Daten im RAM stehen.