[c++] Section vinden voor een pointer

Pagina: 1
Acties:

Onderwerpen


  • kvdveer
  • Registratie: November 2000
  • Laatst online: 07-11-2023
Ik heb een applicatie die een eigen string klasse heeft. Nu komt de volgende declaratie vaak voor:
C++:
1
FString Dinges = FString(L"Hello world");


Door die declaratie, zitten veel strings dubbel in het geheugen: een keer in de .DATA section (of .TEXT) en een keer op de heap. Dat is natuurlijk zonde van het geheugen, en dat wil ik graag oplossen. Mijn plan is een copy-on-write in te bouwen, maar helaas kan dat niet voor alle strings:
C++:
1
2
3
4
5
6
7
8
char_t BSSBuffer[1024];
char_t DataBuffer[2] = { L'4', 0 };  // let op: niet const
const char_t TextBuffer[2] = { L'4', 0 };
void Foo()
{
    char_t StackBuffer[1024];
    // doe dingen
}

In het bovengenoemde geval moeten alle buffers behalve TextBuffer worden gekopieerd.
Om dat in te bouwen, wilde ik een functie bouwen die vaststelt of het geheugen van de string gewijzigd kan worden. Als het niet gewijzigd kan worden, dan hoef ik het dus ook niet te kopiëren.
code:
1
bool IsReadOnlyMemory(void* ptr );

Ik vermoed dat ik deze voor al mijn target platforms (win32,win64,xbox360 en ps3) opnieuw zal moeten implementeren. Xbox en PS3 mogen we hier niet bespreken (NDA stuff), maar win32 en win64 mogen gelukkig wel.
Is de bovengenoemde functie haalbaar om te implementeren? Is VirtualQuery bruikbaar, en is het sneller dan een malloc plus een memcpy?

Localhost, sweet localhost


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik denk dat je je design moet heroverwegen. In het algemeen is copy-on-write lastig in geval van multithreaded applicaties omdat je dan elke access intern moet gaan synchroniseren. En vanuit een usability standpoint kun je er bijna niet voor kiezen om synchronisatie achterwege te laten, omdat het voor de gebruiker niet te zien is of twee verschillende variabelen intern dezelfde buffer gebruiken (zeggen "FString is niet thread-safe" is dus niet genoeg, omdat een door de gebruiker gesynchroniseerde FString variabele alsnog problemen kan geven door een niet gesynchroniseerde interne buffer)

Gezien je platforms gaat dit om een game. En bij games is het vaak zo dat stringbewerkingen amper voorkomen. Veruit de meeste strings die je gaat gebruiken zullen constant zijn en nooit veranderen. Je zou wat dat betreft dus ook twee verschillende klassen kunnen overwegen - eentje die een constante string representeert die hij niet zelf managed en die je niet aan mag passen, en eentje waarbij je de string wel kan bewerken en die gewoon zijn eigen prive-buffer heeft. Je zult voor de aanpasbare strings die je initialiseert met een string natuurlijk wel wat geheugen dupliceren, maar dat is dan nog maar minimaal.

[ Voor 9% gewijzigd door .oisyn op 24-12-2009 14:11 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • kvdveer
  • Registratie: November 2000
  • Laatst online: 07-11-2023
Een nieuwe string klasse is uiteraard de beste oplossing (gamethread string, render thread string, etc.) omdat je daarmee de cross thread problemen ontloopt, maar helaas is dat niet haalbaar - syncen met onze engine leverancier wordt dan vrijwel onmogelijk.

Copy on write is wel safe als de originele buffer ongewijzigd blijft. Een algemene copy-on-write is inderdaad gruwelijk moeilijk te maken, en stel ik daarom nog uit.

Je hebt gelijk dat stringbewerkingen in games relatief zeldzaam zijn, maar helaas zijn ze er toch. Bij een normale run haal je al snel een paar honderd string constructors per seconde, het merendeel onvermijdelijk.We weten we dat bijna een megabyte aan strings zinloos gedupliceerd is in het geheugen. Dat is best jammer en daar doe ik graag iets aan... ;-)

Localhost, sweet localhost


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

kvdveer schreef op donderdag 24 december 2009 @ 14:35:
We weten we dat bijna een megabyte aan strings zinloos gedupliceerd is in het geheugen.
Maakt dat iets uit tegenwoordig? Je wilt je hele code base veel complexer maken om een megabyte geheugen uit te sparen? :?

  • kvdveer
  • Registratie: November 2000
  • Laatst online: 07-11-2023
Zoijar schreef op donderdag 24 december 2009 @ 15:44:
[...]

Maakt dat iets uit tegenwoordig? Je wilt je hele code base veel complexer maken om een megabyte geheugen uit te sparen? :?
Op PC is dat inderdaad niet echt een issue. Gameconsoles hebben echter een chronisch gebrek aan geheugen. Op huidige generatie consoles heb je, na het laden van het OS en je executable, nog zo'n 250 meg general purpose memory beschikbaar. Er is geen pagefile of zo, dus daar moet je het mee doen. Een manweek investeren om 1 megabyte aan memory te winnen wordt hier gezien als een goede investering.

Localhost, sweet localhost


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wat je evt nog zou kunnen doen is je FString klasse geen constructor geven voor const char*, maar wel voor een ander type dat een const char* wrapt, wat tevens aangeeft dat het een string literal betreft. Bijvoorbeeld:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct stringliteral
{
    const char * str;
    explicit stringliteral(const char * s) : str(s) { }
};

class FString
{
public:
    FString(stringliteral l)
    {
        // hier weet je dat het een string literal betreft zodat je speciale dingen kunt doen
    }
};

FString myString1("hoi daar"); // werkt niet
FString myString2(stringliteral("hoi daar")); // werkt wel

Natuurlijk kun je het nog steeds misbruiken door een string mee te geven die je stiekem wel kunt aanpassen, maar deze opzet dwingt af dat de gebruiker iig weet wat ie aan het doen is. Bovendien is het platform-onafhankelijk :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1