Page 1 of 2 1 2 LastLast
Results 1 to 15 of 16

Thread: enorme strings en pass by reference

  1. #1

    enorme strings en pass by reference

    Hoi,

    Wij werken hier met enorm grote strings (sommige wel tot 40MB). Deze strings worden aan verschillende methods doorgegeven als string variabelen by value (zonder var dus). Als je zonder var doorgeeft, wordt dan een copy gemaakt van zo'n enorme string? De Delphi help geeft voorbeelden met integers, niet met strings.

    Edit: de methods wijzigen de string overigens niet.

    Groetjes,
    Jeroen
    Last edited by Jeroen; 19-Apr-06 at 11:27.
    If you can't solve the problem, it isn't a problem... - DeleD - 3D editor project - www.delgine.com

  2. #2
    *+E13818MU01F0F* Norrit's Avatar
    Join Date
    Aug 2001
    Location
    Landgraaf
    Posts
    967
    Is PChar dan niet hetgeen je zoekt ???
    Objective reality is a delirium caused by lack of alcohol in blood

  3. #3
    Ja, dan wordt een copy gemaakt. Maar een (Ansi)String is in feite een pointer, dus wordt alleen een copy gemaakt van de pointer. Toch ontstaat er een kleine performance verbetering als je in zulke gevallen const gebruikt.
    We adore chaos because we like to restore order - M.C. Escher

  4. #4
    Zulke grote strings kunnen alleen maar van het type AnsiString zijn. Ik denk dat alleen de referencecount van dit type verhoogd wordt. Overigens zou ik toch voor een var variabele kiezen of zelfs const aangezien er toch niets gewijzigd wordt in de methods.

  5. #5
    ...of zorg dat je widestring of ansistring onderdeel is van een object dat je doorgeeft. Dan weet je zeker dat er alleen een pointer wordt doorgegeven en niet een hele string op de stack wordt gezet.
    type TViolence=class(TFear)

  6. #6
    SillyMember
    Join Date
    May 2003
    Location
    Gent
    Posts
    7,725
    @Rubus: een string is ook een pointer (zoals je ook al kon lezen in het antwoord van Lord Larry, twee posts boven die van jou).
    All methodologies are based on fear. -- Kent Beck.

  7. #7
    Senior Member Wuf's Avatar
    Join Date
    Sep 2005
    Location
    Utrecht
    Posts
    323
    volgens mij worden strings gewoon gekopieerd hoor. in C is het een array of char, maar in delphi wordt het behandelt als een normale variabele, zoals een integer. overigens kun je dat uitstekend testen mbv de taskmanager.

    [edit]
    de test met de taskmanager laat duidelijk zien dat het geheugengebruik verdubbelt
    ik ga nu kijken hoe dat het beter kan
    [/edit]

    [edit2]
    Briljant, omdat je van een TStringlist de Text property niet kunt meegeven aan een var parameter, heb ik een string gebruikt. en jawel, die waarde wordt natuurlijk ook gewoon gekopieerd.
    [/edit2]

    [edit3]
    ik heb hier een zipje staan met de test code
    grappig is dat als ik de pointer doorgeef van het eerste character, dat hij het stiekem toch kopieert
    [/edit3]

    [edit4]
    het is me niet gelukt om kopieer slagen te vermijden, maar wel om geheugen te besparen door de var parameter en een string te gebruiken. Eerst lees je het in, ik doe dat met een tstringlist, dan kopieer je de inhoud naar een gewone string en geef je de TStringlist vrij.
    vervolgens ga je er mee werken met behulp van var parameters.
    dan heb je 1 keer een kopieerslag en even wat dubbel geheugen gebruik en daarna heb je daar geen last meer van.
    [/edit4]
    Last edited by Wuf; 21-Apr-06 at 01:21.

  8. #8
    SillyMember
    Join Date
    May 2003
    Location
    Gent
    Posts
    7,725
    AnsiStrings in Delphi zijn copy-on-write.

    En AnsiStrings worden in Delphi verder helemaal niet behandeld als een integer: het zijn pointers, het nodige geheugen wordt gealloceerd op de heap, ze zijn reference counted, de pointers wijzen naar een blok geheugen met voor de 0 offset de lengte en de reference count (beiden 32 bits integers).

    Als je een string parameter met const doorgeeft kan de compiler iets meer geoptimalizeerde code genereren.

    Nogmaals: zoals ook Lord Larry en t.c. al hebben gemeld.
    Neem het nu gewoon aan.
    All methodologies are based on fear. -- Kent Beck.

  9. #9
    Counting your refs Paul-Jan's Avatar
    Join Date
    Feb 2002
    Location
    Lage Zwaluwe
    Posts
    2,160
    Wuf: als je echt wilt zien hoe e.e.a. werkt kun je beter met het CPU window aan de slag, dat is wat verhelderender dan black-box testing met de taskmanager (of all tools).

    Hee Jeroen, waarom denk je dat "iemand" in een "bepaalde" applicatie consequent "const" zet voor alle string-argumenten?

  10. #10
    Senior Member Wuf's Avatar
    Join Date
    Sep 2005
    Location
    Utrecht
    Posts
    323
    Quote Originally Posted by Dirk Andries
    AnsiStrings in Delphi zijn copy-on-write.

    En AnsiStrings worden in Delphi verder helemaal niet behandeld als een integer: het zijn pointers, het nodige geheugen wordt gealloceerd op de heap, ze zijn reference counted, de pointers wijzen naar een blok geheugen met voor de 0 offset de lengte en de reference count (beiden 32 bits integers).
    klopt, maar dat neemt Delphi voor zijn rekening, en naar de programmeur toe ga ik er altijd van uit dat het op dezelfde manier werkt als integers. dat haal ik nu ook weer uit mijn test.

    Quote Originally Posted by Dirk Andries
    Als je een string parameter met const doorgeeft kan de compiler iets meer geoptimalizeerde code genereren.

    Nogmaals: zoals ook Lord Larry en t.c. al hebben gemeld.
    Neem het nu gewoon aan.
    echt niet, als je var parameters gebruikt, dan is de kopieerslag al een stuk minder, indien je een string meerdere keren naar een procedure laat gaan.
    met const parameters werkt alleen beter indien je maar 1 keer naar een procedure gaat, en er daarna niets meer mee doet.

    ik ga vanavond mijn test eens uitbreiden met meerdere in elkaar aangeroepen procedures, dan weten we het zeker, maar met var parameters wordt er NIET gekopieerd, en met const parameter wordt er WEL gekopieerd, dat laat ik nou net met mijn test zien.

    [edit]
    ik zit hier een beetje op mijn werk dit te testen, maar bon.
    het blijkt dus dat een 2e keer aanroepen van een procedure er geen verschil meer is in geheugen. ik denk dat Delphi op de achtergrond toch wel iets nuttigs doet.

    maar als ik By Var test, dan kan ik meerdere keren een procedure in gaan, zonder dat er 1 kopieer slag aan te pas komt, behalve pointers.

    ik weet 100% zeker dat var parameters beter zijn dan const en ByValue. Overigens hoor ik net van een collega dat const en ByValue in Borland pascal wel degelijk anders zijn, daar zijn const en var gelijk aan elkaar wat betreft geheugen.
    [/edit]
    Last edited by Wuf; 21-Apr-06 at 13:29.

  11. #11
    Senior Member Wuf's Avatar
    Join Date
    Sep 2005
    Location
    Utrecht
    Posts
    323
    Quote Originally Posted by Paul-Jan
    Wuf: als je echt wilt zien hoe e.e.a. werkt kun je beter met het CPU window aan de slag, dat is wat verhelderender dan black-box testing met de taskmanager (of all tools).
    taskmanager heeft mij al veel geholpen met het oplossen van geheugen problemen met plaatjes ooit. dus het werkt ook goed met strings van 40MB, ik heb ook altijd het gevoel dat het niet nauwkeurig is, maar toch heb ik daar nooit een bewijs voor gevonden, terwijl ik er toch vaak gebruik van maak. trouwens, hoe je het ook went of keert, als ik 5 keer die string in mijn geheugen heb, en de taskmanager geeft aan dat mijn geheugen vol is, dan heb ik toch een probleem, ook al is mijn code nog zo geoptimaliseert.

    misschien dat het verhelderder werkt met het CPU window, maar ik heb een hekel aan assembly, dus niet echt mijn favoriet

  12. #12
    Je trekt je conclusies uit observaties die je doet. Observaties zijn nooit zo nauwkeurig als in de code (asm of pascal) kijkt wat er echt gebeurd. De taskmanager gebruiken voor je observaties geeft je een vertekend beeld, want Delphi heeft zijn eigen memory manager waarvan je het gedrag nauwelijks kan observeren via de task manager.

    AnsiStrings zijn weldegelijk pointers naar een record met daarin o.a. de lengte en de refcount. Het bewijs hiervan is te vinden in system.pas. Zoek maar naar PStrRec.

    const en var doen pass by reference en zonder krijg je pass by value. Bij const zorgt de compiler er nog voor dat de inhoud van de reference niet aangepast kan worden.
    We adore chaos because we like to restore order - M.C. Escher

  13. #13
    Senior Member Wuf's Avatar
    Join Date
    Sep 2005
    Location
    Utrecht
    Posts
    323
    ik weet dat ansistrings pointers zijn, maar Delphi gaat er op een speciale manier mee om, dus je hebt volledig gelijk daarin.

    en je zou idd best gelijk kunnen hebben dat de memory manager er anders mee om gaat. dat heb ik niet getest. echter zie ik wel dat er per procedure call 26MB geheugen wordt verbruikt, en dat is iets waar mijn interesse naar uitgaat, niet hoe delphi het met zijn pointers voor elkaar krijgt.

    Ik zie bij een parameter by Val dat er geen geheugen wordt gedeclareerd, en bij een const parameter( zeker bij 3 verschillende procedure aanroepen ) er telkens meer geheugen wordt gebruikt. en dat is uiteindelijk wat ik weten wil. uiteraard is ook de snelheid van belang, maar ik denk dat daarbij dezelfde conclusies getrokken kunnen worden als bij het geheugengebruik.

    Er is nog niemand die een stuk code neerzet die mij het tegendeel kan bewijzen.
    Vergis je niet, ik zeg niet dat je gelijk of ongelijk hebt, ik zeg alleen dat er enorme bakken met geheugen verdwijnen als ik met const ga werken, en meerdere keren achter elkaar een procedure in spring. Ik zat met een text op schijf van 23MB en na 3 procedures had mijn progje 78 MB in gebruik, telkens kwam er 25MB bij. De TStringlist heeft blijkbaar ook een paar MB nodig.

    overigens staat in de help van D7 het volgende:
    A constant (const) parameter is like a local constant or read-only variable. Constant parameters are similar to value parameters, except that you can't assign a value to a constant parameter within the body of a procedure or function, nor can you pass one as a var parameter to another routine. (But when you pass an object reference as a constant parameter, you can still modify the object's properties.)

    Using const allows the compiler to optimize code for structured- and string-type parameters. It also provides a safeguard against unintentionally passing a parameter by reference to another routine.

    Here, for example, is the header for the CompareStr function in the SysUtils unit:

    function CompareStr(const S1, S2: string): Integer;

    Because S1 and S2 are not modified in the body of CompareStr, they can be declared as constant parameters.
    hieruit staat in tegenstelling van wat jij zegt dat const parameters ByValue zijn, en dus niet byVar. Nogmaals mijn collega zegt dat het in Borland pascal andersom was/is.

  14. #14
    Ik heb het nog even verder uitgezocht en we hebben een beide een beetje gelijk. Hieronder volgt een quote uit de Delphi help:
    +- Delphi Help
    +- Contents
    +- Delphi Language Guide
    +- Program control
    +- Parameters and function results
    +- Parameter passing
    Variable (var) parameters are always passed by reference, as 32-bit pointers that point to the actual storage location.

    Value and constant (const) parameters are passed by value or by reference, depending on the type and size of the parameter:

    * An ordinal parameter is passed as an 8-bit, 16-bit, 32-bit, or 64-bit value, using the same format as a variable of the corresponding type.
    * A real parameter is always passed on the stack. A Single parameter occupies 4 bytes, and a Double, Comp, or Currency parameter occupies 8 bytes. A Real48 occupies 8 bytes, with the Real48 value stored in the lower 6 bytes. An Extended occupies 12 bytes, with the Extended value stored in the lower 10 bytes.
    * A short-string parameter is passed as a 32-bit pointer to a short string.
    * A long-string or dynamic-array parameter is passed as a 32-bit pointer to the dynamic memory block allocated for the long string. The value nil is passed for an empty long string.
    * A pointer, class, class-reference, or procedure-pointer parameter is passed as a 32-bit pointer.
    * A method pointer is passed on the stack as two 32-bit pointers. The instance pointer is pushed before the method pointer so that the method pointer occupies the lowest address.
    * Under the register and pascal conventions, a variant parameter is passed as a 32-bit pointer to a Variant value.
    * Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32-bit values. Larger sets, records, and static arrays are passed as 32-bit pointers to the value. An exception to this rule is that records are always passed directly on the stack under the cdecl, stdcall, and safecall conventions; the size of a record passed this way is rounded upward to the nearest double-word boundary.
    * An open-array parameter is passed as two 32-bit values. The first value is a pointer to the array data, and the second value is one less than the number of elements in the array.
    const wordt dus afhankelijk van het type By Reference of By Value. Maar (Ansi/Long)Strings vallen onder degene die By Reference worden doorgegeven. Dus ik had toch een beetje meer gelijk als jouw.

    Jouw testcode vind ik niet genoeg om het tegendeel te bewijzen. Zoals ik al zei zegt de Task Manager bijna niets.
    We adore chaos because we like to restore order - M.C. Escher

  15. #15
    SillyMember
    Join Date
    May 2003
    Location
    Gent
    Posts
    7,725
    Zelfs als de variabele niet by reference zou worden doorgegeven bij const, en zou worden gekopiëerd zijn het nog steeds maar 4 bytes die worden gekopiëerd , namelijk de pointer en niet de inhoud van de string.

    @Wuf: je "test" toont echt niets aan. Nogmaals: bekijk gewoon de door de compiler gegenereerde asm.
    Waarschijnlijk kijk je naar geheugengebruik in de TaskManager, kijk ook eens naar de VM size?
    Ik heb je "test" een weinig aangepast: vergeet niet bij het runnen af en toe de form te minimalizeren en ondertussen Geheugen en VM in de gaten te houden in TaskManager. Zie bijlage.
    Attached Files Attached Files
    All methodologies are based on fear. -- Kent Beck.

Page 1 of 2 1 2 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •