Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 03/02/21 in all areas

  1. Hello all, in my quest to port a very large project -containing dozens of COM DLL's- from Delphi XE to Sydney, the main obstacle for me was the exploding executable size. Each and every DLL in my project group had grown between 1-4 megabytes and that really added up painfully. Most of that growth, of course, is due to the new extended RTTI (which I do not use). The project was already huge before, and a doubling or tripling in size would cause deployment problems (the software is used on oil wells on remote locations and bandwidth is often costly and slow). Trying to strip off some MB's wherever I could, I started studying the MAP files to make sure no unnecessary stuff was linked in. I noticed that all of my non-visual COM DLL's nevertheless pull in huge chunks of the visual VCL, including units VCL.Forms, VCL.Themes, VCL.Imagelist etc. I am absolutely sure that I don't use these routines anywhere and still they make up over 60% of the executable's code! The underlying cause is that all of the xxxx_TLB.PAS files, which the IDE auto-generates, use a unit called OleServer which has an initialization section. No code in the unit itself is called, but the initialization section manages to pull in most of the VCL for whatever reason. As a test, I made a dummy unit "oleserver.pas" and referenced it as the first file in my COM DLL applications. The project compiled fine, and this change alone instantly reduced executable size with a whopping 1 MB. And the best thing, the project still worked as expected. So it seems to me that this whole OleServer unit is an unnecessary thing in my projects. Another thing. When I link my projects against a "stripped" version of the RTL/VCL (recompiled without extended RTTI), the size difference becomes astronomic. My DLL's have now typically lost 80% of their size, going from 2MB+ to only 400kb. With these executable size reductions I am finally able to port this project to Delphi Sydney. I am in the process of writing a tool to automate the "rtti stripping" of the RTL/VCL which I plan to release as open source. For example, projects like "inno setup" might benefit from it.
  2. Lajos Juhász

    Update hidden file

    Thanks Remy I missed the part that you can give a Handle to the TFileStream constructor. You can replace the file using this code. Of course you've to make sure first the file exists: procedure TForm1.FormCreate(Sender: TObject); var lStrList: TStringList; lfStream: TFileStream; lFileName: PChar; begin lFileName:='D:\temp\0104.txt'; lStrList:=TStringList.Create; lfStream:=TFileStream.Create(Createfile(lFileName, GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, GetFileAttributes(lFileName), 0)); try lStrList.SaveToStream(lfStream); finally lfStream.Free; end; end;
  3. The main reason is in the very first sentence of my previous post. Also as you are so into benchmarking I suggest you make yourself familiar with profilers so you don't have to guess or ask others what is taking time as you can very well see for yourself.
  4. I use a RTTI-stripped version of the XE libraries since ages, because when I migrated from Delphi 2009 to XE my executable sizes also grew a lot. That RTTI stripping is much easier to achieve with XE because the {$RTTI....} directive was still a global option then, so you don't need to patch any source files. Stripping RTTI is now an integral part in my Finalbuilder build scripts. Edit: I have attached an image with the executable sizes. All executables were compiled in "release mode" without any debugging info. All executables were compiled with {$WEAKLINKRTTI ON} and {$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} in the DPR. (1) Compiled with XE10.4.2 Sydney. (2) As (1), replaced unit "Oleserver" with a dummy unit so no unnecessary VCL code is pulled in. (3) As (2), using a RTTI-Stripped RTL/VCL. (4) Compiled with Delphi XE, replaced unit "Oleserver" with a dummy unit so no unnecessary VCL code is pulled in. (5) As (4), using a RTTI-Stripped RTL/VCL.
  5. Remy Lebeau

    Update hidden file

    I said to use THandleStream, not TFileStream. TFileStream does not have a constructor that accepts an external THandle as input. Unless that is a recent addition that has not been documented yet. Sure, eg: procedure TForm1.FormCreate(Sender: TObject); var lFile: THandle; lStrList: TStringList; lStream: THandleStream; lFileName: PChar; lAttrs: DWORD; begin lStrList := TStringList.Create; try ... lFileName := 'D:\temp\0104.txt'; lAttrs := GetFileAttributes(PChar(lFileName)); if lAttrs = INVALID_FILE_ATTRIBUTES then begin if GetLastError() <> ERROR_FILE_NOT_FOUND then RaiseLastOSError; lAttrs = FILE_ATTRIBUTE_NORMAL; end; lFile := CreateFile(lFileName, GENERIC_WRITE, FILE_SHARE_WRITE, nil, CREATE_ALWAYS, lAttrs, 0); if lFile = INVALID_HANDLE_VALUE then RaiseLastOSError; try lStream := THandleStream.Create(lFile); try lStrList.SaveToStream(lStream); finally lStream.Free; end; finally CloseHandle(lFile); end; finally lStrList.Free; end; end;
  6. Lajos Juhász

    Update hidden file

    The answer is here, the TFileStream will take over the ownership and close it in the destructor (FileClose will call CloseHandle): destructor TFileStream.Destroy; begin if FHandle <> INVALID_HANDLE_VALUE then FileClose(FHandle); inherited Destroy; end;
  7. limelect

    50 Years of Pascal

    @FPiette It seems you quote my resume
  8. Remy Lebeau

    Update hidden file

    From the CreateFile documentation: So, you don't have to actually remove the attributes, just match the existing attributes. Which FileCreate() can't do. But you could call CreateFile() directly, and then wrap the HANDLE in a THandleStream if needed.
  9. FredS

    IDE Hang

    Installing MMX15 slowed down everything, had to manually change prior Delphi versions back to 14.. plus those new images aren't my taste to be polite 🙂
  10. Well, no pain, no gain. Used to I also stripped every RTTI because I was annoyed of the binary sizes, but once you get hooked with RTTI and its benefits, there is no back. I can remember watching those code snippets and conversations back to the days on G+ and always thought, man, for WTF do they need that, they are crazy.
  11. Which does absolutely nothing since like XE7 or so when they fixed the $RTTI switch to be local to the current unit.
  12. Nasreddine

    Delphi and the new Apple M1 CPU

    @Hans♫ it was permission errors but the new 11.1.2 BigSur update fixed them for the M1 target. this is a confirmed guess I think, we asked them on the latest webinar and they said that they know about the problem but they can not give any time frame about the solution.
  13. Attila Kovacs

    IDE Hang

    Well, after more than a week without MMX (removed) I can say that not just there is no more IDE Hang's but the IDE become faster. I suspect, that even after turning off the entityinsight, it sets itself to invisible but still working in the background for some reason. On the other hand I'm missing some functions very badly.
  14. Lajos Juhász

    Possible D10.4.2 issue..

    deleted
  15. David Heffernan

    Possible D10.4.2 issue..

    He isn't. He has tried one or the other, but never both.
  16. I've made a patch for this, here a copy/paste from my comment on the issue on sourceforge. I've attached the patched file on sourceforge.
  17. I would like to have a compiler option to disable modern RTTI throughout the application, including the linked standard library. Glad to hear that you managed to disable this information in your project.
  18. Lars Fosdal

    Sql Server Filtered Index

    @Dany Marmur Partitioning is what it sounds like. Like a disk can be partitioned in multiple file systems, a database table can be partitioned into multiple files. You can do this horizontally - divide up by rows - or vertically - divide up by columns. We use a horisontal partition scheme to split the transaction and movement data of each lot created, processed, stored, moved, and delivered in our 40+ warehouses by warehouse. That is many thousands of rows per day per site, and regulation says the data must be stored for certain period of time past the article expiration date. It is used for tracking purposes if a bad batch should reach the market. We would know who got it, where it has been, where it was made, and from which tanks the raw material came. Another similar database tracks who delivered to those tanks, but that is a much smaller amount of data. To oversimplify - you can use a partition key to decide how to divide the records in a table between multiple "physical" files and hence multiple indexes. If a query includes the partition key, the result set would come from one (or more) of the table partitions - giving the secondary keys a much smaller index to deal with. Partitioning gives you query performance if the partition is well designed. If the result set spans multiple partitions - each of the partition queries can be run in parallel since there is no overlap in the data, and the result set will be a union of those queries. The expression index doesn't really lack anything - partitioning is purely for dealing with massively large tables. For examples of the principles of partitioning - take a look at https://www.sqlshack.com/database-table-partitioning-sql-server/
  19. Remy Lebeau

    How to get json array from string?

    That is because IDLIST is an array (of integers), but you are trying to read it as a string. jso.GetValue('IDLIST') will return a TJSONValue pointer to a TJSONArray, which does not implement the Value() method, so it returns a blank string. You need to type-cast the TJSONValue to TJSONArray and enumerate its elements, eg: var jso: TJsonObject; jsa: TJSONArray; s, RetIDList: string; i: Integer; begin s := '{"RESULT":200, "IDLIST":[1,2,3,4,5]}'; jso := TJsonObject.ParseJSONValue(s) as TJsonObject; if jso <> nil then try ... RetIDList := ''; jsa := jso.GetValue('IDLIST') as TJSONArray; if jsa <> nil then begin if jsa.Count > 0 then begin RetIDList := jsa[0].Value; for i := 1 to jsa.Count-1 do RetIDList := RetIDList + ',' + jsa[i].Value; end; end; ... finally jso.Free; end; end;
  20. balabuev

    Delphi 10.4.2 first impressions

    I've found the reason. Auto invoke need to be unchecked. Don't know now, whether it is my fail or Auto invoke was checked by default.
  21. Clément

    Delphi 10.4.2 first impressions

    After using the IDE (10.4.2) for a few days, I wouldn't be fair to say it's just more stable. All the features I'm using are working, including Debug! Most debugging problem are solved, mostly 64bits. If you have a problem LSP you can still deactivacte it. The new LSP features are working fine for me, but it might help if one deactivate it. For instance you can disable error insight: And disable LSP: Even without those items, the IDE still has enough features to justify the migration. You can call me a dreamer ( or incorrigible optimist ), but if Emb can keep that same quality ration from 10.4 ->10.4.2, it's very likely to have a good 10.5 version. 10.4.2 is a clear improvement over 10.4.x (Error insight level at "Warnings and Above") By hovering the mouse over the yellow line, the IDE shows the warning. Cool eh?
  22. balabuev

    Delphi 10.4.2 first impressions

    With 10.5 whole cycle will repeats . So, 10.5.1 will be bugfull like hell, 10.5.2 - will look promising, 10.5.3 - slightly better.
  23. Because IComparer<T> created via TComparer.Construct (TDelegatedComparer<T>) suffer from this issue: https://www.idefixpack.de/blog/2016/05/whats-wrong-with-virtual-methods-called-through-an-interface/ Furthermore every call to GetName_TArrayBinarySearch constructs the comparer again. Eliminating that as well gives me a result of 159 vs 105 which then can be explained by the additional calls through IComparer<T> and the probably a little less optimal allocated registers in the actual method that performs the search because that is the one with many more arguments in class function TArray.BinarySearch<T>(const Values: array of T; const Item: T; out FoundIndex: Integer; const Comparer: IComparer<T>; Index, Count: Integer): Boolean; FWIW your implementation is not exactly the same as the RTL one as you exit as soon as you find a match while the RTL implementation because it returns the index goes on because it returns the first index in case there are successive elements matching.
  24. FPiette

    50 Years of Pascal

    I started to use Pascal in the beginning of '80. I don't remember the exact year but it was something like 1981. At that time I used Pascal on a Motorola 68000 development system to build an image processing system for the industry. I also used USCD Pascal but I don't remember the exact context. Later I moved to C on microcomputers and then CP/M machines and the IBM-PC. On the PC, I used Pascal MT+ at lot before using exclusively C for long time, actually until Delphi was born. And much later, in 1995, I moved to Delphi that I still use today, every days.
  25. Coniah

    Delphi 10.4.2 first impressions

    Thanks Uwe. I made the mistake of using the Migration Tool. A fresh uninstall and reinstall worked to restore a working instance of RAD Studio. I'll have to reinstall and configure the 3rd party components. I was hoping this process would get easier, and I thought the dot dot upgrades didn't require reinstalling, but I was wrong.
×