Немного теории:
Конкатенация (соединение строк). Казалось бы - ну что может быть проще и однозначнее? Ан нет. Выражение T = "А"+"Б"; (если оно не вычислено на этапе компиляции/разбора) требует выделения памяти для "А", памяти для "Б", анализа длин "А" и "Б", выделение памяти для T, копирование первой строки, копирование второй строки. Это медленно, особенно если в цикле дописывается кусочек в конец строки.
В "нормальных" системах, например в .NET от этого можно уйти используя так называемые StringBuilder - это специальный объект, который более эффективно выделяет память (крупными блоками) и не копирует зря строки. По сути это поток (stream) который используется для записи в память, как в файл. А вот в 1С такого нет. Фиг вам товарищи, а не эффективная работа со строками
Но фиг только тем у кого хитрости мало, а для остальных есть варианты.
ТекстовыйДокумент
Оказывается, что метод ДобавитьСтроку() для типа ТекстовыйДокумент для больших строк работает гораздо эффективнее чем тупая конкатенация. Возможно, это связано с тем, что этот тип - обёртка к текстовому редактору, встроенному в 1С. Кстати, этот редактор для простых текстовых файлов файлов мне нравится гораздо больше, чем например, notepad или редактор Visual Studio - он позволяет бодрее работать с большими текстами, как в длину, так и в ширину.
Но! У этого способа есть недостаток - в 8.0 и 8.1 он не доступен на сервере, т.к. считается "интерфейсным". Обидно. Но это заставляет искать нас более эффективный способ:
ЗаписьXML
Опа! А при чём здесь XML? Правильно, XML нам не нужен. Но важно, что тип ЗаписьXML представляет собой как раз обёртку над последовательной записью в поток. А если учесть, что он позволяет формировать результат в память в виде строки, а не только в файл, то это уже готовый кандидат на замену StringBuilder. Осталось только упомянуть, что он позволяет дозаписывать в "XML" всё что угодно при помощи метода ЗаписатьБезОбработки().
Код 1C v 8.2 УП ДлинаДобавляемогоКуска = 200; //символов, последний - ПС
ОбщаяДлинаСтроки = 1000000;
КоличествоИтераций = 10;
//Создаём базовую строчку:
БазоваяСтрока = "";
Для Сч = 1 по ДлинаДобавляемогоКуска-1 Цикл
БазоваяСтрока = БазоваяСтрока + "Ы";
КонецЦикла;
БазоваяСтрокаПС = БазоваяСтрока + Символы.ПС;
//Способ 1. Добавление строк к концу строки
Сообщить("Способ 1. Добавление строк к концу строки - Начало " + Строка(ТекущаяДата()));
ФиктивныйРезультат = 0;
Для СчИтераций = 1 по КоличествоИтераций Цикл
Состояние("Способ 1. Добавление строк к концу строки - " + Строка(СчИтераций));
СтрокаРезультат = "";
Для СчДобавлений = 1 по (ОбщаяДлинаСтроки/ДлинаДобавляемогоКуска) Цикл
СтрокаРезультат = СтрокаРезультат + БазоваяСтрокаПС;
КонецЦикла;
ФиктивныйРезультат = ФиктивныйРезультат + СтрДлина(СтрокаРезультат);
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Фиктивный результат = " + Строка(ФиктивныйРезультат));
Сообщить("Способ 1. Добавление строк к концу строки - Окончание " + Строка(ТекущаяДата()));
//Способ 2. Добавление строк в текстовый документ
Сообщить("Способ 2. Добавление строк в текстовый документ - Начало " + Строка(ТекущаяДата()));
ФиктивныйРезультат = 0;
Для СчИтераций = 1 по КоличествоИтераций Цикл
Состояние("Способ 2. Добавление строк в текстовый документ - " + Строка(СчИтераций));
ТекстПостроитель = Новый ТекстовыйДокумент;
Для СчДобавлений = 1 по (ОбщаяДлинаСтроки/ДлинаДобавляемогоКуска) Цикл
ТекстПостроитель.ДобавитьСтроку(БазоваяСтрока); //ПС добавляется сам
КонецЦикла;
СтрокаРезультат = ТекстПостроитель.ПолучитьТекст();
ФиктивныйРезультат = ФиктивныйРезультат + СтрДлина(СтрокаРезультат);
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Фиктивный результат = " + Строка(ФиктивныйРезультат));
Сообщить("Способ 2. Добавление строк в текстовый документ - Окончание " + Строка(ТекущаяДата()));
//Способ 3. Создание через ЗаписьXML
Сообщить("Способ 3. Создание через ЗаписьXML - Начало " + Строка(ТекущаяДата()));
ФиктивныйРезультат = 0;
Для СчИтераций = 1 по КоличествоИтераций Цикл
Состояние("Способ 3. Создание через ЗаписьXML - " + Строка(СчИтераций));
ТекстПостроитель = Новый ЗаписьXML;
ТекстПостроитель.УстановитьСтроку();
Для СчДобавлений = 1 по (ОбщаяДлинаСтроки/ДлинаДобавляемогоКуска) Цикл
ТекстПостроитель.ЗаписатьБезОбработки(БазоваяСтрокаПС);
КонецЦикла;
СтрокаРезультат = ТекстПостроитель.Закрыть();
ФиктивныйРезультат = ФиктивныйРезультат + СтрДлина(СтрокаРезультат);
ОбработкаПрерыванияПользователя();
КонецЦикла;
Сообщить("Фиктивный результат = " + Строка(ФиктивныйРезультат));
Сообщить("Способ 3. Создание через ЗаписьXML - Окончание " + Строка(ТекущаяДата()));
//ЗЫ: данный код проверен в 8.2
Результаты забегов
У меня на тестовой среде получилось примерно следующее время:
1. Конкатенация - 24 секунды
2. Текстовый документ 1,5 секунды
3. ЗаписьXML - около 0,4 секунды
Пишет
Alexander Speshilov Код 1C v 8.х // Функция переводит дату в формате 1С в международный текстовый формат вида 'YYYYMMDD hh:mm:ss'
// Параметры: Дата1С - Дата - Дата в формате 1С
// Возвращаемое значение: Строка - Дата в международном текстовом формате
//
Функция ДатаВСтроку(Дата1С)
Результат = Формат(Год(Дата1С),"ЧГ=0") + ?(СтрДлина(Строка(Месяц(Дата1С))) < 2,"0" + Строка(Месяц(Дата1С)) , Строка(Месяц(Дата1С)))
+ ?(СтрДлина(Строка(День(Дата1С))) < 2, "0" + Строка(День(Дата1С)), Строка(День(Дата1С))) + " "
+ ?(СтрДлина(Строка(Час(Дата1С))) < 2, "0" + Строка(Час(Дата1С)), Строка(Час(Дата1С))) + ":"
+ ?(СтрДлина(Строка(Минута(Дата1С))) < 2, "0" + Строка(Минута(Дата1С)), Строка(Минута(Дата1С))) + ":"
+ ?(СтрДлина(Строка(Секунда(Дата1С))) <2, "0" + Строка(Секунда(Дата1С)), Строка(Секунда(Дата1С)));
Возврат Результат;
КонецФункции
// Функция переводит строку в дату с указанным форматом
// Параметры:
// Строка - Строка - Дата в виде строки
// ФорматДаты - Строка - Формат даты, в который переводится строка
// Возвращаемое значение: Дата - Дата в указанном формате
//
Функция ПривестиСтрокуКДате(Строка, ФорматДаты="дмг")
Список = Новый Массив;
Подстрока = "";
Позиция = 1;
ДлинаСтроки = СтрДлина(Строка) + 1;
Пока Позиция <= ДлинаСтроки цикл
Символ = Сред(Строка, Позиция, 1);
Если (Символ >= "0") И (Символ <= "9") тогда
Подстрока = Подстрока + Символ;
ИначеЕсли Подстрока <> "" тогда
Список.Добавить(Число(Подстрока));
Подстрока = "";
КонецЕсли;
Позиция = Позиция + 1;
КонецЦикла;
Если Список.Количество() < 3 тогда
Возврат Неопределено;
КонецЕсли;
Если ФорматДаты="дмг" тогда
День = Список[0]; Месяц = Список[1]; Год = Список[2];
ИначеЕсли ФорматДаты="мдг" тогда
День = Список[1]; Месяц = Список[0]; Год = Список[2];
ИначеЕсли ФорматДаты="гмд" тогда
День = Список[2]; Месяц = Список[1]; Год = Список[0];
Иначе
День = 1; Месяц = 1; Год = 1;
КонецЕсли;
Час = 0; Минута = 0; Секунда = 0;
Если Список.Количество() >= 5 тогда
Час = Список[3];
Минута = Список[4];
Секунда = ?(Список.Количество() >= 6, Список[5], 0);
КонецЕсли;
Попытка
Результат = Дата(Год, Месяц, День, Час, Минута, Секунда);
Исключение
Возврат Неопределено;
КонецПопытки;
Возврат Результат;
КонецФункции
Код 1C v 8.х // Функция Дополняет переданную в качестве первого параметра строку символами слева\справа до заданной длины и возвращает ее
// Незначащие символы слева и справа удаляются
// По умолчанию функция добавляет строку нулями слева
//
// Параметры:
// Строка - Строка - исходная строка, которую необходимо дополнить символами до заданной длины
// ДлинаСтроки - Число - требуемая конечная длина строки
// Символ - Строка - (необязательный) значение символа, которым необходимо дополнить строку
// Режим - Строка - (необязательный) [Слева|Справа] режим добавления символов к исходной строке: слева или справа
//
// Пример 1:
// Строка = "1234"; ДлинаСтроки = 10; Символ = "0"; Режим = "Слева"
// Возврат: "0000001234"
//
// Пример 2:
// Строка = " 1234 "; ДлинаСтроки = 10; Символ = "#"; Режим = "Справа"
// Возврат: "1234######"
//
// Возвращаемое значение:
// Строка - строка, дополненная символами слева или справа
//
Функция ДополнитьСтроку(Знач Строка, Знач ДлинаСтроки, Знач Символ = "0", Знач Режим = "Слева") Экспорт
Если ПустаяСтрока(Символ) Тогда
Символ = "0";
КонецЕсли;
// длина символа не должна превышать единицы
Символ = Лев(Символ, 1);
// удаляем крайние пробелы слева и справа строки
Строка = СокрЛП(Строка);
КоличествоСимволовНадоДобавить = ДлинаСтроки - СтрДлина(Строка);
Если КоличествоСимволовНадоДобавить > 0 Тогда
СтрокаДляДобавления = "";
Пока СтрДлина(СтрокаДляДобавления) < КоличествоСимволовНадоДобавить Цикл
СтрокаДляДобавления = СтрокаДляДобавления + Символ;
КонецЦикла;
Если ВРег(Режим) = "СЛЕВА" Тогда
Строка = СтрокаДляДобавления + Строка;
ИначеЕсли ВРег(Режим) = "СПРАВА" Тогда
Строка = Строка + СтрокаДляДобавления;
КонецЕсли;
КонецЕсли;
Возврат Строка;
КонецФункции
Пример Дополнения строки пробелами до заданной длины
Код 1C v 8.х Функция ДополнитьСтрокуПробелами(Строка, Длина)
Пока СтрДлина(Строка) < Длина Цикл
Пробел = Символ(0);
Строка = Строка + Пробел;
КонецЦикла;
Возврат Строка;
КонецФункции