Среди начинающих разработчиков нередко возникает вопрос: влияет ли язык синтаксиса (русский или английский) на производительность выполнения модулей? Проанализируем внутреннее устройство платформы 1С:Предприятие, выясним причину медленной работы алгоритмов сопоставления текстовых данных и разберем эффективные способы оптимизации.
Разберем, как платформа 1С обрабатывает программный код. Язык написания (будь то русский или английский) абсолютно не влияет на скорость работы алгоритмов. Процесс исполнения строится следующим образом:
Если и If, Попытка и Try преобразуются в абсолютно идентичные внутренние опкоды команд.Таким образом, замена русских конструкций на английские не дает никакой прибавки к скорости. Если обработка выполняется медленно, узким местом является не синтаксис, а сам используемый алгоритм или работа с оперативной памятью и диском.
Проанализируем типовую проблему: долгое построчное сравнение двух текстовых файлов, в которых строки идут в произвольном порядке. Медленная работа обычно обусловлена следующими факторами:
ТекстовыйДокумент приводит к повышенному расходу оперативной памяти и дополнительным накладным расходам на парсинг.Рассмотрим несколько проверенных способов решения этой задачи средствами платформы 1С.
Наиболее быстрый и простой способ ускорить поиск неупорядоченных строк — использовать потоковое чтение через ЧтениеТекста и индексацию данных в оперативной памяти с помощью объекта Соответствие. Поиск по ключу в объекте Соответствие выполняется за константное время O(1), что снижает общую сложность алгоритма до линейной O(N + M).
Разберем по шагам реализацию данного подхода:
// Создаем хеш-таблицу для строк первого файла
ХешТаблица = Новый Соответствие;
// Потоково читаем первый файл
ЧтениеФайла1 = Новый ЧтениеТекста("C:\Temp\file1.txt", КодировкаТекста.UTF8);
СтрокаФайла1 = ЧтениеФайла1.ПрочитатьСтроку();
Пока СтрокаФайла1 <> Неопределено Доделать
// Если в файле могут быть дубликаты, сохраняем количество вхождений
Количество = ХешТаблица[СтрокаФайла1];
Если Количество = Неопределено Тогда
ХешТаблица.Вставить(СтрокаФайла1, 1);
Иначе
ХешТаблица.Вставить(СтрокаФайла1, Количество + 1);
КонецЕсли;
СтрокаФайла1 = ЧтениеФайла1.ПрочитатьСтроку();
КонецЦикла;
ЧтениеФайла1.Закрыть();
// Потоково читаем второй файл и выполняем сопоставление
ЧтениеФайла2 = Новый ЧтениеТекста("C:\Temp\file2.txt", КодировкаТекста.UTF8);
СтрокаФайла2 = ЧтениеФайла2.ПрочитатьСтроку();
Пока СтрокаФайла2 <> Неопределено Доделать
Если ХешТаблица[СтрокаФайла2] <> Неопределено Тогда
// Строка найдена в первом файле
Иначе
// Строка отсутствует в первом файле
КонецЕсли;
СтрокаФайла2 = ЧтениеФайла2.ПрочитатьСтроку();
КонецЦикла;
ЧтениеФайла2.Закрыть();
Если требуется хранить дополнительную информацию по строкам (например, номер строки или признак сопоставления), оптимально использовать объект ТаблицаЗначений с явным добавлением индекса.
Посмотрим на пример создания индекса и поиска:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("ТекстСтроки", Новый ОписаниеТипов("Строка",,,, Новый КвалификаторыСтроки(250)));
ТЗ.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"));
// Создаем индекс по колонке поиска для ускорения НайтиСтроки
ТЗ.Индексы.Добавить("ТекстСтроки");
// Заполняем таблицу данными первого файла...
// Поиск выполняется через структуру отбора с использованием созданного индекса
Отбор = Новый Структура("ТекстСтроки", ИскомаяСтрока);
НайденныеСтроки = ТЗ.НайтиСтроки(Отбор);
Если НайденныеСтроки.Количество() > 0 Тогда
// Обработка найденных совпадений
КонецЕсли;
Если строки имеют большую длину, прямое сравнение и сохранение их в памяти может быть ресурсоемким. В таких случаях рекомендуется рассчитывать хеш-сумму строки (например, MD5 или SHA-1) с помощью объекта ХешированиеДанных.
Рассмотрим пример получения хеша строки:
Хеширование = Новый ХешированиеДанных(ХешФункция.MD5);
Хеширование.Добавить(СтрокаФайла);
ХешСтроки = Хеширование.ХешСумма;
Сравнение коротких 32-символьных хешей происходит значительно быстрее и существенно экономит оперативную память при работе с большими массивами данных.
Для файлов огромного объема (сотни мегабайт или гигабайты) оптимальным решением является перенос сопоставления на уровень СУБД. Данные загружаются порциями в МенеджерВременныхТаблиц, после чего выполняется запрос с использованием соединения ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ или ЛЕВОЕ СОЕДИНЕНИЕ с отбором строк, отсутствующих во второй таблице.
Если файлы слишком велики для оперативной памяти, можно применить алгоритм слияния отсортированных последовательностей:
ЗапуститьПриложение() (например, стандартной утилитой sort).При оптимизации алгоритмов обработки файлов в 1С следует учитывать системные ограничения:
ЧтениеТекста или пакетную загрузку в СУБД.ТаблицаЗначений или временных таблицах запросов поле не должно иметь неограниченную длину.Соответствие одинаковые ключи перезаписываются. Если важен учет количества одинаковых строк, сохраняйте счетчик повторений в значении элемента.