diff --git a/tests/php-unit-tests/perf-tests.xml.dist b/tests/php-unit-tests/perf-tests.xml.dist
new file mode 100644
index 0000000000..a89cd508ec
--- /dev/null
+++ b/tests/php-unit-tests/perf-tests.xml.dist
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ perf-tests
+
+
+
+
+
+
+ ../../core/apc-emulation.php
+ ../../core/ormlinkset.class.inc.php
+ ../../datamodels/2.x/itop-tickets/main.itop-tickets.php
+
+
+
+
diff --git a/tests/php-unit-tests/perf-tests/BulkDBObjectTest.php b/tests/php-unit-tests/perf-tests/BulkDBObjectTest.php
new file mode 100644
index 0000000000..e806d84b39
--- /dev/null
+++ b/tests/php-unit-tests/perf-tests/BulkDBObjectTest.php
@@ -0,0 +1,93 @@
+getTestOrgId();
+ $idx = 1;
+ $fStart = microtime(true);
+ $fMaxExecutionTimeAllowed = 40.0;
+ $iInitialPeak = 0;
+ $sInitialPeak = '';
+ $fStartLoop = $fStart;
+ for ($i = 0; $i < 3000; $i++) {
+ $oPerson = $this->CreateObject(Person::class, ['org_id' => $sOrgId, 'name' => "Person_$i", 'first_name' => 'John']);
+ if (0 == ($idx % 100)) {
+ $fDuration = microtime(true) - $fStartLoop;
+ $iMemoryPeakUsage = memory_get_peak_usage();
+ if ($iInitialPeak === 0) {
+ $iInitialPeak = $iMemoryPeakUsage;
+ $sInitialPeak = \utils::BytesToFriendlyFormat($iInitialPeak, 4);
+ }
+
+ $sCurrPeak = \utils::BytesToFriendlyFormat($iMemoryPeakUsage, 4);
+ echo "$idx ".sprintf('%.1f ms', $fDuration * 1000)." - Peak Memory Usage: $sCurrPeak\n";
+ $this->assertTrue($iMemoryPeakUsage === $iInitialPeak, "Peak memory changed from $sInitialPeak to $sCurrPeak after $idx insert loops"); $fStartLoop = microtime(true);
+
+ $fTotalDuration = microtime(true) - $fStart;
+ $sTotalDuration = sprintf('%.3f s', $fTotalDuration);
+ $this->assertTrue($fTotalDuration < $fMaxExecutionTimeAllowed, "execution time $sTotalDuration should be < $fMaxExecutionTimeAllowed ($idx insert loops)");
+ }
+ $idx++;
+ }
+
+ $fTotalDuration = microtime(true) - $fStart;
+ $sTotalDuration = sprintf('%.3f s', $fTotalDuration);
+ echo "Total duration: $sTotalDuration\n\n";
+ $this->assertTrue($fTotalDuration < $fMaxExecutionTimeAllowed, "Total execution time $sTotalDuration should be < $fMaxExecutionTimeAllowed");
+
+ //////////////////////
+ // Part 2 Fetch all the created persons
+ echo "Part 1: Fetch Persons\n";
+
+ $oSearch = DBSearch::FromOQL('SELECT Person WHERE org_id=:org_id');
+ $oSet = new DBObjectSet($oSearch, [], ['org_id' => $sOrgId]);
+ $idx = 1;
+ $iInitialPeak = 0;
+ $sInitialPeak = '';
+ $fMaxExecutionTimeAllowed = 0.5;
+ $fStart = microtime(true);
+ $fStartLoop = $fStart;
+ while ($oContact = $oSet->Fetch()) {
+ if (0 == ($idx % 100)) {
+ $fDuration = microtime(true) - $fStartLoop;
+ $iMemoryPeakUsage = memory_get_peak_usage();
+ if ($iInitialPeak === 0) {
+ $iInitialPeak = $iMemoryPeakUsage;
+ $sInitialPeak = \utils::BytesToFriendlyFormat($iInitialPeak, 4);
+ }
+
+ $sCurrPeak = \utils::BytesToFriendlyFormat($iMemoryPeakUsage, 4);
+ echo "$idx ".sprintf('%.1f ms', $fDuration * 1000)." - Peak Memory Usage: $sCurrPeak\n";
+ $this->assertTrue($iMemoryPeakUsage === $iInitialPeak, "Peak memory changed from $sInitialPeak to $sCurrPeak after $idx fetch loops");
+ $fStartLoop = microtime(true);
+
+ $fTotalDuration = microtime(true) - $fStart;
+ $sTotalDuration = sprintf('%.3f s', $fTotalDuration);
+ $this->assertTrue($fTotalDuration < $fMaxExecutionTimeAllowed, "Total execution time $sTotalDuration should be < $fMaxExecutionTimeAllowed ($idx fetch loops)");
+ }
+ $idx++;
+ }
+ $fTotalDuration = microtime(true) - $fStart;
+ $sTotalDuration = sprintf('%.3f s', $fTotalDuration);
+ echo "Total duration: $sTotalDuration\n\n";
+ $this->assertTrue($fTotalDuration < $fMaxExecutionTimeAllowed, "Total execution time $sTotalDuration should be < $fMaxExecutionTimeAllowed");
+ }
+}
\ No newline at end of file
diff --git a/tests/php-unit-tests/phpunit.xml.dist b/tests/php-unit-tests/phpunit.xml.dist
index 70b3ba5939..84af71d760 100644
--- a/tests/php-unit-tests/phpunit.xml.dist
+++ b/tests/php-unit-tests/phpunit.xml.dist
@@ -34,6 +34,9 @@
+
+ perf-tests
+
unitary-tests/application
diff --git a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php
index 63ddbff9b5..3bfc499ec6 100644
--- a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php
+++ b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php
@@ -267,7 +267,9 @@ abstract class ItopDataTestCase extends ItopTestCase
$oMyObj->DBInsert();
$iKey = $oMyObj->GetKey();
$this->debug("Created $sClass::$iKey");
- $this->aCreatedObjects[] = $oMyObj;
+ if (!static::USE_TRANSACTION) {
+ $this->aCreatedObjects[] = $oMyObj;
+ }
return $oMyObj;
}