Increased linker times when using TAdvGridExcelExport

Hello,

we are using TAdvGridExcelExport quite a while now. The problem is, that the linker times are much longer since we are using it.

Our Setup:

  • C++ Builder 13.1
  • No dynamic linking
  • No linking with runtime packages
  • (We want a single Exe-File that can be used without other dependencies)

Without TAdvGridExcelExport (FlexCel) our main application needs ~10 Minutes for Compile and linking.
With the Export activated and linked it needs ~25 Minutes, which is slowing us down...

Now our workaround is a DLL which is encapsulating the Excel-Export. But since we need it to act as "pure standalone DLL", we have to:

  • Transfer the Grid Data as Binary-Data
  • Get the Formattings from the grid in the exe
  • Transfer the Formattings to the DLL
  • Create a new Grid (load binary data)
  • Reapply the Formatting
  • Export the Grid

This works in general, but i wonder if there is a better solution which:

  • Let us statically link all the needed libraries
  • Doesn't blow up the linker times

Thank you

Hi,
FlexCel is basically an "embedded Excel without UI", so yes, it is big. Still, 15 extra minutes of extra linking seems too much, I am not sure on why it can be taking so long.

Just to rule out someting in the machine (maybe some antivirus?), how long does it take you to build the demo "Custom Preview" (at <install folder>\tms.flexcel.vcl\Demo\Cpp\Modules\25.Printing and Exporting\20.CustomPreview)

What I did here was:

  • Set the configuration to Release
  • Set it to win64 (I assume your app is win64, but if not, win32 should actually be faster)
  • Turn dynamic package linking off:

  • Disabled incremental link (this option is for win32 only)

It is taking 15 seconds here to build the full application (which is not that complex in itself, but uses a lot of FlexCel functionality, linking most of it)

I'd like to see your numbers for compiling this application, because while I understand that bigger apps will have bigger linking times and it is not linear, from 15 seconds to 15 minutes there is a big difference. Could there be other option slowing this down? (like full program optimization?). Do you get extra 15 minutes both in release and debug modes? Do you get any better times if you disable your antivirus?

Finally, while I can't give a lot of workarounds here, what happens if you dynamically link FlexCel*.bpl? Bpls are dlls renamed, but they have extra information so they can work much simpler with your app. So if you are going to use a dll, I would use just a bpl instead, and ship the bpl with your app. And switching between the bpl and everything statically linked is just changing the checkbox "link with dynamic packages". You might even have the "Debug" configuration to dynamically link the FlexCel packages, and the "Release" configuration to statically link everything. So in day to day, building will be in debug and fast. For "shipping builds", those will be in release mode and slower, but it won't slow your dev

Hello adrian,

thank you for your detailed answer. We are mostly using 32bit Debug Builds at the moment.

The sample project builds in about 10-15 Seconds.

Linking dynamically leads to the behavior wo don't want (bpls, that have to be deployed with the appliction).

And linking against the bpl without dynamic linking, the Objects that are needed for exporting (for example TFont, etc.) are different in EXE and BPL just as when using a DLL if i understand it correctly - which leads to errors.

So we just stick with the DLL for the moment. I just wondered if there was a better solution or if i was missing something ...

The sample project builds in about 10-15 Seconds.

It is strange how much longer it takes with your app. I am not expert on the linking part, and I know it is not linear ( a twice the size lib won't take twice the time) but still it looks like you are hitting some border case where the linker performance is degrading exponentially. As said, I sadly can't offer a solution, but still I am curious:

  1. Does it change anything if you temporarily disable the antivirus? (I guess no, but just to be sure)
  2. If you try compiling in win64 or win64 modern, do the times get better? This is to see if this could be a particular bug in the win32 linker.

Linking dynamically leads to the behavior wo don't want (bpls, that have to be deployed with the appliction).

Yes, I understand that, and again I wish I could provide some better solution. I was just pointing out that deploying bpls with your app is no worse than deploying a dll (which as I understood is what you are currently doing). In fact, while the best is of course a single exe, deploying a bpl should still be better than a dll, since the bpl has some additional checks (That it, you shouldn't be able to use a bpl from a different delphi version, so no problems with a different TFont)

One approach you could use, both it using bpls or dlls to be completely sure, is that when you call the bpl/dll, you verify the version of the bpl/dll, and if it is not the exact number you expect, you refuse to run the app. This is an approach we follow in FlexCel dll ( TMS FlexCel DLL Read, write, manipulate .XLS, .XLSX files and generate PDF or HTML reports from any Windows programming language or application scripting )

The dll provides a XLVersion method:

procedure CheckVersion;
var
  dllVer: Int32;
const
  {$INCLUDE FlexCelDllVersion.inc}
begin
  dllVer := XLVersion;
  if (dllVer <> FlexCelDllVersion32)
    then raise Exception.Create('The version of ' + FLEXCELDLL + ' doesn''t match the version used in the application. '
    + 'Make sure the correct dll is available. '
    + 'Application Version: ' + GetVerStr(FlexCelDllVersion32) + '. FlexCelDyn version: ' + GetVerStr(dllVer));

end;

And in the calling side, we call this code:

procedure CheckVersion;
var
  dllVer: Int32;
const
  {$INCLUDE FlexCelDllVersion.inc}
begin
  dllVer := XLVersion;
  if (dllVer <> FlexCelDllVersion32)
    then raise Exception.Create('The version of ' + FLEXCELDLL + ' doesn''t match the version used in the application. '
    + 'Make sure the correct dll is available. '
    + 'Application Version: ' + GetVerStr(FlexCelDllVersion32) + '. FlexCelDyn version: ' + GetVerStr(dllVer));

end;

So we are sure that the dll we are calling is exactly the version we compiled against. This way we avoid the possibility of using the wrong dll and having, as you mention, wrong objects called and weird errors. If you also ship the dll or bpl with your app, instead of copying it so some shared place like system32, well, it should be not that different from a single exe. Local dlls/bpls are used first if available, so even if you have the wrong dll in system32 or somewhere in your path, the app will load the bpl that is shipped together with the exe.

Again, I am not arguing that a single exe isn't the best solution, I am just saying that you can also use bpls if you ship them with the exe instead of putting them somewhere in the PATH (which is what causes all problems), and you also check that the exact bpl you expect is there. And between shipping a dll or a bpl, I would choose a bpl since you can, as you mention, pass TFonts and stuff. A dll won't even let you pass a string.

And of course, the other thing I mention is that you can have a mixed approach here:

  1. For release builds (the ones you ship to your customers), ship a single exe. Release builds can normally take a little longer, because they aren't so common, and you can let them working overnight in a nightly build.
  2. For dev, keep with the dll/bpl approach. In fact, you could even use more dynamic bpls to try to make the time faster than 10 minutes. But you don't ship that to your clients, you just use it to speed up development. When doing the nightly build, you just wait a little longer.