Repository: mongodb/laravel-mongodb (PHP)

Issue:
Performance Regression 5.x
- Laravel-mongodb Version: 5.0.2
- PHP Version: 8.3.12
- Database Driver & Version: pecl/mongodb-1.20.0

### Description:

Hello,

We are experiencing a significant performance regression after upgrading to the latest version 5.0.2.

Our test suite, comprising approximately 400 tests, 2,000 assertions, and 15,000 queries, used to complete in about 15 seconds with version 4.8.0. After the upgrade, it now takes around 50 seconds to complete. (on my local dev box)

Individual HTTP requests or single tests do not exhibit any issues. In fact, performance for our average web request has slightly improved.

The issue only shows up in long-running processes, such as a test suite.

I have created a demo Laravel application that demonstrates the problem in a simple, isolated manner: [Demp-App](https://github.com/jensk/lara-mongo-debug)
We were able to reproduce the issue in 3 different environments: 
* WSL2-Ubuntu/Mongo-7 via docker, 
* Archlinux/Mongo-7 via docker, 
* Gentoo/Mongo 4.4 without docker

### Steps to reproduce
1. git clone  https://github.com/jensk/lara-mongo-debug
2. composer install
3. vendor/bin/phpunit

### Expected behaviour
Execution time of the tests should remain stable. ([Example results with 4.8](https://github.com/jensk/lara-mongo-debug/blob/main/phpunit-output-v4.8.0.txt))

### Actual behaviour
Execution time increases slightly and linearly with each call to the various methods of laravel-mongodb. (e.g. truncate, delete, create ...) ([Example results with 5.0.2](https://github.com/jensk/lara-mongo-debug/blob/main/phpunit-output-v5.0.2.txt))


Discussion: Thank you for the report and the demo app; that will definitely help us investigate. This issue is tracked in our Jira for investigation [PHPORM-248](https://jira.mongodb.org/browse/PHPORM-248).

I'll check the [`CommandSubscriber`](https://github.com/mongodb/laravel-mongodb/blob/5.x/src/CommandSubscriber.php).
Thanks for the quick response! <3
If I can help any further to track this down, please let me know.
As I suspected, it's the command subscriber that's at fault. I've open a PR to register it only when logs are enabled. https://github.com/mongodb/laravel-mongodb/pull/3167



Fix (patch):
diff --git a/src/Connection.php b/src/Connection.php
index a76ddc010..84ca97aba 100644
--- a/src/Connection.php
+++ b/src/Connection.php
@@ -48,7 +48,7 @@ class Connection extends BaseConnection
      */
     protected $connection;
 
-    private ?CommandSubscriber $commandSubscriber;
+    private ?CommandSubscriber $commandSubscriber = null;
 
     /**
      * Create a new database connection instance.
@@ -65,8 +65,6 @@ public function __construct(array $config)
 
         // Create the connection
         $this->connection = $this->createConnection($dsn, $config, $options);
-        $this->commandSubscriber = new CommandSubscriber($this);
-        $this->connection->addSubscriber($this->commandSubscriber);
 
         // Select database
         $this->db = $this->connection->selectDatabase($this->getDefaultDatabaseName($dsn, $config));
@@ -141,6 +139,40 @@ public function getDatabaseName()
         return $this->getMongoDB()->getDatabaseName();
     }
 
+    public function enableQueryLog()
+    {
+        parent::enableQueryLog();
+
+        if (! $this->commandSubscriber) {
+            $this->commandSubscriber = new CommandSubscriber($this);
+            $this->connection->addSubscriber($this->commandSubscriber);
+        }
+    }
+
+    public function disableQueryLog()
+    {
+        parent::disableQueryLog();
+
+        if ($this->commandSubscriber) {
+            $this->connection->removeSubscriber($this->commandSubscriber);
+            $this->commandSubscriber = null;
+        }
+    }
+
+    protected function withFreshQueryLog($callback)
+    {
+        try {
+            return parent::withFreshQueryLog($callback);
+        } finally {
+            // The parent method enable query log using enableQueryLog()
+            // but disables it by setting $loggingQueries to false. We need to
+            // remove the subscriber for performance.
+            if (! $this->loggingQueries) {
+                $this->disableQueryLog();
+            }
+        }
+    }
+
     /**
      * Get the name of the default database based on db config or try to detect it from dsn.
      *
@@ -203,8 +235,7 @@ public function ping(): void
     /** @inheritdoc */
     public function disconnect()
     {
-        $this->connection?->removeSubscriber($this->commandSubscriber);
-        $this->commandSubscriber = null;
+        $this->disableQueryLog();
         $this->connection = null;
     }