Profiling 1C-Bitrix PHP code (Xdebug, Blackfire)

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

PHP Code Profiling for 1C-Bitrix (Xdebug, Blackfire)

Page loads 4 seconds. Nginx responds quickly, MySQL is fine — but PHP spends three seconds on something unclear. Without a profiler, this is guessing. With a profiler — specific function, specific line, specific time. Let's cover two tools actually used in Bitrix projects.

Xdebug: Profiling via Cachegrind

Xdebug is a PHP extension that can record script execution traces in cachegrind format. The file opens in KCachegrind (Linux) or QCacheGrind (Windows/Mac).

Installation (PHP 8.x):

pecl install xdebug
# or via apt: apt-get install php8.2-xdebug

Configuration in php.ini or 99-xdebug.ini:

[xdebug]
zend_extension=xdebug.so
xdebug.mode=profile
xdebug.output_dir=/tmp/xdebug
xdebug.profiler_output_name=callgrind.out.%p.%r
xdebug.start_with_request=trigger

xdebug.start_with_request=trigger — profiling starts only with ?XDEBUG_PROFILE=1 GET parameter or cookie. Important: don't enable always on production — cachegrind generation kills performance.

Request with profiling:

curl "https://site.ru/catalog/product/?XDEBUG_PROFILE=1" -o /dev/null

File callgrind.out.12345.xyz appears in /tmp/xdebug. Open in KCachegrind — see call tree, time percentage for each function.

What to Look For in Bitrix Profile

Typical bottlenecks that appear in cachegrind:

  • CIBlockElement::GetList() — called dozens of times per page without cache. Search profile for total GetList time — if over 30% of PHP time, problem is caching.
  • CSQLWhere::GetQuery() — complex iblock filters without indexes.
  • CBitrixComponent::includeComponent() — if 20+ nested components, each loads templates and CSS, overhead accumulates.
  • CUser::IsAuthorized() — on some configs called on every API access, not cached between calls in one request.
  • \Bitrix\Main\ORM\Query\Query::exec() — D7 queries with fetchAll() on large selections without limit.

Blackfire: Profiling with Aggregation

Blackfire is SaaS. Agent is installed on server, PHP extension (blackfire.so) intercepts execution, data goes to blackfire.io, result is interactive call graph in browser.

Installing agent and extension:

# Agent
wget -O - https://packages.blackfire.io/gpg.key | apt-key add -
echo "deb http://packages.blackfire.io/debian any main" > /etc/apt/sources.list.d/blackfire.list
apt-get update && apt-get install blackfire

# PHP extension
apt-get install blackfire-php

# Or via PECL:
pecl install blackfire

In php.ini:

extension=blackfire.so
blackfire.agent_socket=tcp://127.0.0.1:8307

Agent authorization:

blackfire agent:config --server-id=XXXX --server-token=YYYY
blackfire agent:start

Running profiling via CLI:

blackfire run php artisan bitrix:some-command
# or via curl:
blackfire curl https://site.ru/catalog/

Via browser extension Blackfire (Chrome/Firefox) — Profile button right on page.

Xdebug vs Blackfire: When to Use What

Criterion Xdebug cachegrind Blackfire
Profiling overhead High (~10–20x slowdown) Low (~2x)
Analysis ease KCachegrind (desktop) Web interface, graph
Profile comparison Manual Built-in diff
CLI script profiling Yes Yes
Production use Not recommended Possible (carefully)
Cost Free Freemium

Xdebug — on dev server for deep diagnostics. Blackfire — when need to compare "before and after" optimization or profile staging.

Practical Optimization Algorithm

  1. Baseline measurement. Take a page, run profiler, fix top-5 functions by time.
  2. Root analysis. For each "expensive" function look at call stack — who calls it and how many times. Often GetList is expensive not itself, but because called 40 times in a row.
  3. Caching. Enable cache on component (CACHE_TYPE=A, CACHE_TIME=3600). Or cache GetList result manually via \Bitrix\Main\Data\Cache.
  4. Recheck. Profile again, compare with baseline.
  5. Query optimization. If query is slow — add needed fields to $select, remove unnecessary IBLOCK_SECTION_ID without index, rewrite from GetList to D7 ORM.

Profiling Agents and CLI

For background agents (\Bitrix\Main\Diag\ExceptionHandler), cron scripts, and CLI commands, Xdebug starts via environment variable:

XDEBUG_MODE=profile XDEBUG_OUTPUT_DIR=/tmp/xdebug php -d xdebug.start_with_request=yes /path/to/bitrix-script.php

Blackfire via CLI:

blackfire run php /path/to/bitrix-script.php

Timeline

Task Duration
Xdebug setup on dev server 2–4 hours
Blackfire setup (agent + extension) 4–6 hours
Profiling one page + report 2–4 hours
Profiling + fixing 3–5 bottlenecks 2–5 days

Profiling without subsequent optimization is pointless. We don't just take a profile and hand over a report — we fix found issues and measure the result.