Re: [fpc-pascal] code optimization
fpc-pascal-boun...@lists.freepascal.org scritti il 22/09/2010 08.08.45 > is this a benchmark program or a complex program you are talking about. > If it is a benchmark, then it would be interesting to see the code, > because from my experience I doubt that Delphi produces better code than > fpc (in general it is the other way round). If it is a complex program, > then you need to analyze carefully which part of the program consumes > the most time and why. A number of 50% is in anyway unrealistic (this is > something you get if you compare inlined code against uninlined) , > because the differences you get from code optimization are in a range > from +/-10% normally - unless you have found a real performance > bottleneck. And sometimes (most of) it is only an unoptimized library code. "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" Donald Knuth ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] Questions regarding arrays
Hi, I'm have some tough times with arrays (I use them very little). With trial and error I found that to use a pointer to an array of int32 values returned by a C API (Xlib to be exact), I have to define it as follows in Object Pascal. type TAtomArray = array[0..0] of TAtom; PAtomArray = ^TAtomArray; var xdndtypes: PAtomArray; a: TAtom; // just a culong type begin ... XGetWindowProperty(Display, FSrcWinHandle, XdndTypeList, 0, 16000, TBool(False), AnyPropertyType, @actualtype, @actualformat, @count, @remaining, @xdndtypes); // 'count' tells me the amount of items in the returned xdndtypes array // so I can access the array items as follows a := xdndtypes^[i] ... XFree(xdndtypes); end; Now if I change TAtomArray to the follow, then my code doesn't work. :-) TAtomArray = array of TAtom; // a dynamic array So what exactly is the difference between these two? TAtomArray = array[0..0] of TAtom; vs TAtomArray = array of TAtom; Is array[0..0] not actually a dynamic array, but just a static array with a single item? If so, then why does the returned value from the C API call, which returns a pointer to an array of culong's (normally more that one item) work? Somewhere I'm getting confused with all this, but would love to understand it correctly, and why it works. :) >From the XGetWindowProperty() man page, it says the the following about the return type which get stored in xdndtypes value (the last parameter in the declaration below). int XGetWindowProperty(Display *display, Window w, Atom property, long long_offset, long long_length, Bool delete, Atom req_type, Atom *actual_type_return, int *actual_for‐ mat_return, unsigned long *nitems_return, unsigned long *bytes_after_return, unsigned char **prop_return); "If the returned format is 32, the property data will be stored as an array of longs (which in a 64-bit application will be 64-bit values that are padded in the upper 4 bytes)." -- Regards, - Graeme - ___ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net:8080/fpgui/ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Questions regarding arrays
2010/9/22 Graeme Geldenhuys : > type > TAtomArray = array[0..0] of TAtom; > PAtomArray = ^TAtomArray; > > Now if I change TAtomArray to the follow, then my code doesn't work. :-) > > TAtomArray = array of TAtom; // a dynamic array > > So what exactly is the difference between these two? > > TAtomArray = array[0..0] of TAtom; > vs > TAtomArray = array of TAtom; > > > Is array[0..0] not actually a dynamic array, but just a static array > with a single item? If so, then why does the returned value from the C > API call, which returns a pointer to an array of culong's (normally > more that one item) work? Somewhere I'm getting confused with all > this, but would love to understand it correctly, and why it works. :) > In brief AFAIK: type T1 = array[l..h] of T3; T2 = array of T3; says that T1 is a value type and T2 is a pointer type (ptr casted deref of a T2 typed variable may(? depends on implementation) safely alias a T1 typed entity, but a pointer to a first element of a T1 value can't be safely aliased to a T2 typed entity). Additionally dynamic arrays are a compiler handled structures, the differences are similar to those between shortstrings and AnsiStrings types. -- bflm freepascal-bits.blogspot.com ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] Re: Questions regarding arrays
> unsigned char **prop_return you can actually define it as: type PAtom = ^TAtom; PPAtom = ^PAtom; and pass a PPAtom variable instead. -- View this message in context: http://free-pascal-general.1045716.n5.nabble.com/Questions-regarding-arrays-tp2849398p2849462.html Sent from the Free Pascal - General mailing list archive at Nabble.com. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] Any recommendations for a good in-memory storage type
Hi, While implementing drag-n-drop support in fpGUI, I created a TfpgMimeData class. This class will hold various data items, and a mime-type describing each of the data items. Obviously the TfpgMimeData class should be able to handle any data type. So my question is, what is a good universal type to store all kinds of data (strings, images (binary data), sound etc)? The possible ideas I can think of is the following: TByteArray Variants TMemoryStream So which one would be more fitting for any mime types, or is there another option I didn't think of? Here is a simple usage example of the TfpgMimeData class - to help put this in perspective: var m: TfpgMimeData; d: TfpgDrag; a: TfpgDropAction; begin m := TfpgMimeData.Create; m.SetData('text/plain', 'My name is Earl'); m.SetData('text/html', 'My name is Earl'); // text/plain can actually be created from this automatically m.SetData('image/png', MyPNGImage); d := TfpgDrag.Create(self); d.MimeData := m; d.StartDrag([daCopy]); // d manages the lifespan of m // d will be freed automatically when drag action is complete or cancelled end; -- Regards, - Graeme - ___ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net:8080/fpgui/ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Any recommendations for a good in-memory storage type
Personally, I would go for TMemoryStream -- Felipe Monteiro de Carvalho ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Any recommendations for a good in-memory storage type
In our previous episode, Graeme Geldenhuys said: > While implementing drag-n-drop support in fpGUI, I created a > TfpgMimeData class. This class will hold various data items, and a > mime-type describing each of the data items. Obviously the > TfpgMimeData class should be able to handle any data type. So my > question is, what is a good universal type to store all kinds of data > (strings, images (binary data), sound etc)? > The possible ideas I can think of is the following: > > TByteArray > Variants > TMemoryStream Different choices. The question is if you want some typing (if only runtime) and easy conversions, or e.g. have the data in a directly writable format. It depends on what you do most, operating on the data, or not. e.g. You can easily assign a string to a variant, but for the rest you need to more or less stream it. Same for e.g. classes. At the same time, you can very quickly dump bytearrays to disc (and tmemorystream is only a thin wrapper around one). So what do you do more? I would first try a variant. (the example code doesn't perform any action on the data of the mimetype, so it doesn't really add anything IMHO) ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Any recommendations for a good in-memory storage type
On Wed, 22 Sep 2010, Felipe Monteiro de Carvalho wrote: Personally, I would go for TMemoryStream That would be my option too. It's the most flexible. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Any recommendations for a good in-memory storage type
On 22 September 2010 12:52, Marco van de Voort wrote: > Different choices. The question is if you want some typing (if only runtime) > and easy conversions, or e.g. have the data in a directly writable format. Well, the data needs to be passed via Clipboard or Drag-n-Drop API's of the underlying system (when used from application to application), or can bypass those API's when dragging and dropping inside the same application (where a more efficient data format could be used). Currently I'm only busy with Xlib (but GDI will follow soon). There are some conversion support, like I suggested. for example: a HTML data string can be converted to a Plain Text string, by simply striping all tags. Images, Sound etc will be passed as a byte array (at least under Xlib). TfpgMimeData has the following convenience functions/properties to automatically search for the mime type and return the associated data, or if an exact mime type doesn't exist, try and do a conversion of a similar mime type (as in the case of HTML -> Plain Text). Or when setting data, use the property to determine what mime type must be associated with the data being stored. eg: TfpgMimeData property Urls (text with URI formatting property Text (text) property HTML(text with tags) function Data(mimetype) (byte array) > I would first try a variant. Just for getting the initial DND support to work under Xlib, I limited myself to text types only, so choose variant as my storage type, but now that I'm moving to the next phase (multiple data types), I am considering other storage types because I don't know if variant is suitable for binary data like sound, images etc.. I'm leaning towards TMemoryStream now. Just spotting the new incoming messages, Felipe and Michael seem to share my thoughts on that. -- Regards, - Graeme - ___ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net:8080/fpgui/ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] TEventLog.FileName : Hot to do an append to existing log file
Hi, I'm not understand how to use unit Teventlog to no create each time a new file but to append to an existing log file. I want to do something like: assign(f,filename); if FileExists(filename) then Append(f) else Rewrite(f); Writeln(f,FormatDateTime('dd/mm/ hh:nn:ss ',Now),msg); CloseFile(f); Regards, ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Any recommendations for a good in-memory storage type
In our previous episode, Graeme Geldenhuys said: > > I would first try a variant. > > Just for getting the initial DND support to work under Xlib, I limited > myself to text types only, so choose variant as my storage type, but > now that I'm moving to the next phase (multiple data types), I am > considering other storage types because I don't know if variant is > suitable for binary data like sound, images etc.. No. But it allows you to keep text as text, not as streamed value. I don't know if assigning a string to a variant is copy-on-write though. If you don't operate much on it, it doesn't matter. But the above sounds like you do most of the work on text, not binary blobs. > I'm leaning towards > TMemoryStream now. Just spotting the new incoming messages, Felipe and > Michael seem to share my thoughts on that. They didn't ask what you wanted to do exactly either :-) variants support most base Delphi types, afaik including class , interface and dyn array. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] TEventLog.FileName : Hot to do an append to existing log file
On Wed, 22 Sep 2010, phoebus phoebus wrote: Hi, I'm not understand how to use unit Teventlog to no create each time a new file but to append to an existing log file. I want to do something like: assign(f,filename); if FileExists(filename) then Append(f) else Rewrite(f); Writeln(f,FormatDateTime('dd/mm/ hh:nn:ss ',Now),msg); CloseFile(f); This is currently not possible. Please file a feature request in the bugtracker. Michael.___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Any recommendations for a good in-memory storage type
On Wed, 22 Sep 2010, Marco van de Voort wrote: In our previous episode, Graeme Geldenhuys said: I would first try a variant. Just for getting the initial DND support to work under Xlib, I limited myself to text types only, so choose variant as my storage type, but now that I'm moving to the next phase (multiple data types), I am considering other storage types because I don't know if variant is suitable for binary data like sound, images etc.. No. But it allows you to keep text as text, not as streamed value. I don't know if assigning a string to a variant is copy-on-write though. If you don't operate much on it, it doesn't matter. But the above sounds like you do most of the work on text, not binary blobs. I'm leaning towards TMemoryStream now. Just spotting the new incoming messages, Felipe and Michael seem to share my thoughts on that. They didn't ask what you wanted to do exactly either :-) variants support most base Delphi types, afaik including class , interface and dyn array. For the kind of data he is most likely to receive, a stream still seems best. For most data formats, maybe a TStringSTream is better suited. You'll have the text as data available at once, which is the most likely use anyway, and has all semantics of a stream. Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Any recommendations for a good in-memory storage type
On 22 September 2010 13:31, Marco van de Voort wrote: > > No. But it allows you to keep text as text, not as streamed value. I'll see how it goes, maybe I could store text as text, and binary as binary - this will allow for the least amount of conversions. Plus the storage variable not being used will not be initialized - to reduce memory consumption. I'll experiment further. > If you don't operate much on it, it doesn't matter. But the above sounds > like you do most of the work on text, not binary blobs. Well, that will depend on the application the developer writes, not on what I do or use. > variants support most base Delphi types, afaik including class , interface > and dyn array. Supporting delphi data types is pointless when drag and drop occurs between two applications - hence the reason I am opting for the mime-type standards. This is why I can't believe the stupid drag-n-drop support implemented in Delphi and Kylix. There, the data enters the event handler as a TObject instance, so the VCL and CLX frameworks only support drag-n-drop inside the same application. For external DND, you must revert to external OS API's - using Win32 API under Windows, and no idea what under Kylix. -- Regards, - Graeme - ___ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net:8080/fpgui/ ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re : [fpc-pascal] TEventLog.FileName : Hot to do an append to existing log file
Hi, >> This is currently not possible. Please file a feature request in the >>bugtracker. I raised into bugtracker the id: 0017464 for this feature. Regards, Phoebus ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
[fpc-pascal] Mantis for fpcprojects
Can someone from the core team advise how to handle bug reports/ feature requests for fpcprojects? Darius > Sorry, forgot to ask - to what category should I submit bugs for > > fpprofiler? I can't find anything mentioning fpprofiler in > > http://bugs.freepascal.org ... > > > Can't tell. Can anyone from FPC core advise on this? ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Any recommendations for a good in-memory storage type
Graeme Geldenhuys wrote: So which one would be more fitting for any mime types, or is there another option I didn't think of? Here is a simple usage example of the TfpgMimeData class - to help put this in perspective: This seems a lot like the BMessage class used with in the BeAPI. There is an API called MUSCLE, which originates from a project created by Jeremey Freisner for BeOS, but is now very "cross platform". It uses a Message class to implement the format you mention below. It is designed to be used for comms, so it has the concept of "flattening" data to a binary format and then "unflattening" the data at the destination. What does all this have to do with your class? I wrote an implementation for Delphi a good 5 years ago. It might be worth looking at? It was in the original MUSCLE distro, but if not, I can find you a copy. https://public.msli.com/lcs/muscle/ Messages are not the "fastest" way of storing data, but the idea of an extensible generic data storage mechanism is extremely powerful, especially for distributed comms. MUSCLE implements a whole lot more and really is worth looking at if you want to create C/S over a WAN. The MUSCLE server becomes a middle man dispatcher on to which the clients publish resources and subscribe to events. The "server" becomes another node. Really love it, would love it more if it wasn't written in C++. M var m: TfpgMimeData; d: TfpgDrag; a: TfpgDropAction; begin m := TfpgMimeData.Create; m.SetData('text/plain', 'My name is Earl'); m.SetData('text/html', 'My name is Earl'); // text/plain can actually be created from this automatically m.SetData('image/png', MyPNGImage); d := TfpgDrag.Create(self); d.MimeData := m; d.StartDrag([daCopy]); // d manages the lifespan of m // d will be freed automatically when drag action is complete or cancelled end; ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] code optimization
Hi Adrian, it is a scientific application that I have, which has about 2000 lines of code. By extracting the most time consuming routine I now have 360 lines of code. With this code I get the following runtime results: optimized FPC pascal *** is 58% SLOWER *** than optimized DELPHI 7 unoptimized FPC pascal *** is 60% SLOWER *** than optimized DELPHI 7 unoptimized Delphi 7 *** is 62% SLOWER *** than optimized DELPHI 7 Thus it looks like FPC pascal is doing very bad on optimizing the code. I agree, that I also have seen examples where FPC pascal code is about 10% faster than Delphi code. So why does FPC pascal fail on this code? I have included the code below. I compiled it with Delphi 7 , optimization on, range checking off, stack checking off, I/O checking off. For FPC pascal I used the compiler options: -Mdelphi -O3 -OpPENTIUMM -Cfsse2 -Cr- -Co- -CO- -Ci- The FPC compiler version is 2.4.0, I run under Windows XP. any suggestions? Stefan -Ursprüngliche Nachricht- Von: "Adrian Veith" Gesendet: 22.09.2010 08:08:45 An: "FPC-Pascal users discussions" Betreff: Re: [fpc-pascal] code optimization > Hi Stefan, > >is this a benchmark program or a complex program you are talking about. >If it is a benchmark, then it would be interesting to see the code, >because from my experience I doubt that Delphi produces better code than >fpc (in general it is the other way round). If it is a complex program, >then you need to analyze carefully which part of the program consumes >the most time and why. A number of 50% is in anyway unrealistic (this is >something you get if you compare inlined code against uninlined) , >because the differences you get from code optimization are in a range >from +/-10% normally - unless you have found a real performance >bottleneck. And sometimes (most of) it is only an unoptimized library code. > >Adrian. > Here is the code (I was not able to cut it down in size further): program P; {$APPTYPE CONSOLE} uses Math, SysUtils, Windows; type TRectangle = object width : Integer; Area: Int64; NextUnusedRectangle: Integer; end; TRectangleArray = Array of TRectangle; var UnsortedRectangle: TRectangleArray; NumRectangles: Integer; BoundingBox : TRectangle; function GapAlgorithm: Boolean; type TBarEntry = record Height: Integer; Width : Integer; Start : Integer; Next : Integer; Prev : Integer; end; var SolutionFound: Boolean; Bar : Array of TBarEntry; FreeBarEntry : Array of Integer; NumFreeBarEntries: Integer; NumIterations: Int64; procedure ExtendPartialSolution (NumPlacedRectangles, FirstUnusedRectangle: Integer); type TBarCase = (BarCase1, BarCase2, BarCase3, BarCase4, BarCase5, BarCase6); var i, MinValley, MinValleyWidth: Integer; PrevBar, NextBar: Integer; RectWidth : Integer; BarCase : TBarCase; NextBarWidth: Integer; NewEntry, NewEntry2 : Integer; MinValleyArea : Int64; MinValleyHeight : Integer; TotalAreaOfFittingRectangles: Int64; CurrentRectangle: Integer; PreviousRectangle : Integer; OldFirstUnusedRectangle : Integer; OldPrevNextRectangle: Integer; begin if NumPlacedRectangles = NumRectangles then begin writeln ('Solution found'); SolutionFound := true; exit; end else begin inc (NumIterations); MinValleyWidth := BoundingBox.Width+1; PrevBar := 1; i := Bar[PrevBar].Next; NextBar := Bar[i].Next; while NextBar <> 0 do begin if (Bar[i].Width< MinValleyWidth) and (Bar[PrevBar].Height > Bar[i].Height) and (Bar[NextBar].Height > Bar[i].Height) then begin MinValleyWidth := Bar[i].Width; MinValley := i; end; PrevBar := i; i := NextBar; NextBar := Bar[i].Next; end; MinValleyHeight := min(Bar[Bar[MinValley].Prev].Height, Bar[Bar[MinValley].Next].Height)- Bar[MinValley].Height; MinValleyArea := int64(MinValleyHeight) * int64(MinValleyWidth); if MinValleyWidth < BoundingBox.Width then begin TotalAreaOfFittingRectangles := 0; CurrentRectangle := FirstUnusedRectangle; while CurrentRectangle <> 0 do begin i := CurrentRectangle; if (UnsortedRectangle[i].Width <= MinValleyWidth) then inc (TotalAreaOfFittingRectangles, UnsortedRectangle[i].Area); CurrentRectangle := UnsortedRectangle[CurrentRectangle].NextUnusedRectangle end; if TotalAreaOfFittingRectangles < MinValleyArea then exit; end; PreviousRectangle := 0; CurrentRectangle := FirstUnusedRectangle; while CurrentRectangle <> 0 do begin i := CurrentRectangle; if (UnsortedRectangle[i].width <= MinValleyWidth) and (UnsortedRectangle[i].Width + Bar[MinValley].Height <= BoundingBox.Width) then begin OldFirstUnusedRectangle := FirstUnusedRectangle; OldPrevNextRectangle:= UnsortedRectangle[PreviousRectangle].NextUnusedRectangle; if CurrentRectangle = FirstUnusedRectangle then begin FirstUnusedRect
Re: [fpc-pascal] code optimization
On 22 Sep 2010, at 16:08, stefan...@web.de wrote: Thus it looks like FPC pascal is doing very bad on optimizing the code. I agree, that I also have seen examples where FPC pascal code is about 10% faster than Delphi code. So why does FPC pascal fail on this code? At first sight it looks like FPC makes less efficient use of the available registers. Other than from the machine code, it's also indicated by the program being just as fast on my PowerMac G5/1.8GHz as on an AMD Opteron 2356 at 2.3GHz (normally pretty much any reasonably modern non-netbook-class x86 trounces my 6 year old Mac regardless of the clock speed and of what you throw at them :). Interestingly, the program becomes about 20% slower when compiled by FPC for x86-64, which is odd because more registers are available there (only half as many as on the PowerPC, but still...). Delphi (Kylix) also uses a trick to avoid some multiplies with a small constant, but that has almost no influence on modern x86 cpus (the time of the FPC-compiled program barely changes if you manually apply that trick to the generated code). Jonas ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Mantis for fpcprojects
On Wed, 22 Sep 2010, Darius Blaszyk wrote: Can someone from the core team advise how to handle bug reports/ feature requests for fpcprojects? I created a new project fpcprojects, with subproject fpprofiler. You are listed as 'developer' for fpprofiler, that should be enough ? Michael. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Mantis for fpcprojects
On Wed, 2010-09-22 at 17:29 +0200, Michael Van Canneyt wrote: > I created a new project fpcprojects, with subproject fpprofiler. > You are listed as 'developer' for fpprofiler, that should be enough ? It's all I wanted ;) Thank you. ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Questions regarding arrays
Hi Graeme! Am 22.09.2010 um 11:25 schrieb Graeme Geldenhuys: > Hi, > > I'm have some tough times with arrays (I use them very little). With > trial and error I found that to use a pointer to an array of int32 > values returned by a C API (Xlib to be exact), I have to define it as > follows in Object Pascal. > > type > TAtomArray = array[0..0] of TAtom; > PAtomArray = ^TAtomArray; > > var > xdndtypes: PAtomArray; > a: TAtom; // just a culong type > begin > ... >XGetWindowProperty(Display, FSrcWinHandle, >XdndTypeList, 0, 16000, >TBool(False), >AnyPropertyType, >@actualtype, @actualformat, @count, @remaining, >@xdndtypes); >// 'count' tells me the amount of items in the returned xdndtypes array >// so I can access the array items as follows >a := xdndtypes^[i] > ... > XFree(xdndtypes); > end; > > > Now if I change TAtomArray to the follow, then my code doesn't work. :-) > > TAtomArray = array of TAtom; // a dynamic array > > > So what exactly is the difference between these two? > >TAtomArray = array[0..0] of TAtom; > vs >TAtomArray = array of TAtom; > > > Is array[0..0] not actually a dynamic array, but just a static array > with a single item? Yes. > If so, then why does the returned value from the C > API call, which returns a pointer to an array of culong's (normally > more that one item) work? Somewhere I'm getting confused with all > this, but would love to understand it correctly, and why it works. :) I assume you are running into an often made error when switching from static array to dynamic array that is used as a buffer and used with commands that expect a pointer to the buffer. For a static array the compiler knows the size of the array since it can't be changed during runtime so it doesn't need to store the array length in an internal value. So a pointer to the static array points to the first element of the array. But a dynamic array need to remember its actual size. So the internal data structure of a dynamic array will look like TDynIntegerArray = record ArraySize: Integer; Array: ^Integer; end; The real array buffer can be at a complete different place in the memory. So if you now send a pointer of TDynIntegerArray to a function that simply returns an array it will set the ArraySize to the value of the first array element. But the much more problematic part will be that if the array is bigger than SizeOf(TDynIntegerArray) it will overwrite memory that follows TDynIntegerArray and can lead to a memory access violation. So what you need to do is to send the address of the first array element, in your case @xdndtypes[0]. But I don't know if this works well with an empty dynamic array. Especially since you can only set the array size by SetLength(). If in your case you do SetLength(xdndtypes, count) after the call I would expect that it will allocate memory for the array since the new size is greater than the old size (which is 0 for an unused dyn. array) and will overwrite the pointer of your function call array. Another problem is often to free memory in Pascal that was allocated by C. The only case when I have used a dynamic array (or in the follow example a string which is a kind of dyn. char array) for a function call was when I set the array to a maximum size before the call, specify the maximum size in the call and reduced the array to the actual size after the call like: Filename: String; UsedLength: Integer; SetLength(Filename, MAXPATH); GetWhateverFilenameFromTheSystem(@Filename[1], MAXPATH, @UsedLength); // String start at index 1; SetLength(Filename, UsedLength); // or UsedLength - 1 when UsedLength includes a #0 as the char. array end indicator So when the array memory is allocated by the calling function and freed by another function and you only what to be able to access the elements using the array braces you should use the static array approach. But I would define the static array type as follows TAtomArray = array[0..MaxInt] of TAtom; // or whatever is the allowed maximum index to avoid that Pascal will raise a range checking error when you activate range checking. To prove my explanation you can simply print the memory addresses of @xdndtypes and @xdndtypes[0] for a static array and a (initialized?) dynamic array and you'll get the same addresses for the static array and different addresses for the dynamic. Regards Michael___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] Questions regarding arrays
On Thu, 23 Sep 2010 00:49:29 +0200 Michael Müller wrote: > Another problem is often to free memory in Pascal that was allocated by C. Having done some interaction with C libs IMHO the best option is not to free the memory in pascal at all but doing it with the provided C functions (if the lib does not do the freeing automatic, that is). In cases like Graemes I always used leledumbos approach which never failed me. type PAtom = ^TAtom; PPAtom = ^PAtom; This gives you access to the array but the memory management is done entirely by the lib/C-code. hih R. -- A: Because it messes up the order in which people normally read text. Q: Why is top-posting such a bad thing? A: Top-posting. Q: What is the most annoying thing in e-mail? ___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Re: [fpc-pascal] code optimization
> Message: 6 > Date: Wed, 22 Sep 2010 16:08:37 +0200 (CEST) > From: stefan...@web.de > Subject: Re: [fpc-pascal] code optimization > To: fpc-pascal@lists.freepascal.org > Message-ID: > <1487431390.1512221.1285164517310.javamail.fm...@mwmweb065> > Content-Type: text/plain; charset=UTF-8 > > Hi Adrian, > > it is a scientific application that I have, which has about 2000 lines of > code. By extracting the most time consuming routine I now have 360 lines of > code. With this code I get the following runtime results: > > optimized FPC pascal *** is 58% SLOWER *** than optimized DELPHI 7 > unoptimized FPC pascal *** is 60% SLOWER *** than optimized DELPHI 7 > unoptimized Delphi 7 *** is 62% SLOWER *** than optimized DELPHI 7 > > Thus it looks like FPC pascal is doing very bad on optimizing the code. > I agree, that I also have seen examples where FPC pascal code is about 10% > faster than Delphi code. > So why does FPC pascal fail on this code? > > I have included the code below. I compiled it with Delphi 7 , optimization > on, range checking off, stack checking off, I/O checking off. > For FPC pascal I used the compiler options: Â -Mdelphi -O3 -OpPENTIUMM > -Cfsse2 -Cr- -Co- -CO- -Ci- > The FPC compiler version is 2.4.0, I run under Windows XP. > > any suggestions? > Stefan My 2 cents: looking at the code, i would assume that you can gain by using linked lists with pointers instead of arrays and working with the index. This would reduce the number of offset calculations. However, it means quite a rewrite. So, do you really need more speed? Even the following primitive replace, which is not yet a conversion to a linked list already saved about 10% on Mac OS X: while CurrentRectangle <> 0 do begin i := CurrentRectangle; if (UnsortedRectangle[i].Width <= MinValleyWidth) then inc (TotalAreaOfFittingRectangles, UnsortedRectangle[i].Area); CurrentRectangle := UnsortedRectangle[CurrentRectangle].NextUnusedRectangle end; - var ThisUnsortedRectangle: ^TRectangle; ... while CurrentRectangle <> 0 do begin ThisUnsortedRectangle := @UnsortedRectangle[CurrentRectangle]; if (ThisUnsortedRectangle^.Width <= MinValleyWidth) then inc (TotalAreaOfFittingRectangles, ThisUnsortedRectangle^.Area); CurrentRectangle := ThisUnsortedRectangle^.NextUnusedRectangle end; Btw. profiling indicates that this loop takes over 30% of cpu time. Skipping the initial assignment (i := CurrentRectangle;) made up for about 5%. All the best Michael Schindler___ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal