Zeos connection library caching

The offical for ZeosLib 7.3 Report problems, ask for help, post proposals for the new version of Zeoslib 7.3/v8
Quick Info:
-We made two new drivers: odbc(raw and unicode version) and oledb
-GUID domain/field-defined support for FB
-extended error infos of Firebird
-performance ups are still in queue
In future some more feature will arrive, so stay tuned and don't hassitate to help
Post Reply
User avatar
aehimself
Zeos Dev Team
Zeos Dev Team
Posts: 765
Joined: 18.11.2018, 17:37
Location: Hungary

Zeos connection library caching

Post by aehimself »

I know we already talked about this but this time I'm bringing a solution proposal too.

The thing is, Zeos is automatically caching driver libraries, leaving the handles open even after a connection to a database is closed. You can reproduce the "issue" quite easily: drop a TZConnection on a form, set it to a database of your choice, finally call ZConnection1.Connect and ZConnection1.Disconnect right after it. Once the application is running, try to delete the driver .dll - it won't work as your program is still using it.

Caching is done in the TZAbstractDriver level and the cache can manually be cleared (therefore handles released) like this:

Code: Select all

Type
  THackAbstractDriver = Class(TZAbstractDriver);

Var
  drivers: IZCollection;
  driver: TZAbstractDriver;
  a: Integer;
Begin
  drivers := DriverManager.GetDrivers;

  For a := 0 To drivers.Count - 1 Do
  Begin
    driver := drivers[a] As TZAbstractDriver;

    THackAbstractDriver(driver).FCachedPlainDrivers.Clear;
  End;
End;
To be honest I don't know why this was implemented at the first place as loading the library will only be a fraction of the time spent compared to actually establisthing the connection but as I'm not questioning the viability of such cache. As I can not imagine a scenario when switching between cached and non-cached mode is actually needed I suggest to create a conditional directive like ZEOS_DISABLE_DRIVER_CACHE. When defined, I'd not even create the FCachedPlainDrivers instances to save some more resources.

What do you guys think about this solution? If agreed I can create a pull request even tonight with the changes.
Delphi 12.1, Zeos 8 from latest GIT snapshot
Using:
- MySQL server 8.0.18; libmariadb.dll 3.3.8
- Oracle server 11.2.0, 12.1.0, 19.0.0; oci.dll 21.13
- MSSQL 2012, 2019; sybdb.dll FreeTDS_2435
- SQLite 3.45.2
User avatar
aehimself
Zeos Dev Team
Zeos Dev Team
Posts: 765
Joined: 18.11.2018, 17:37
Location: Hungary

Re: Zeos connection library caching

Post by aehimself »

As it turns out FCachedPlainDrivers has to stay as the initial ones are stored here too.
So the only thing the conditional directive would do is to disable line 977 in ZDbcConnection.pas

Code: Select all

      {$IFNDEF ZEOS_DISABLE_DRIVER_CACHE}AddPlainDriverToCache(Result, Protocol, LibLocation);{$ENDIF}
Tested, works as planned.
Delphi 12.1, Zeos 8 from latest GIT snapshot
Using:
- MySQL server 8.0.18; libmariadb.dll 3.3.8
- Oracle server 11.2.0, 12.1.0, 19.0.0; oci.dll 21.13
- MSSQL 2012, 2019; sybdb.dll FreeTDS_2435
- SQLite 3.45.2
User avatar
aehimself
Zeos Dev Team
Zeos Dev Team
Posts: 765
Joined: 18.11.2018, 17:37
Location: Hungary

Re: Zeos connection library caching

Post by aehimself »

I opened two pull requests on GitHub: one for master branch, one for 7.2-patches.

Changes are exactly the same, but this feature can be ported to 7.2 - that's why the second one :)
Delphi 12.1, Zeos 8 from latest GIT snapshot
Using:
- MySQL server 8.0.18; libmariadb.dll 3.3.8
- Oracle server 11.2.0, 12.1.0, 19.0.0; oci.dll 21.13
- MSSQL 2012, 2019; sybdb.dll FreeTDS_2435
- SQLite 3.45.2
Scalmax
Fresh Boarder
Fresh Boarder
Posts: 13
Joined: 04.05.2023, 15:16

Re: Zeos connection library caching

Post by Scalmax »

aehimself wrote: 02.02.2024, 18:38 As I can not imagine a scenario when switching between cached and non-cached mode is actually needed I suggest to create a conditional directive like ZEOS_DISABLE_DRIVER_CACHE. When defined, I'd not even create the FCachedPlainDrivers instances to save some more resources.

What do you guys think about this solution? If agreed I can create a pull request even tonight with the changes.
1. More elastic solution would be to pass parameter on function/procedure call or even add procedure to clean the cache from what is clean-able.
2. You will never know all of the wet dark dreams of the managers of the Zeos users :)

Despite this obvious whining you have a working solution, which is good.
User avatar
aehimself
Zeos Dev Team
Zeos Dev Team
Posts: 765
Joined: 18.11.2018, 17:37
Location: Hungary

Re: Zeos connection library caching

Post by aehimself »

Scalmax wrote: 08.02.2024, 22:411. More elastic solution would be to pass parameter on function/procedure call or even add procedure to clean the cache from what is clean-able.
You definetly can clear the cache on-demand, see the snipplet in my first post. The reason I did not include this is I did not find a way to determine whether a driver is still in use or not - either I kill all or none.
We safely can purge the cache even every second though - due to how interfaces work an active connection will always keep it's refcount high and won't cause any connection drops (tested).
Scalmax wrote: 08.02.2024, 22:412. You will never know all of the wet dark dreams of the managers of the Zeos users :)
As I mentioned previously I simply can not imagine a project which sometimes need library caching, sometimes not. Your app either:
- Connects to a DB, does it's work and quits: doesn't matter as handles are released upon exit anyway
- Connects to the same DB, does it's work and disconnects: caching would make sense however loading the library is extremely quick. I doubt there would be a real performance drop without caching
- Connects to different DBs, does it's work and disconnects: caching makes no sense as each connection might be using a different library, rendering caching effectively irrelevant
- Connects to the same set of DBs, does it's work and disconnects: same arguement as #2

In any case I already mentioned I'm not questioning the existence of a library cache. We have a way to manually clear the cache in case of more complicated approaches, now Zeos can provide a way to disable it alltogether for simple cases. With these two available we can cover all scenarios I suppose.
Delphi 12.1, Zeos 8 from latest GIT snapshot
Using:
- MySQL server 8.0.18; libmariadb.dll 3.3.8
- Oracle server 11.2.0, 12.1.0, 19.0.0; oci.dll 21.13
- MSSQL 2012, 2019; sybdb.dll FreeTDS_2435
- SQLite 3.45.2
Post Reply