Насколько быстро PHP читает Excel
Открытое сравнение avadim/fast-excel-reader с основными библиотеками чтения XLSX: сколько времени и сколько памяти уходит на один и тот же файл. Замеры выполняются на реальных файлах в изолированных процессах — и вы можете прогнать тот же тест на собственном файле, без регистрации.
Что сравнивается
FastExcelReader v3.2.0 потоковая предмет теста
Потоковый XMLReader поверх ZIP; строки отдаются генератором nextRow().
OpenSpout v5.8.0 потоковая
Наследник box/spout. Потоковые итераторы; shared strings кэшируются на диск при нехватке памяти.
PhpSpreadsheet 5.9.0
Строит полную объектную модель книги. Замеряется в режиме setReadDataOnly(true) — без стилей и формул.
SimpleXLSX 1.1.16
Один класс без зависимостей. readRows() — генератор, но XML листа целиком лежит в SimpleXMLElement.
Результаты на подготовленных файлах
Семь наборов разной формы: от небольшой выгрузки до таблицы на миллион ячеек, отдельно — широкая таблица, отдельно — текст в словаре sharedStrings и тот же текст инлайном. Каждый файл можно скачать и перепроверить результат у себя. Прогон от 22.07.2026, по 5 повторов на замер, показана медиана.
- Всего 21 замер: 7 наборов × 3 сценария. Чаще всех оказывался самым быстрым SimpleXLSX (14), самым экономным по памяти — OpenSpout (21). У FastExcelReader 5 побед по скорости и 0 по памяти.
- Попарно с FastExcelReader по всем замерам (медиана отношения): OpenSpout — по времени медленнее в 2,13 раза, по памяти легче в 1,45 раза; PhpSpreadsheet — по времени медленнее в 4,01 раза, по памяти тяжелее в 8,33 раза; SimpleXLSX — по времени быстрее в 1,55 раза, по памяти тяжелее в 2,93 раза.
- Расход памяти почти не зависит от размера файла у: OpenSpout. Такие библиотеки безопасно ставить туда, где размер входного файла заранее неизвестен.
- Пик памяти растёт вместе с файлом у: FastExcelReader (×16,5), PhpSpreadsheet (×45,5), SimpleXLSX (×56,6) — разница между самым маленьким и самым большим набором.
- Один и тот же текст, записанный через словарь sharedStrings, читается не так, как записанный инлайном. По времени на словаре: FastExcelReader — на 23% медленнее; OpenSpout — на 21% медленнее; SimpleXLSX — на 29% медленнее.
- Словарь sharedStrings дороже по памяти — библиотеки держат его целиком в ОЗУ. Инлайн против словаря: FastExcelReader — 1,8 МБ против 26,5 МБ (×14,5); OpenSpout — 1,3 МБ против 3,2 МБ (×2,50). Если вы сами генерируете файлы для последующего чтения, это заметный рычаг.
- Стоимость «открыть файл и получить первую строку» на самом большом наборе: FastExcelReader — 566 мс, OpenSpout — 1,24 с, PhpSpreadsheet — 3,65 с, SimpleXLSX — 1,37 с. Это важно для валидации заголовков перед импортом.
| Набор | FastExcelReader | OpenSpout | PhpSpreadsheet | SimpleXLSX |
|---|---|---|---|---|
|
small-1k 1 001 × 12, 84,5 КБ |
45 мс ×1,70 |
86 мс ×3,23 |
174 мс ×6,55 |
27 мс |
|
medium-20k 20 001 × 15, 2,0 МБ |
1,05 с ×1,55 |
2,27 с ×3,33 |
4,18 с ×6,14 |
681 мс |
|
large-100k 100 001 × 10, 6,4 МБ |
3,38 с ×1,54 |
6,95 с ×3,16 |
14,03 с ×6,38 |
2,20 с |
|
wide-2k-x-150 2 001 × 150, 2,1 МБ |
1,07 с ×1,58 |
3,16 с ×4,66 |
4,04 с ×5,95 |
679 мс |
|
strings-40k-shared 40 001 × 8, 1,9 МБ |
1,35 с ×1,50 |
3,03 с ×3,37 |
4,51 с ×5,01 |
900 мс |
|
strings-40k-inline 40 001 × 8, 1,7 МБ |
1,09 с ×1,57 |
2,50 с ×3,58 |
4,54 с ×6,50 |
699 мс |
|
numeric-40k 40 001 × 10, 2,6 МБ |
1,11 с ×1,60 |
1,97 с ×2,84 |
4,96 с ×7,13 |
695 мс |
| Набор | FastExcelReader | OpenSpout | PhpSpreadsheet | SimpleXLSX |
|---|---|---|---|---|
|
small-1k 1 001 × 12, 84,5 КБ |
2,0 МБ ×1,15 |
1,7 МБ |
12,3 МБ ×7,27 |
2,7 МБ ×1,61 |
|
medium-20k 20 001 × 15, 2,0 МБ |
13,5 МБ ×4,59 |
2,9 МБ |
198 МБ ×67,5 |
49,2 МБ ×16,8 |
|
large-100k 100 001 × 10, 6,4 МБ |
30,2 МБ ×10,5 |
2,9 МБ |
561 МБ ×195 |
155 МБ ×53,9 |
|
wide-2k-x-150 2 001 × 150, 2,1 МБ |
14,0 МБ ×4,83 |
2,9 МБ |
201 МБ ×69,4 |
47,8 МБ ×16,5 |
|
strings-40k-shared 40 001 × 8, 1,9 МБ |
26,5 МБ ×8,39 |
3,2 МБ |
234 МБ ×74,2 |
70,4 МБ ×22,3 |
|
strings-40k-inline 40 001 × 8, 1,7 МБ |
1,8 МБ ×1,45 |
1,3 МБ |
214 МБ ×170 |
81,2 МБ ×64,3 |
|
numeric-40k 40 001 × 10, 2,6 МБ |
1,8 МБ ×1,38 |
1,3 МБ |
218 МБ ×164 |
49,0 МБ ×37,0 |
Разбор по наборам
Внутри каждого набора — все три сценария и подробная таблица с минимумом, максимумом и счётчиками прочитанных строк.
Небольшой отчёт — 1 000 × 12
Скачать этот файл ↓Типичная выгрузка из админки: смешанные типы, немного данных.
Чтение всех строк
Основной сценарий: пройти по всем строкам первого листа и получить значения ячеек. Значения не накапливаются в памяти — там, где библиотека умеет отдавать строки потоком, используется поток.
Открытие + первая строка
Сколько стоит просто открыть файл и получить первую строку. Показывает, обязана ли библиотека разобрать весь документ до того, как отдаст первые данные.
Весь лист в массив
Весь лист загружается в один PHP-массив. Самый частый способ использования и самый тяжёлый по памяти.
Все цифры таблицей
| Библиотека | Сценарий | Время (медиана) | Мин | Макс | Пик памяти | Прочитано строк | Непустых ячеек |
|---|---|---|---|---|---|---|---|
| SimpleXLSX | Чтение всех строк | 27 мс | 27 мс | 27 мс | 2,7 МБ | 1 001 | 11 814 |
| FastExcelReader | Чтение всех строк | 45 мс | 45 мс | 48 мс | 2,0 МБ | 1 001 | 11 814 |
| OpenSpout | Чтение всех строк | 86 мс | 85 мс | 87 мс | 1,7 МБ | 1 001 | 11 814 |
| PhpSpreadsheet | Чтение всех строк | 174 мс | 174 мс | 174 мс | 12,3 МБ | 1 001 | 11 814 |
| FastExcelReader | Открытие + первая строка | 11 мс | 11 мс | 12 мс | 2,0 МБ | 1 | 12 |
| OpenSpout | Открытие + первая строка | 16 мс | 16 мс | 16 мс | 1,7 МБ | 1 | 12 |
| SimpleXLSX | Открытие + первая строка | 17 мс | 17 мс | 17 мс | 2,7 МБ | 1 | 12 |
| PhpSpreadsheet | Открытие + первая строка | 57 мс | 57 мс | 57 мс | 5,7 МБ | 1 | 12 |
| SimpleXLSX | Весь лист в массив | 26 мс | 26 мс | 27 мс | 2,7 МБ | 1 001 | 11 814 |
| FastExcelReader | Весь лист в массив | 46 мс | 46 мс | 46 мс | 2,3 МБ | 1 001 | 11 814 |
| OpenSpout | Весь лист в массив | 86 мс | 85 мс | 87 мс | 2,0 МБ | 1 001 | 11 814 |
| PhpSpreadsheet | Весь лист в массив | 171 мс | 170 мс | 172 мс | 12,5 МБ | 1 001 | 11 814 |
Средняя выгрузка — 20 000 × 15
Скачать этот файл ↓Рабочий объём для импорта заказов или товаров.
Чтение всех строк
Основной сценарий: пройти по всем строкам первого листа и получить значения ячеек. Значения не накапливаются в памяти — там, где библиотека умеет отдавать строки потоком, используется поток.
Открытие + первая строка
Сколько стоит просто открыть файл и получить первую строку. Показывает, обязана ли библиотека разобрать весь документ до того, как отдаст первые данные.
Весь лист в массив
Весь лист загружается в один PHP-массив. Самый частый способ использования и самый тяжёлый по памяти.
Все цифры таблицей
| Библиотека | Сценарий | Время (медиана) | Мин | Макс | Пик памяти | Прочитано строк | Непустых ячеек |
|---|---|---|---|---|---|---|---|
| SimpleXLSX | Чтение всех строк | 681 мс | 679 мс | 681 мс | 49,2 МБ | 20 001 | 295 975 |
| FastExcelReader | Чтение всех строк | 1,05 с | 1,05 с | 1,06 с | 13,5 МБ | 20 001 | 295 975 |
| OpenSpout | Чтение всех строк | 2,27 с | 2,27 с | 2,27 с | 2,9 МБ | 20 001 | 295 975 |
| PhpSpreadsheet | Чтение всех строк | 4,18 с | 4,17 с | 4,19 с | 198 МБ | 20 001 | 295 975 |
| FastExcelReader | Открытие + первая строка | 213 мс | 212 мс | 216 мс | 13,5 МБ | 1 | 15 |
| SimpleXLSX | Открытие + первая строка | 437 мс | 437 мс | 438 мс | 49,2 МБ | 1 | 15 |
| OpenSpout | Открытие + первая строка | 460 мс | 458 мс | 460 мс | 2,1 МБ | 1 | 15 |
| PhpSpreadsheet | Открытие + первая строка | 1,17 с | 1,14 с | 1,18 с | 28,7 МБ | 1 | 15 |
| SimpleXLSX | Весь лист в массив | 678 мс | 678 мс | 679 мс | 49,2 МБ | 20 001 | 295 975 |
| FastExcelReader | Весь лист в массив | 1,08 с | 1,08 с | 1,09 с | 22,5 МБ | 20 001 | 295 975 |
| OpenSpout | Весь лист в массив | 2,29 с | 2,28 с | 2,30 с | 17,2 МБ | 20 001 | 295 975 |
| PhpSpreadsheet | Весь лист в массив | 4,07 с | 4,06 с | 4,09 с | 202 МБ | 20 001 | 295 975 |
Большая выгрузка — 100 000 × 10
Скачать этот файл ↓Миллион ячеек. Здесь разница между потоковым и объектным чтением становится решающей.
Чтение всех строк
Основной сценарий: пройти по всем строкам первого листа и получить значения ячеек. Значения не накапливаются в памяти — там, где библиотека умеет отдавать строки потоком, используется поток.
Открытие + первая строка
Сколько стоит просто открыть файл и получить первую строку. Показывает, обязана ли библиотека разобрать весь документ до того, как отдаст первые данные.
Весь лист в массив
Весь лист загружается в один PHP-массив. Самый частый способ использования и самый тяжёлый по памяти.
Все цифры таблицей
| Библиотека | Сценарий | Время (медиана) | Мин | Макс | Пик памяти | Прочитано строк | Непустых ячеек |
|---|---|---|---|---|---|---|---|
| SimpleXLSX | Чтение всех строк | 2,20 с | 2,20 с | 2,20 с | 155 МБ | 100 001 | 980 093 |
| FastExcelReader | Чтение всех строк | 3,38 с | 3,37 с | 3,39 с | 30,2 МБ | 100 001 | 980 093 |
| OpenSpout | Чтение всех строк | 6,95 с | 6,95 с | 6,95 с | 2,9 МБ | 100 001 | 980 093 |
| PhpSpreadsheet | Чтение всех строк | 14,03 с | 14,03 с | 14,03 с | 561 МБ | 100 001 | 980 093 |
| FastExcelReader | Открытие + первая строка | 566 мс | 565 мс | 571 мс | 30,2 МБ | 1 | 10 |
| OpenSpout | Открытие + первая строка | 1,24 с | 1,24 с | 1,25 с | 2,1 МБ | 1 | 10 |
| SimpleXLSX | Открытие + первая строка | 1,37 с | 1,37 с | 1,37 с | 155 МБ | 1 | 10 |
| PhpSpreadsheet | Открытие + первая строка | 3,65 с | 3,65 с | 3,66 с | 75,1 МБ | 1 | 10 |
| SimpleXLSX | Весь лист в массив | 2,22 с | 2,22 с | 2,22 с | 155 МБ | 100 001 | 980 093 |
| FastExcelReader | Весь лист в массив | 3,47 с | 3,46 с | 3,48 с | 71,7 МБ | 100 001 | 980 093 |
| OpenSpout | Весь лист в массив | 7,00 с | 7,00 с | 7,00 с | 60,1 МБ | 100 001 | 980 093 |
| PhpSpreadsheet | Весь лист в массив | 13,68 с | 13,68 с | 13,68 с | 589 МБ | 100 001 | 980 093 |
Широкая таблица — 2 000 × 150
Скачать этот файл ↓Мало строк, но очень много колонок — нагрузка на разбор адресов ячеек.
Чтение всех строк
Основной сценарий: пройти по всем строкам первого листа и получить значения ячеек. Значения не накапливаются в памяти — там, где библиотека умеет отдавать строки потоком, используется поток.
Открытие + первая строка
Сколько стоит просто открыть файл и получить первую строку. Показывает, обязана ли библиотека разобрать весь документ до того, как отдаст первые данные.
Весь лист в массив
Весь лист загружается в один PHP-массив. Самый частый способ использования и самый тяжёлый по памяти.
Все цифры таблицей
| Библиотека | Сценарий | Время (медиана) | Мин | Макс | Пик памяти | Прочитано строк | Непустых ячеек |
|---|---|---|---|---|---|---|---|
| SimpleXLSX | Чтение всех строк | 679 мс | 679 мс | 683 мс | 47,8 МБ | 2 001 | 299 770 |
| FastExcelReader | Чтение всех строк | 1,07 с | 1,07 с | 1,07 с | 14,0 МБ | 2 001 | 299 770 |
| OpenSpout | Чтение всех строк | 3,16 с | 3,16 с | 3,16 с | 2,9 МБ | 2 001 | 299 770 |
| PhpSpreadsheet | Чтение всех строк | 4,04 с | 4,02 с | 4,07 с | 201 МБ | 2 001 | 299 770 |
| FastExcelReader | Открытие + первая строка | 237 мс | 236 мс | 237 мс | 14,0 МБ | 1 | 150 |
| SimpleXLSX | Открытие + первая строка | 444 мс | 443 мс | 444 мс | 47,8 МБ | 1 | 150 |
| OpenSpout | Открытие + первая строка | 508 мс | 507 мс | 511 мс | 2,1 МБ | 1 | 150 |
| PhpSpreadsheet | Открытие + первая строка | 1,14 с | 1,14 с | 1,14 с | 28,6 МБ | 1 | 150 |
| SimpleXLSX | Весь лист в массив | 680 мс | 680 мс | 681 мс | 47,8 МБ | 2 001 | 299 770 |
| FastExcelReader | Весь лист в массив | 1,10 с | 1,08 с | 1,13 с | 29,8 МБ | 2 001 | 299 770 |
| OpenSpout | Весь лист в массив | 3,15 с | 3,14 с | 3,16 с | 25,7 МБ | 2 001 | 299 770 |
| PhpSpreadsheet | Весь лист в массив | 3,98 с | 3,97 с | 3,99 с | 213 МБ | 2 001 | 299 770 |
Только текст, shared strings — 40 000 × 8
Скачать этот файл ↓Повторяющийся текст вынесен в sharedStrings.xml, как это делает Excel.
Чтение всех строк
Основной сценарий: пройти по всем строкам первого листа и получить значения ячеек. Значения не накапливаются в памяти — там, где библиотека умеет отдавать строки потоком, используется поток.
Открытие + первая строка
Сколько стоит просто открыть файл и получить первую строку. Показывает, обязана ли библиотека разобрать весь документ до того, как отдаст первые данные.
Весь лист в массив
Весь лист загружается в один PHP-массив. Самый частый способ использования и самый тяжёлый по памяти.
Все цифры таблицей
| Библиотека | Сценарий | Время (медиана) | Мин | Макс | Пик памяти | Прочитано строк | Непустых ячеек |
|---|---|---|---|---|---|---|---|
| SimpleXLSX | Чтение всех строк | 900 мс | 898 мс | 900 мс | 70,4 МБ | 40 001 | 320 008 |
| FastExcelReader | Чтение всех строк | 1,35 с | 1,34 с | 1,35 с | 26,5 МБ | 40 001 | 320 008 |
| OpenSpout | Чтение всех строк | 3,03 с | 3,03 с | 3,04 с | 3,2 МБ | 40 001 | 320 008 |
| PhpSpreadsheet | Чтение всех строк | 4,51 с | 4,50 с | 4,51 с | 234 МБ | 40 001 | 320 008 |
| FastExcelReader | Открытие + первая строка | 398 мс | 397 мс | 411 мс | 26,5 МБ | 1 | 8 |
| SimpleXLSX | Открытие + первая строка | 647 мс | 646 мс | 649 мс | 70,4 МБ | 1 | 8 |
| OpenSpout | Открытие + первая строка | 847 мс | 840 мс | 854 мс | 2,3 МБ | 1 | 8 |
| PhpSpreadsheet | Открытие + первая строка | 1,52 с | 1,52 с | 1,52 с | 46,0 МБ | 1 | 8 |
| SimpleXLSX | Весь лист в массив | 910 мс | 908 мс | 912 мс | 70,4 МБ | 40 001 | 320 008 |
| FastExcelReader | Весь лист в массив | 1,36 с | 1,36 с | 1,37 с | 38,1 МБ | 40 001 | 320 008 |
| OpenSpout | Весь лист в массив | 3,06 с | 3,06 с | 3,06 с | 28,0 МБ | 40 001 | 320 008 |
| PhpSpreadsheet | Весь лист в массив | 4,42 с | 4,42 с | 4,43 с | 234 МБ | 40 001 | 320 008 |
Только текст, inline strings — 40 000 × 8
Скачать этот файл ↓Тот же контент без словаря строк — так пишут многие генераторы отчётов.
Чтение всех строк
Основной сценарий: пройти по всем строкам первого листа и получить значения ячеек. Значения не накапливаются в памяти — там, где библиотека умеет отдавать строки потоком, используется поток.
Открытие + первая строка
Сколько стоит просто открыть файл и получить первую строку. Показывает, обязана ли библиотека разобрать весь документ до того, как отдаст первые данные.
Весь лист в массив
Весь лист загружается в один PHP-массив. Самый частый способ использования и самый тяжёлый по памяти.
Все цифры таблицей
| Библиотека | Сценарий | Время (медиана) | Мин | Макс | Пик памяти | Прочитано строк | Непустых ячеек |
|---|---|---|---|---|---|---|---|
| SimpleXLSX | Чтение всех строк | 699 мс | 698 мс | 699 мс | 81,2 МБ | 40 001 | 320 008 |
| FastExcelReader | Чтение всех строк | 1,09 с | 1,09 с | 1,10 с | 1,8 МБ | 40 001 | 320 008 |
| OpenSpout | Чтение всех строк | 2,50 с | 2,48 с | 2,52 с | 1,3 МБ | 40 001 | 320 008 |
| PhpSpreadsheet | Чтение всех строк | 4,54 с | 4,53 с | 4,55 с | 214 МБ | 40 001 | 320 008 |
| OpenSpout | Открытие + первая строка | 3 мс | 3 мс | 3 мс | 1,3 МБ | 1 | 8 |
| FastExcelReader | Открытие + первая строка | 3 мс | 3 мс | 3 мс | 1,8 МБ | 1 | 8 |
| SimpleXLSX | Открытие + первая строка | 435 мс | 435 мс | 436 мс | 81,2 МБ | 1 | 8 |
| PhpSpreadsheet | Открытие + первая строка | 1,37 с | 1,37 с | 1,38 с | 31,4 МБ | 1 | 8 |
| SimpleXLSX | Весь лист в массив | 705 мс | 705 мс | 707 мс | 81,2 МБ | 40 001 | 320 008 |
| FastExcelReader | Весь лист в массив | 1,12 с | 1,11 с | 1,16 с | 27,7 МБ | 40 001 | 320 008 |
| OpenSpout | Весь лист в массив | 2,50 с | 2,48 с | 2,51 с | 27,5 МБ | 40 001 | 320 008 |
| PhpSpreadsheet | Весь лист в массив | 4,47 с | 4,45 с | 4,50 с | 231 МБ | 40 001 | 320 008 |
Числа и даты — 40 000 × 10
Скачать этот файл ↓Почти нет строк: проверяем стоимость конвертации чисел и дат.
Чтение всех строк
Основной сценарий: пройти по всем строкам первого листа и получить значения ячеек. Значения не накапливаются в памяти — там, где библиотека умеет отдавать строки потоком, используется поток.
Открытие + первая строка
Сколько стоит просто открыть файл и получить первую строку. Показывает, обязана ли библиотека разобрать весь документ до того, как отдаст первые данные.
Весь лист в массив
Весь лист загружается в один PHP-массив. Самый частый способ использования и самый тяжёлый по памяти.
Все цифры таблицей
| Библиотека | Сценарий | Время (медиана) | Мин | Макс | Пик памяти | Прочитано строк | Непустых ячеек |
|---|---|---|---|---|---|---|---|
| SimpleXLSX | Чтение всех строк | 695 мс | 695 мс | 696 мс | 49,0 МБ | 40 001 | 400 010 |
| FastExcelReader | Чтение всех строк | 1,11 с | 1,11 с | 1,12 с | 1,8 МБ | 40 001 | 400 010 |
| OpenSpout | Чтение всех строк | 1,97 с | 1,97 с | 1,97 с | 1,3 МБ | 40 001 | 400 010 |
| PhpSpreadsheet | Чтение всех строк | 4,96 с | 4,95 с | 4,97 с | 218 МБ | 40 001 | 400 010 |
| OpenSpout | Открытие + первая строка | 3 мс | 3 мс | 3 мс | 1,3 МБ | 1 | 10 |
| FastExcelReader | Открытие + первая строка | 3 мс | 3 мс | 3 мс | 1,8 МБ | 1 | 10 |
| SimpleXLSX | Открытие + первая строка | 321 мс | 321 мс | 322 мс | 49,0 МБ | 1 | 10 |
| PhpSpreadsheet | Открытие + первая строка | 1,13 с | 1,13 с | 1,14 с | 21,1 МБ | 1 | 10 |
| SimpleXLSX | Весь лист в массив | 691 мс | 690 мс | 693 мс | 49,0 МБ | 40 001 | 400 010 |
| FastExcelReader | Весь лист в массив | 1,14 с | 1,14 с | 1,14 с | 16,9 МБ | 40 001 | 400 010 |
| OpenSpout | Весь лист в массив | 2,01 с | 1,97 с | 2,04 с | 16,7 МБ | 40 001 | 400 010 |
| PhpSpreadsheet | Весь лист в массив | 4,85 с | 4,83 с | 4,87 с | 239 МБ | 40 001 | 400 010 |
Окружение стенда
- PHP
- 8.4.12 (cli)
- ОС
- Linux 4.19.0-18-amd64 / x86_64
- CPU
- 12th Gen Intel(R) Core(TM) i5-12600
- Zend Engine
- 4.4.12
- ext-zip
- 1.22.6
- libxml
- 2.9.4
- Xdebug
- не установлен
- OPcache
- установлен (в воркерах выключен)
Проверьте на своём файле
Загрузите книгу XLSX — те же четыре библиотеки прочитают её на этом сервере, и вы получите ссылку на страницу с результатами. Регистрация не нужна. Файл удаляется сразу после прогона, его содержимое нигде не показывается — в отчёт попадают только размеры, количество строк и тайминги.
Не загружайте файлы с персональными данными и коммерческой тайной: сервер обрабатывает их обычным PHP-процессом, а ссылка на результаты доступна любому, кто её знает.