Быстрое создание наполненных коллекций

Разберем самые частые способы создания коллекции, значения которой известны заранее. И сравним скорость их выполнения.

 

— А что это такое?

Программист Артём заметил у программиста Васи такой код:

Для Каждого КоллекцияМетаданных Из СтрРазделить("Справочники,Документы", ",") Цикл

//...

КонецЦикла;

 

Василий рассказал Артёму, что таким образом он быстро создал наполненный массив. Сделав код более коротким. Раньше было так:

КоллекцииМетаданных = Новый Массив;
КоллекцииМетаданных.Добавить("Справочники");
КоллекцииМетаданных.Добавить("Документы");

Для Каждого КоллекцияМетаданных Из КоллекцииМетаданных Цикл

//...

КонецЦикла;

 

Артём понял задумку Василия. Ведь никто так хорошо не поймёт ленивого программиста, как другой ленивый программист. Но заметил, что он бы делал немного по-другому. 

Для Каждого КоллекцияМетаданных Из Новый Структура("Справочники,Документы") Цикл

//...

КонецЦикла;

— Так оптимальнее — сказал программист Артём, рассказывая что-то про внутренние механизмы платформы…

— А вот и нет! — не согласился программист Вася, рассказывая что-то про оптимизацию метода СтрРазделить…

 

Так всё и началось.

 

Быстрое создание наполненных коллекций

 

Помните, как бывает в других языках программирования?

 

C#

 

string[] seasons = {"Winter", "Spring", "Summer", "Autumn"};

 

Java

 

String[] seasons = {"Winter", "Spring", "Summer", "Autumn"};

 

JavaScript

 

var seasons = ["Winter", "Spring", "Summer", "Autumn"];

 

Python

 

seasons = ['Winter', 'Spring', 'Summer', 'Autumn']

Как же это бывает удобно — создать сразу наполненный значениями массив. Жаль, что в 1С такое не предусмотрено.

 

Но хорошо, что в нашем примере потребовались строковые массивы. Для этого в 1С есть способы:

 

 

СтрРазделить()

 

РезультатСоздания = СтрРазделить("Понедельник,Вторник,Среда,Четверг,Пятница,Суббота,Воскресенье", ",");

Кто-то скажет, что это не совсем то, что нам нужно — парсить строку для того, чтобы получить массив, значения которого заранее известны. Однако, на практике такой подход встречается довольно часто. 

 
Управление торговлей 11.4.9.91 (спойлер):
ОбязательныеСтандартныеРеквизиты = СтрРазделить("Период,Регистратор,ВидДвижения,Активность", ",");

Для каждого РеквизитРегистра Из Коллекция.СтандартныеРеквизиты Цикл
НаборГруппДанныхСМаркировкой = СтрРазделить("ПоДокументу,ПоФакту,Бой,Брак,Излишки,Недостача", ",");
НаборГруппДанныхСПрослеживанием = СтрРазделить("ПоДокументу,ПоФакту,Бой,Брак,Излишки,Недостача", ",");

 

Бухгалтерия предприятия КОРП 3.0.72.70 (спойлер):
СвойстваНастроек = СтрРазделить("Использование, ВидСравнения, Значение", ", ", Ложь);
Для Каждого СвойствоНастройки Из СвойстваНастроек Цикл
Для каждого ВидПериода Из СтрРазделить("ДатаПроизводства,СрокГодности",",") Цикл

 

И тут можно вспомнить, что метод СтрРазделить() появился только в версии 8.3.6. Как же раньше программисты могли одной строчкой кода создать наполненный массив?

 

 

РазложитьСтрокуВМассивПодстрок()

 

Выглядит это так:

РезультатСоздания = РазложитьСтрокуВМассивПодстрок("Понедельник,Вторник,Среда,Четверг,Пятница,Суббота,Воскресенье", ",");

Да, ещё один парсинг. Только на основе БСПшной функции, которая существует в типовых испокон веков.

Удивительно, но до сих пор можно встретить примеры использования даже в свежих типовых конфигурациях:

 
 
Бухгалтерия предприятия КОРП 3.0.72.70 (спойлер) :
Для Каждого ЭлтКлюч Из СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок("_ДатаПрмЭ,_ДатаПрмБ,_ДатаДокОтв", ",") Цикл
СЗ.Добавить(ЭлтКлюч, Формат(Ответ[ЭлтКлюч], "ДФ=yyyyMMdd"));
КонецЦикла;
Для Каждого Элт Из СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок("А%Б%В", "%") Цикл
 
Зарплата и управление персоналом 3.1.11.106 (спойлер) :
Для Каждого ЭлтКлюч Из СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок("_ДатаПрмЭ,_ДатаПрмБ,_ДатаДокОтв", ",") Цикл
Для Каждого Элт Из СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок("{{,{", ",") Цикл

 

 

Что лучше использовать в таком случае? Думаю, вопрос очевиден, учитывая, что платформенный метод, как заявляют разработчики, намного быстрее БСПшного. Так ли это? Проверим далее. Но не стоит забывать, что они не совсем идентичны. И об этом писалось в статье Чем расщепить или "СтрРазделить() VS РазложитьСтрокуВМассивПодстрок()" ?

 

 

Новый Структура()

 

Да, умельцы-программисты использовали стандартный конструктор структуры как способ создавать наполненную коллекцию.

И да, этот способ имеет ряд ограничений:

 

  • Результат будет структурой, а не массивом.

  • Все значения должны соответствовать правилам именования 1С.

  • Разделитель только запятая.

 

Все эти минусы, зачастую, не создают проблем и разработчики с удовольствием применяют данный подход.

Ну и, как обычно, примеры из типовых:

 

Управление торговлей 11.4.9.91 (спойлер):
Для Каждого КлючИЗначение Из Новый Структура("Данные, Источники, Приемники, РасчетныеПартии") Цикл
ПоляРесурсов = "
 |Стоимость, СтоимостьБезНДС, ПостояннаяРазница, ВременнаяРазница,
 |СтоимостьРегл, ДопРасходы, ДопРасходыБезНДС,
 |СтоимостьЗабалансовая, Трудозатраты, ПостатейныеПостоянныеСНДС, ПостатейныеПеременныеСНДС,
 |ПостатейныеПостоянныеБезНДС, ПостатейныеПеременныеБезНДС,
 |СтоимостьЗабалансоваяРегл, ДопРасходыРегл, ТрудозатратыРегл, ПостатейныеПостоянныеРегл, ПостатейныеПеременныеРегл,
 |СтоимостьУпр, ДопРасходыУпр, ТрудозатратыУпр, ПостатейныеПостоянныеУпр, ПостатейныеПеременныеУпр";

Для Каждого КлючИЗначение Из Новый Структура(ПоляРесурсов) Цикл
Запись[КлючИЗначение.Ключ] = - ДанныеДвижения[КлючИЗначение.Ключ];
КонецЦикла;
ВозвращаемыеСвойства = "НетЗаданий, ПерезапускОбновления, ПерезапускОбновленияСНачала, НаборПорций,
       |НовыйПоследнийОбновленныйЭлемент, НачальноеОбновлениеЗавершено, ТекстОшибкиЗавершения";

Для Каждого КлючИЗначение Из Новый Структура(ВозвращаемыеСвойства) Цикл

 

Бухгалтерия предприятия КОРП 3.0.72.70 (спойлер) :
КолонкиДоходов = "ЦенныеБумагиИтогоСуммаДоходов,ЦенныеБумагиСуммаДохода";
Для Каждого КолонкаДохода Из Новый Структура(КолонкиДоходов) Цикл
КолонкиРасходов = "ЦенныеБумагиИтогоСуммаРасходовКВычету,ЦенныеБумагиСуммаРасходовУменьшающаяДоходы,ЦенныеБумагиИтогоСуммаУбытка";
Для Каждого КолонкаРасхода Из Новый Структура(КолонкиРасходов) Цикл

 

И тут становится уже интереснее. А что быстрее: создать массив при помощи парсинга строки СтрРазделить() или же создать структуру стандартным конструктором Новый Структура() ? Чего гадать, когда можно проверить!

 

 

Разработка инструмента

 

Под этим спойлером подробная информация, как делался инструмент:

 

Для этого создаём простенький отчет.

В СКД указываем набор данных объект с колонками, которые нужны будут для анализа:

 

В параметрах указываем количество "подходов", количество созданий за один подход, ну и сами методы:

 

Накидываем ресурсы:

 

И делаем простой вывод диаграммы с детальными записями:

 

В ПриКомпоновкеРезультата() будем делать все манипуляции.

Для начала отключим стандартную обработку и очистим результат:

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

СтандартнаяОбработка = Ложь;
ДокументРезультат.Очистить();

КонецПроцедуры

Получим параметры из настроек (добавим функцию):

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

СтандартнаяОбработка = Ложь;
ДокументРезультат.Очистить();

ПараметрыВыполнения = ПараметрыВыполнения();

КонецПроцедуры

Функция ПараметрыВыполнения()

ПараметрыВыполнения = Новый Структура;

НастройкиКомпоновки = КомпоновщикНастроек.ПолучитьНастройки();
ПараметрыВыполнения.Вставить("НастройкиКомпоновки", НастройкиКомпоновки);

Для Каждого ПараметрКомпоновщика Из НастройкиКомпоновки.ПараметрыДанных.Элементы Цикл
Если ПараметрКомпоновщика.Использование Тогда
ПараметрыВыполнения.Вставить(ПараметрКомпоновщика.Параметр, ПараметрКомпоновщика.Значение);
КонецЕсли;
КонецЦикла;

Возврат ПараметрыВыполнения;

КонецФункции

 

Подготовим функцию для замеров:

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

СтандартнаяОбработка = Ложь;
ДокументРезультат.Очистить();

ПараметрыВыполнения = ПараметрыВыполнения();

ДанныеЗамеров = ДанныеЗамеров(ПараметрыВыполнения);

КонецПроцедуры

Функция ДанныеЗамеров(ПараметрыВыполнения)

ДанныеЗамеров = Новый ТаблицаЗначений; //Просто заполним структуру таблицы из полей описанного нами набора схемы компоновки
Для Каждого ТекущееПоле Из СхемаКомпоновкиДанных.НаборыДанных.Получить(0).Поля Цикл
ДанныеЗамеров.Колонки.Добавить(ТекущееПоле.Поле, ТекущееПоле.ТипЗначения, ТекущееПоле.Заголовок);
КонецЦикла;

Если НЕ ЗначениеЗаполнено(ПараметрыВыполнения.Методы) Тогда
Возврат ДанныеЗамеров;
КонецЕсли;

//Здесь будем замерять

Возврат ДанныеЗамеров;

КонецФункции

И сразу же не забудем вывести результат в табличный документ.

Для удобства будем использовать процедуру, описанную в статье "Меньше копипаста!", или как Вася универсальную процедуру писал

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)

СтандартнаяОбработка = Ложь;
ДокументРезультат.Очистить();

ПараметрыВыполнения = ПараметрыВыполнения();

ДанныеЗамеров = ДанныеЗамеров(ПараметрыВыполнения);

ВнешниеНаборыДанных = Новый Структура("Результат", ДанныеЗамеров);

СкомпоноватьРезультатОтчета(ДокументРезультат, СхемаКомпоновкиДанных, 
ПараметрыВыполнения.НастройкиКомпоновки, ДанныеРасшифровки, ВнешниеНаборыДанных);

КонецПроцедуры

Всё, база готова. Уже сейчас отчёт может выводиться, хоть и без замеров. Пора заняться ими! 

Подготовим циклы. Будем сначала выполнять подходы, а потом для каждого подхода будем выполнять каждый метод:

Функция ДанныеЗамеров(ПараметрыВыполнения)

ДанныеЗамеров = Новый ТаблицаЗначений;    //Просто заполним структуру таблицы из полей описанного нами набора схемы компоновки
Для Каждого ТекущееПоле Из СхемаКомпоновкиДанных.НаборыДанных.Получить(0).Поля Цикл
ДанныеЗамеров.Колонки.Добавить(ТекущееПоле.Поле, ТекущееПоле.ТипЗначения, ТекущееПоле.Заголовок);
КонецЦикла;

Если НЕ ЗначениеЗаполнено(ПараметрыВыполнения.Методы) Тогда
Возврат ДанныеЗамеров;
КонецЕсли;

Для ТекущийПодход = 1 По ПараметрыВыполнения.КоличествоПодходов Цикл

Для Каждого ТекущийМетод Из ПараметрыВыполнения.Методы Цикл



КонецЦикла;

КонецЦикла;

Возврат ДанныеЗамеров;

КонецФункции

Добавим новую строчку замера и заполним текущими данными

Функция ДанныеЗамеров(ПараметрыВыполнения)

ДанныеЗамеров = Новый ТаблицаЗначений;    //Просто заполним структуру таблицы из полей описанного нами набора схемы компоновки
Для Каждого ТекущееПоле Из СхемаКомпоновкиДанных.НаборыДанных.Получить(0).Поля Цикл
ДанныеЗамеров.Колонки.Добавить(ТекущееПоле.Поле, ТекущееПоле.ТипЗначения, ТекущееПоле.Заголовок);
КонецЦикла;

Если НЕ ЗначениеЗаполнено(ПараметрыВыполнения.Методы) Тогда
Возврат ДанныеЗамеров;
КонецЕсли;

Для ТекущийПодход = 1 По ПараметрыВыполнения.КоличествоПодходов Цикл

Для Каждого ТекущийМетод Из ПараметрыВыполнения.Методы Цикл

ТекущиеДанные = ДанныеЗамеров.Добавить();
ТекущиеДанные.Метод         = ТекущийМетод.Значение;
ТекущиеДанные.ТекущийПодход = ТекущийПодход;
ТекущиеДанные.КоличествоСозданий = ПараметрыВыполнения.КоличествоСозданий;

КонецЦикла;

КонецЦикла;

Возврат ДанныеЗамеров;

КонецФункции

Пока пропустим ненадолго момент с самими замерами. Представим, что они выполнены. Теперь нам нужно рассчитать количество созданий экземпляра коллекции за одну миллисекунду:

Функция ДанныеЗамеров(ПараметрыВыполнения)

ДанныеЗамеров = Новый ТаблицаЗначений;    //Просто заполним структуру таблицы из полей описанного нами набора схемы компоновки
Для Каждого ТекущееПоле Из СхемаКомпоновкиДанных.НаборыДанных.Получить(0).Поля Цикл
ДанныеЗамеров.Колонки.Добавить(ТекущееПоле.Поле, ТекущееПоле.ТипЗначения, ТекущееПоле.Заголовок);
КонецЦикла;

Если НЕ ЗначениеЗаполнено(ПараметрыВыполнения.Методы) Тогда
Возврат ДанныеЗамеров;
КонецЕсли;

Для ТекущийПодход = 1 По ПараметрыВыполнения.КоличествоПодходов Цикл

Для Каждого ТекущийМетод Из ПараметрыВыполнения.Методы Цикл

ТекущиеДанные = ДанныеЗамеров.Добавить();
ТекущиеДанные.Метод         = ТекущийМетод.Значение;
ТекущиеДанные.ТекущийПодход = ТекущийПодход;
ТекущиеДанные.КоличествоСозданий = ПараметрыВыполнения.КоличествоСозданий;

Если ТекущиеДанные.ОбщееВремяСозданий > 0 Тогда
ТекущиеДанные.КоличествоСозданийЗаМилисекунду = Окр(ТекущиеДанные.КоличествоСозданий / ТекущиеДанные.ОбщееВремяСозданий, 2);
Иначе
ТекущиеДанные.КоличествоСозданийЗаМилисекунду = ТекущиеДанные.КоличествоСозданий;
КонецЕсли;

КонецЦикла;

КонецЦикла;

Возврат ДанныеЗамеров;

КонецФункции

 

База готова. Теперь просто выполним замеры каждого метода.

Функция ДанныеЗамеров(ПараметрыВыполнения)

ДанныеЗамеров = Новый ТаблицаЗначений;    //Просто заполним структуру таблицы из полей описанного нами набора схемы компоновки
Для Каждого ТекущееПоле Из СхемаКомпоновкиДанных.НаборыДанных.Получить(0).Поля Цикл
ДанныеЗамеров.Колонки.Добавить(ТекущееПоле.Поле, ТекущееПоле.ТипЗначения, ТекущееПоле.Заголовок);
КонецЦикла;

Если НЕ ЗначениеЗаполнено(ПараметрыВыполнения.Методы) Тогда
Возврат ДанныеЗамеров;
КонецЕсли;

Для ТекущийПодход = 1 По ПараметрыВыполнения.КоличествоПодходов Цикл

Для Каждого ТекущийМетод Из ПараметрыВыполнения.Методы Цикл

ТекущиеДанные = ДанныеЗамеров.Добавить();
ТекущиеДанные.Метод         = ТекущийМетод.Значение;
ТекущиеДанные.ТекущийПодход = ТекущийПодход;
ТекущиеДанные.КоличествоСозданий = ПараметрыВыполнения.КоличествоСозданий;

Если ТекущиеДанные.Метод = "СтрРазделить" Тогда

ЗамеритьМетодСтрРазделить(ТекущиеДанные);

ИначеЕсли ТекущиеДанные.Метод = "НовыйСтруктура" Тогда

ЗамеритьМетодНовыйСтруктура(ТекущиеДанные);

ИначеЕсли ТекущиеДанные.Метод = "РазложитьСтрокуВМассивПодстрок" Тогда

ЗамеритьМетодРазложитьСтрокуВМассивПодстрок(ТекущиеДанные);

КонецЕсли;

Если ТекущиеДанные.ОбщееВремяСозданий > 0 Тогда
ТекущиеДанные.КоличествоСозданийЗаМилисекунду = Окр(ТекущиеДанные.КоличествоСозданий / ТекущиеДанные.ОбщееВремяСозданий, 2);
Иначе
ТекущиеДанные.КоличествоСозданийЗаМилисекунду = ТекущиеДанные.КоличествоСозданий;
КонецЕсли;

КонецЦикла;

КонецЦикла;

Возврат ДанныеЗамеров;

КонецФункции

 

Ну и, собственно, сами методы:

Процедура ЗамеритьМетодСтрРазделить(ТекущиеДанные)

НачалоЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах();

Для ТекущееСоздание = 1 По ТекущиеДанные.КоличествоСозданий Цикл
РезультатСоздания = СтрРазделить("Понедельник,Вторник,Среда,Четверг,Пятница,Суббота,Воскресенье", ",");
КонецЦикла;

ТекущиеДанные.ОбщееВремяСозданий = ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоЗамера;

КонецПроцедуры

Процедура ЗамеритьМетодРазложитьСтрокуВМассивПодстрок(ТекущиеДанные)

НачалоЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах();

Для ТекущееСоздание = 1 По ТекущиеДанные.КоличествоСозданий Цикл
РезультатСоздания = РазложитьСтрокуВМассивПодстрок("Понедельник,Вторник,Среда,Четверг,Пятница,Суббота,Воскресенье", ",");
КонецЦикла;

ТекущиеДанные.ОбщееВремяСозданий = ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоЗамера;

КонецПроцедуры

Процедура ЗамеритьМетодНовыйСтруктура(ТекущиеДанные)

НачалоЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах();

Для ТекущееСоздание = 1 По ТекущиеДанные.КоличествоСозданий Цикл
РезультатСоздания = Новый Структура("Понедельник,Вторник,Среда,Четверг,Пятница,Суббота,Воскресенье");
КонецЦикла;

ТекущиеДанные.ОбщееВремяСозданий = ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоЗамера;

КонецПроцедуры

Здесь стоит пояснить, что можно было реализовать без повторяющегося кода. Однако, в данной реализации всё сделано специально, чтобы было как можно меньше сомнений в одинаковых условиях выполнения методов. Пусть лучше мы сделаем не такой классный и красивый код, как хотелось бы, зато получим более точные результаты.

Ну всё. Инструмент готов! 

 

 

 

Сравнение

 

Пробуем запустить замеры на серверной базе. Для этого поочередно каждый метод в цикле создаёт по N раз одну и ту же коллекцию из заранее известных элементов. И так указанное количество «подходов».

Почему одну и туже? Потому что в этом и суть эксперимента — показать, как будут работать такие создания, если вы где-то в коде захотите быстро создать наполненную заранее известными значениями коллекцию. И как будут работать примеры типовых, указанные выше.

Для начала установим:

  • Количество созданий в одном подходе: 10 000
  • Количество подходов: 10

И глянем, насколько по скорости отличаются СтрРазделить() и РазложитьСтрокуВМассивПодстрок().

 

Код создания:

РезультатСоздания = СтрРазделить("Понедельник,Вторник,Среда,Четверг,Пятница,Суббота,Воскресенье", ",");
РезультатСоздания = РазложитьСтрокуВМассивПодстрок("Понедельник,Вторник,Среда,Четверг,Пятница,Суббота,Воскресенье", ",");

Результат неудивителен. Количество создания коллекции за одну миллисекунду у СтрРазделить() значительно выше:

 

Было 10 подходов. В каждый подход коллекция создавалась по 10 000 раз. В каждый подход количество создаваемых элементов (10 000) делились на общее затраченное время на их создание.

График построен на результатах, выраженных в этой таблице:

 

Спойлер

Метод

Текущий подход

Количество созданий

Количество созданий за милисекунду

Общее время созданий

РазложитьСтрокуВМассивПодстрок()

1

10 000

11,85

844

СтрРазделить()

1

10 000

128,21

78

РазложитьСтрокуВМассивПодстрок()

2

10 000

13,33

750

СтрРазделить()

2

10 000

161,29

62

РазложитьСтрокуВМассивПодстрок()

3

10 000

12,30

813

СтрРазделить()

3

10 000

161,29

62

РазложитьСтрокуВМассивПодстрок()

4

10 000

10,66

938

СтрРазделить()

4

10 000

161,29

62

РазложитьСтрокуВМассивПодстрок()

5

10 000

12,79

782

СтрРазделить()

5

10 000

161,29

62

РазложитьСтрокуВМассивПодстрок()

6

10 000

13,33

750

СтрРазделить()

6

10 000

128,21

78

РазложитьСтрокуВМассивПодстрок()

7

10 000

13,33

750

СтрРазделить()

7

10 000

158,73

63

РазложитьСтрокуВМассивПодстрок()

8

10 000

12,80

781

СтрРазделить()

8

10 000

128,21

78

РазложитьСтрокуВМассивПодстрок()

9

10 000

11,43

875

СтрРазделить()

9

10 000

158,73

63

РазложитьСтрокуВМассивПодстрок()

10

10 000

12,80

781

СтрРазделить()

10

10 000

128,21

78

 

В принципе, не удивительно. Метод СтрРазделить() был специально оптимизирован так, чтобы заменить БСПшный РазложитьСтрокуВМассивПодстрок().

Ещё раз напомним, что методы не полностью идентичные и об этом писалось в статье Чем расщепить или "СтрРазделить() VS РазложитьСтрокуВМассивПодстрок()" ?

В рамках наших примеров, эти отличия не актуальны, однако ознакомится стоит.

 

Выходит, РазложитьСтрокуВМассивПодстрок() для подобного использовать не оптимально (интересно, почему в типовых до сих пор встречаются примеры). Но что покажет сравнение между СтрРазделить() и Новый Структура() ? Добавим в сравнение и этот метод:

РезультатСоздания = Новый Структура("Понедельник,Вторник,Среда,Четверг,Пятница,Суббота,Воскресенье");

 

Результаты замеров получились такие (спойлер)

Метод

Текущий подход

Количество созданий

Количество созданий за милисекунду

Общее время созданий

Новый Структура()

1

10 000

91,74

109

РазложитьСтрокуВМассивПодстрок()

1

10 000

13,33

750

СтрРазделить()

1

10 000

158,73

63

Новый Структура()

2

10 000

91,74

109

РазложитьСтрокуВМассивПодстрок()

2

10 000

13,33

750

СтрРазделить()

2

10 000

161,29

62

Новый Структура()

3

10 000

106,38

94

РазложитьСтрокуВМассивПодстрок()

3

10 000

13,05

766

СтрРазделить()

3

10 000

161,29

62

Новый Структура()

4

10 000

106,38

94

РазложитьСтрокуВМассивПодстрок()

4

10 000

12,80

781

СтрРазделить()

4

10 000

158,73

63

Новый Структура()

5

10 000

106,38

94

РазложитьСтрокуВМассивПодстрок()

5

10 000

13,07

765

СтрРазделить()

5

10 000

158,73

63

Новый Структура()

6

10 000

106,38

94

РазложитьСтрокуВМассивПодстрок()

6

10 000

13,33

750

СтрРазделить()

6

10 000

128,21

78

Новый Структура()

7

10 000

107,53

93

РазложитьСтрокуВМассивПодстрок()

7

10 000

13,33

750

СтрРазделить()

7

10 000

158,73

63

Новый Структура()

8

10 000

91,74

109

РазложитьСтрокуВМассивПодстрок()

8

10 000

13,33

750

СтрРазделить()

8

10 000

158,73

63

Новый Структура()

9

10 000

106,38

94

РазложитьСтрокуВМассивПодстрок()

9

10 000

13,07

765

СтрРазделить()

9

10 000

158,73

63

Новый Структура()

10

10 000

106,38

94

РазложитьСтрокуВМассивПодстрок()

10

10 000

12,32

812

СтрРазделить()

10

10 000

158,73

63

 

Ну и, собственно, график (обожаю их):

 

И так, на графике видно, помимо того, что сервер периодически «проседает», и то, что СтрРазделить() лидирует в этом сравнении.

Даже в «худшие времена» СтрРазделить() срабатывает быстрее, чем Новый Структура() в лучшие.

 

Почему так?

Мы можем лишь предположить, что структура — это более затратная коллекция, чем массив. Насколько это верный вывод лучше уточнять у знатоков всея нутра платформы 1С.

 

И так, что имеем на данный момент? Вася, который утверждал, что для наших целей СтрРазделить() аки лучше, чем Новый Структура(), оказался прав. С точки зрения скорости этот метод будет работать быстрее. Естественно, что выигрыш в производительности на вряд ли позволит нам сказать, что пользователи будут прыгать от радости.

 

Вроде Вася уже собрался открывать бутылку шампанского, но тут подходит Он. Оптимальный Программист. Священник Восьми Платформ. Хранитель Желтых Талмудов и Свидетель Великого Ассемблера.

 

 — Костыли всё это. Никаких созданий наполненного массива быть не должно! Зачем дополнительно напрягать вычислительную машину?

 

Новый Массив()

 

Эта статья нужна именно для того, чтобы сравнить между собой создания коллекций с заранее известными элементами. И Гуру программирования на нулях и единицах настаивает использовать только Новый Массив с последующими добавлениями элементов.

РезультатСоздания = Новый Массив;
РезультатСоздания.Добавить("Понедельник");
РезультатСоздания.Добавить("Вторник");
РезультатСоздания.Добавить("Среда");
РезультатСоздания.Добавить("Четверг");
РезультатСоздания.Добавить("Пятница");
РезультатСоздания.Добавить("Суббота");
РезультатСоздания.Добавить("Воскресенье");

А что нам мешает сравнить?

 

Добавляем в наш отчёт и такой способ (спойлер)

 

Для этого в доработаем отчёт. 

Функция ДанныеЗамеров(ПараметрыВыполнения)

ДанныеЗамеров = Новый ТаблицаЗначений;    //Просто заполним структуру таблицы из полей описанного нами набора схемы компоновки
Для Каждого ТекущееПоле Из СхемаКомпоновкиДанных.НаборыДанных.Получить(0).Поля Цикл
ДанныеЗамеров.Колонки.Добавить(ТекущееПоле.Поле, ТекущееПоле.ТипЗначения, ТекущееПоле.Заголовок);
КонецЦикла;

Если НЕ ЗначениеЗаполнено(ПараметрыВыполнения.Методы) Тогда
Возврат ДанныеЗамеров;
КонецЕсли;

Для ТекущийПодход = 1 По ПараметрыВыполнения.КоличествоПодходов Цикл

Для Каждого ТекущийМетод Из ПараметрыВыполнения.Методы Цикл

ТекущиеДанные = ДанныеЗамеров.Добавить();
ТекущиеДанные.Метод         = ТекущийМетод.Значение;
ТекущиеДанные.ТекущийПодход = ТекущийПодход;
ТекущиеДанные.КоличествоСозданий = ПараметрыВыполнения.КоличествоСозданий;

Если ТекущиеДанные.Метод = "СтрРазделить" Тогда

ЗамеритьМетодСтрРазделить(ТекущиеДанные);

ИначеЕсли ТекущиеДанные.Метод = "НовыйСтруктура" Тогда

ЗамеритьМетодНовыйСтруктура(ТекущиеДанные);

ИначеЕсли ТекущиеДанные.Метод = "РазложитьСтрокуВМассивПодстрок" Тогда

ЗамеритьМетодРазложитьСтрокуВМассивПодстрок(ТекущиеДанные);

ИначеЕсли ТекущиеДанные.Метод = "НовыйМассив" Тогда

ЗамеритьМетодНовыйМассив(ТекущиеДанные);

КонецЕсли;

Если ТекущиеДанные.ОбщееВремяСозданий > 0 Тогда
ТекущиеДанные.КоличествоСозданийЗаМилисекунду = Окр(ТекущиеДанные.КоличествоСозданий / ТекущиеДанные.ОбщееВремяСозданий, 2);
Иначе
ТекущиеДанные.КоличествоСозданийЗаМилисекунду = ТекущиеДанные.КоличествоСозданий;
КонецЕсли;

КонецЦикла;

КонецЦикла;

Возврат ДанныеЗамеров;

КонецФункции
Процедура ЗамеритьМетодНовыйМассив(ТекущиеДанные)

НачалоЗамера = ТекущаяУниверсальнаяДатаВМиллисекундах();

Для ТекущееСоздание = 1 По ТекущиеДанные.КоличествоСозданий Цикл

РезультатСоздания = Новый Массив;
РезультатСоздания.Добавить("Понедельник");
РезультатСоздания.Добавить("Вторник");
РезультатСоздания.Добавить("Среда");
РезультатСоздания.Добавить("Четверг");
РезультатСоздания.Добавить("Пятница");
РезультатСоздания.Добавить("Суббота");
РезультатСоздания.Добавить("Воскресенье");

КонецЦикла;

ТекущиеДанные.ОбщееВремяСозданий = ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоЗамера;


КонецПроцедуры

 

И так. Принцип анализа тот же. Только теперь будем сравнивать четыре метода. Без особого желания, ведь победитель ясен. Создать и наполнить массив таки лучше, чем парсить строку и разбивать её на элементы…

 

 

Результат нас удивил.

Мы перепроверили. На разных серверах.

 

Под спойлером данные замеров
         

Метод

Текущий подход

Количество созданий

Количество созданий за милисекунду

Общее время созданий

Новый Массив()

1

10 000

80,00

125,00

Новый Структура()

1

10 000

106,38

94,00

РазложитьСтрокуВМассивПодстрок()

1

10 000

12,79

782,00

СтрРазделить()

1

10 000

161,29

62,00

Новый Массив()

2

10 000

80,00

125,00

Новый Структура()

2

10 000

106,38

94,00

РазложитьСтрокуВМассивПодстрок()

2

10 000

13,07

765,00

СтрРазделить()

2

10 000

158,73

63,00

Новый Массив()

3

10 000

80,00

125,00

Новый Структура()

3

10 000

106,38

94,00

РазложитьСтрокуВМассивПодстрок()

3

10 000

13,07

765,00

СтрРазделить()

3

10 000

158,73

63,00

Новый Массив()

4

10 000

91,74

109,00

Новый Структура()

4

10 000

90,91

110,00

РазложитьСтрокуВМассивПодстрок()

4

10 000

9,28

1 078,00

СтрРазделить()

4

10 000

161,29

62,00

Новый Массив()

5

10 000

90,91

110,00

Новый Структура()

5

10 000

107,53

93,00

РазложитьСтрокуВМассивПодстрок()

5

10 000

13,05

766,00

СтрРазделить()

5

10 000

161,29

62,00

Новый Массив()

6

10 000

80,00

125,00

Новый Структура()

6

10 000

106,38

94,00

РазложитьСтрокуВМассивПодстрок()

6

10 000

13,05

766,00

СтрРазделить()

6

10 000

161,29

62,00

Новый Массив()

7

10 000

90,91

110,00

Новый Структура()

7

10 000

106,38

94,00

РазложитьСтрокуВМассивПодстрок()

7

10 000

13,07

765,00

СтрРазделить()

7

10 000

158,73

63,00

Новый Массив()

8

10 000

80,00

125,00

Новый Структура()

8

10 000

107,53

93,00

РазложитьСтрокуВМассивПодстрок()

8

10 000

12,55

797,00

СтрРазделить()

8

10 000

158,73

63,00

Новый Массив()

9

10 000

91,74

109,00

Новый Структура()

9

10 000

90,91

110,00

РазложитьСтрокуВМассивПодстрок()

9

10 000

13,33

750,00

СтрРазделить()

9

10 000

161,29

62,00

Новый Массив()

10

10 000

80,00

125,00

Новый Структура()

10

10 000

106,38

94,00

РазложитьСтрокуВМассивПодстрок()

10

10 000

13,07

765,00

СтрРазделить()

10

10 000

158,73

63,00

 

Оказывается, что СтрРазделить() быстрее, чем Новый Массив(). Более того, Новый Массив() ещё и борется за третье место с Новый Структура().

 

На создание и наполнение массива уходит больше времени, чем на парсинг строки при помощи СтрРазделить().

 

Пока мы удивлялись происходящему, к нам подплыл на волнах торсионных полей эзотерик от мира программирования Инокентий.

 

— Я знаю как вам помочь.

Продолжение следует…

 

В данной статье мы рассмотрели основные способы создания коллекции с заранее известными строковыми значениями. Примеры их использования есть и в типовых и, тем более, в всякого рода самописок и самодописок. По результатам замера вы сами можете сделать вывод. Разница есть, но не существенная. Какой подход использовать? Решать вам. Однако, на мой сугубо личный взляд, СтрРазделить выглядит более лаконично. Так что, если вы как-нибудь задумаетесь, мол, «этот массив из трех строк будет создаваться 100500 раз» , то не переживайте — написав его обычным созданием массива вы вряд ли предотвратите образование узкого места будущего кода.

В следующей статье разберем более «эзотерические» методы создания наполненного массива. И сравним их результаты. 

 

Понравилась статья?

Не будьте равнодушными! Поставьте лайк звездочку и переходите к другим работам автора:

 

 

60 Comments

  1. shalimski

    Нужен тест с РезультатСоздания = Новый Массив(7);

    Reply
  2. SeiOkami

    (2) именно! Но об этом в следующей серии.

    спойлер
    Reply
  3. user1166203

    А ФиксированныйМассив?

    Reply
  4. dock

    (5) Ну просто сразу же напрашивается создание через запрос! 🙂

    Reply
  5. dock

    Это всё прекрасно и замечательно, но вот вопрос: а что делать бедному программисту, если требуется коллекция с НЕ строковыми значениями 🙂 ?

    Reply
  6. herfis

    У кого-то дофига свободного времени. Это не упрек. Исключительно зависть.

    Reply
  7. Sashares

    (7)Для строковых значений это кажется уже слишком.

    Reply
  8. MSK_Step

    (0) Попробуйте использовать в разделителе такие знаки»;» в новой функции СтрРазделить, он криво обрабатывает, строку не делил на платформе 8.3.12.1714, поэтому старый добрый БСП РазложитьСтрокуВМассив еще долго будет использоваться.

    Reply
  9. SeiOkami

    (10)

    старый добрый БСП РазложитьСтрокуВМассив еще долго будет использоваться

    Багов с «;» не встречал, всё нормально отрабатывает. А вот отличия у методов есть, описывал их здесь: Чем расщепить или «СтрРазделить() VS РазложитьСтрокуВМассивПодстрок()» ?

    Однако, в контексте указанных в статье примеров нет в этом смысла, ведь входную строку пишет сам разработчик. Он может указать хоть «;» хоть «,»

    Reply
  10. alexch8

    По идее следующий код должен быть самым быстрым.

    РезультатСоздания = Новый Массив(7);

    РезультатСоздания[0] = «Понедельник»;

    РезультатСоздания[1] = «Вторник»;

    РезультатСоздания[2] = «Среда»;

    РезультатСоздания[3] = «Четверг»;

    РезультатСоздания[4] = «Пятница»;

    РезультатСоздания[5] = «Суббота»;

    РезультатСоздания[6] = «Воскресенье»;

    Массив.Добавить() каждый раз пересоздает массив с большим количеством элементов. Отсюда и невысокая производительность.

    Reply
  11. Sashares

    (12)

    Массив.Добавить() каждый раз пересоздает массив с большим количеством элементов.

    Ну уж, с чего каждый раз то?

    В (3) под спойлером посмотрите.

    Reply
  12. SeiOkami

    (13) В зависимости от «мощности» сервера, разница между СтрРазделить() и Новый Массив() отличается. СтрРазделить() стабильно быстрее, чем обычный Новый Массив(), но вот насколько — зависит от сервера.

    А вот Новый Массив(7) периодически вырывается вперёд. На самой мощной машине он одолел СтрРазделить() с неплохим отрывом. Но на более простых машинах он чуть быстрее Новый Массив, но всё же не дотягивает до СтрРазделить().

    В следующей статье возьмём больше сравнений. И даже применим волшебный «цикл в одну строку».

    Reply
  13. SlavaKron

    (13) У меня Новый Массив(7) выиграл.

    На Intel Core i3-6100 @ 3.70GHz, 1 млн. итераций:

    Новый Массив(7) ~ 2200 мс

    СтрРазделить() ~ 2900 мс

    Reply
  14. Sashares

    (15)Подозреваю, если значения строковые будут больше по длине и/или самих значений будет больше 7, то результат может быть совсем другим.

    Reply
  15. masterkio

    (5) Попробуйте для способа

    РезультатСоздания = Новый Массив;

    РезультатСоздания.Добавить(«Понедельник»);

    РезультатСоздания.Добавить(«Вторник»);

    РезультатСоздания.Добавить(«Среда»);

    РезультатСоздания.Добавить(«Четверг»);

    РезультатСоздания.Добавить(«Пятница»);

    РезультатСоздания.Добавить(«Суббота»);

    РезультатСоздания.Добавить(«Воскресенье»);

    Убрать переносы строк, т.е. написать весь этот код в одну строку. На большом количестве итераций цикла это очень сильно может повлиять на результат.

    Reply
  16. Dream_kz

    (14)

    И даже применим волшебный «цикл в одну строку».

    Это же из за особенностей отладчика, 7 строк кода работают тупо дольше, чем 1. Но только в режиме отладки.

    Reply
  17. SeiOkami

    (19) мерили именно этим методом. Под спойлером в статье специально выложена полная инфа по разработке инструмента для сравнения, чтобы любой мог попробовать замерить сам. Авось получим новую информацию.

    А по поводу особенностей отладчика. Я тоже так думал. Но факты показывают, что независимо от подключенной отладки, скорость выполнения кода в одну строку действительно быстрее.

    Reply
  18. Dream_kz

    (20)

    мерили именно этим методом

    Да, я сначала ляпнул, потом глянул код, извиняюсь.

    (20)

    скорость выполнения кода в одну строку действительно быстрее.

    Во всяком случае разработчики на партнерском форуме уверяли что разницы без отладки быть не должно.

    Reply
  19. SeiOkami

    (17) я так понимаю, вы ставите минус каждой статье, которая, на ваш взгляд, «не настолько полезна» ?)

    Reply
  20. Darklight
    Reply
  21. Darklight

    (10)Я даже так делил

    СтрРазделить(Строка, Символы.ПС)

    и даже так

    СтрРазделить(Строка, «,»+Символы.ПС+Символы.Таб)

    Нормально всё делится

    Reply
  22. MSK_Step

    (11)платформа 8.3.12.1714 ? я же не просто так пишу, если вы не встречали, это еще не говорит о том, что этого нет. Я поделился своим наблюдением

    Reply
  23. Sashares

    (19)

    Но только в режиме отладки.

    Нет =)

    Reply
  24. Darklight
    Reply
  25. swenzik

    вероятно Инокентий предложит брать массив из строк макета

    Reply
  26. Darklight

    (26)Может имеет значение — включена ли отладка на сервере (ключ -debug) — ну это если алгоритм на сервере выполняется. Для клиентского кода такой опции нет — и подключиться отладчиком можно почти в любой момент, поэтому тут байт кода должен генерировать по одинаковым правилам без зависимости от отладки, но в зависимости от того как расположены операторы (в одну ли строку) — ведь разница в байткоде — как раз в наличие отладочных опкодов.

    Reply
  27. Darklight
    Reply
  28. Sashares

    (30) О мои глаза…

    Что за говнокод…

    Хотите из переменных массив создавать, так хоть нормально напишите.

    Создайте структуру, в нее присвойте значения переменных.

    Обойдите в цикле структуру и присвойте значения в массив.

    Reply
  29. Darklight

    (31)Чует моя задница, что предложенное Вами решение по говнянности не уступет моему (если будет повторять тот же функционал)

    Reply
  30. qbdp

    В общем «СтрРазделить» — наглядный пример того, насколько важно уменьшать количество аллокаций памяти, и насколько быстрее может быть любой нативный код, в сравнении со встроенным языком 1С. (Капитан Очевидность передаёт привет)

    Reply
  31. Sashares

    (32)Но оно хотя бы будет не на 200 с лишним строк, а пара циклов))

    Reply
  32. Darklight

    (34)Эта функция создана «на скорую руку», и не для того, чтобы любоваться её внутренностями. А чтобы было ей удобно пользоваться при минимуме кода вызова, чтобы работала на всех клиентах и платформах, чтобы она не была узким местом производительности при многократном циклическом вызове (с допущением на универсальность), и чтобы была легко понятна.

    В предлагаемом (описанном Вами лишь в общих чертах) способе — я сомневаюсь что будет хоть какое-то преимущество, кроме сокращения строк кода — которое, в общем-то, не несёт никакой практической полезности.

    И да, как я уже написал выше, истоки данного подхода растут из другой задачи, где первопроходцем была функция создающая… хе-хе… Структуру. Но структуру — для применения в модулях повторного использования — т.е. временно-константную при повторном создании. Но это уже другая история.

    Reply
  33. Sashares

    (36) Пример со структурой:

    Функция СоздатьМассив(Значение1,Значение2=NULL,Значение3=NULL,Значение4=NULL)
    
    СтруктураЗначений = Новый Структура(«Значение1,Значение2,Значение3,Значение4»,
    Значение1,Значение2,Значение3,Значение4);
    
    МойМассив = Новый Массив;
    
    Для Инд = 1 По 4 Цикл
    ТекЗначение = СтруктураЗначений[«Значение»+Инд];
    Если ТекЗначение=NULL Тогда
    Прервать;
    КонецЕсли;
    МойМассив.Добавить(ТекЗначение);
    КонецЦикла;
    
    Возврат МойМассив;
    КонецФункции
    

    Показать

    Reply
  34. Darklight

    (37) Для 4-х значений у Вас слишком много кода. Ну а для поддержки 100 (ЛИШЬ ПОТЕНЦИАЛЬНЫХ значений, которых могут передать и 40 и 10 и 1) — длинна кода может и не шибко изменится — но, вот, насколько просядет производительность — это ещё не известно, вот эти строчки очень настораживают если число элементов будет большим или функция будет вызываться очень часто в цикле:

     СтруктураЗначений = Новый Структура(«Значение1,Значение2,Значение3,Значение4»,
    Значение1,Значение2,Значение3,Значение4);
    ТекЗначение = СтруктураЗначений[«Значение»+Инд]; 

    Я, конечно, согласен с тем, что 100 значений так передавать в массив это бред — и если кто-то хочет передать более 10-20 значений, то это уже явная архитектурная ошибка такого горе-программиста. Но, создав поддержку 100 значений я лишь хотел создать «видимость» поддержки неограниченного списка аргументов (что 1С поддерживает для своих объектов, но не поддерживает в пользовательских функциях и ВК)

    Reply
  35. Sashares

    (38) Создание структуры с заполненными параметрами выполняется быстро, значительно быстрее, чем создать пустую и вставлять значения.

    Обращение к структуре по ключу тоже быстро.

    Проседания производительности в этих пунктах не будет.

    Количество строк меняться не будет вне зависимости от количество переменных.

    Reply
  36. PerlAmutor

    Может эти публикации еще натолкнут на какие-нибудь идеи:

    https://infostart.ru/public/1116103/

    https://infostart.ru/public/71130/#Pro_bystrye_massivy

    Reply
  37. par_62

    Вернемся на землю. Рассуждения в статье интересны,если бы не одно но… Если бы мы писали драйверы устройств на языках мреднего и низкого уровня,тогда бы мы это обсуждали. А мы работаем в сфере бизнес логики,где гораздо важнее работа с базой данных. Тупое обращение в запросах или » умелый » поиск по таблице значений нивелмруют наши изощрения о СтрРазделить

    Reply
  38. SeiOkami

    (30)

    помню, я раньше писал подобную функцию. Однако упёрся в ограничения платформы — если метод имеет больше N (не помню) параметров, то начинаются какая-то квантовая неопределенность с их значениями. Вы пробовали использовать метод с указанием, например, 50-ти значений?

    Reply
  39. SeiOkami

    (23)

    Так, как чем ниже условие — тем больше операций сравнения для захода в него требуется. А тут ещё и строки сравниваются — вряд ли платформа 1С тут использует быстрое стравнение по заранее готовым числовым кешам.

    Заметьте, замеры происходят внутри условий, а не снаружи. Об этом даже упоминалось в статье. Поэтому в данном моменте всё корректно)

    7 значений для коллекции — это очень мало для сравнения — слишком уж быстро происходит такое создание — массива — тут начинают играть существенную роль всякие иные накладные расходы и процессы сервера и платформы . Опять таки, это важно для чистоты эксперимента.

    Именно такое небольшое число и важно для чистоты эксперимента. Об этом тоже упоминал в статье. Дело в том, что мы здесь сравниваем именно такие ситуации, как указаны в примерах из типовых. Когда у разработчика должен быть заранее известный и чаще всего небольшой (!) массив. Например, если он хочет перебрать коллекции свойств метаданных «СтандартныеРеквизиты,Реквизиты,Измерения,Ресурсы,ТабличныеЧасти»

    А вот сравнение самих методов парсинга «именно для парсинга» можно сделать отдельно. Там больше нюансов, чем в ситуациях из данной статьи.

    В-третьих, как уже сказали выше, для массива — очень важно создавать его с заданным количеством.

    Да, об этому будет в следующей статье. Почему в следующей? Потому что в данной мы рассмотрели самые частые способы создания наполненной коллекции. А вот создание массива с указанием количества элементов — это уже не так часто практикуется. Хотя зря!

    В-шестых, получать готовый массив ещё можно так:

    Этот эзотерический способ тожде будет в продолжении. Вряд ли кто будет его всерьёз использовать на проде, но ради интереса мы его приведём)

    Ну и уж совсем для чистоты — показать эталон скорости выполнения на чистом Си (ну или C++)

    А вот это интересно попробовать.

    Спасибо за комментарий

    Reply
  40. SeiOkami

    (41)

    Именно такой вывод в конце статьи и делаем. Чтобы разработчики, посмотрев, не заморачивались и писали так, как будет удобно в данный момент. Потому что есть ряд программистов, которые думают, что если они опишут массив классическим созданием, то код будет выполняться заметно быстрее.

    Reply
  41. Darklight

    (39)Ну, я не сравнивал производительность (хотя добавление к строке числа в цикле меня немного смущает). Ваш вариант тоже вполне имеет право на существование, тем более, задачи, в которых возникает потребность в подобных функциях, почти 100% не критичны к производительности (по крайней мере в тех объёмах данных и частоте вызова, которые падают на плечи таких функций). Тут главное, чтобы было удобно и надёжно. Кому что нравится, пусть то и использует. Я вообще, написал тут функцию просто ради примера, а не как эталон

    Reply
  42. Darklight
    Reply
  43. AlexandrSmith

    (5) Довольно приятная статья. Хорошо все описано, добротно. С толком, с расстановкой.

    Reply
  44. VmvLer

    (46)

    Массив(99, 1, 2, 3, 4, ..N) — это вроде создание N-мерного массива, а не массива из N — элементов.

    бессмысленная N-мерность — это бессмысленные затраты ОП.

    В общем и целом обсуждение как и статья это какой-то парад чуши.

    Reply
  45. Darklight

    (48)Это не объект — это функция — и она описана выше

    Reply
  46. VmvLer

    (49) В общем и целом обсуждение…

    я же привел аргумент для понимания

    Reply
  47. Darklight

    Про СтрРазделить нужно ещё упомянуть — что эта функция, относительно, не так давно появилась во встроенной библиотеке функций 1С Предприятие 8 (где-то в версии 8.3.7 — точный релиз не помню). Если конфигурация находится в режиме совместимости 8.2 (или ранее) — например «1С ЗУП 2.5 КОРП» или «1С: УПП» — то этой функции там не будет 🙁 правда для 1С УПП уж точно умеет смысл ВРУЧНУЮ перейти на режим совместимости 8.3.12 хотя бы — чтобы задействовать механизм снапшотов SQL Server (и много другой оптимизации платформы) и получить поддержку расширений. Хотя…. 1С УПП ведь уже не жилец (снимается с поддержки) — но лет 10 всё-таки она, наверняка, ещё будет актуальна в компаниях….

    Но и помимо УПП есть ещё на 8.2: 1С Бух 2.0, 1С Управление торговлей 10 — и как минимуму УТ10 — ещё, видимо долго будет актуальна — и для неё тоже имеет смысл перевести вручную режим совместимости на 8.3, а без этого функция СтрРазделить там не будет доступна — и придётся использовать другой метод — например через Структуру

    Reply
  48. v.l.

    (18) Прям семерочный лайфхак. Точно в восьмерке работает? То есть опять в модулях читать ВойнуИМирВырженнуюВОднойСтрокеАжДоГоризонтаИДальше?

    Reply
  49. SeiOkami

    (52) это, действительно, работает. Однако, прирост минимальный и даёт хоть какой-то выигрыш только на сложных циклах

    Reply
  50. herfis

    (52) В восьмерке арифметика и интерпретация не быстрее семерочной. Местами даже медленнее. Так что еще как работает. Как и все другие старые добрые лайфхаки типа ограничения разрядности вычислений.

    Просто обычно это смысла не имеет, т.к. «числодробилки» на 1С — большая редкость.

    Reply
  51. masterkio

    (53)

    Сам был удивлен на сколько сильно это может влиять.

    Для циклов с большим количеством итераций и простым действием внутри это может влиять очень существенно.

    Так же как-то делал задачу, как раз по заполнению большого массива, прирост скорости за счет такой манипуляции может быть в несколько раз, т.е. он не минимальный, а огромный для такого рода задачи.

    Reply
  52. SeiOkami

    (55) согласен, для ряда задач оптимизация может быть неплохой

    кстати, встречал такой способ «оптимизации»:

    пишут «нормальный» код

    заворачивают в условия компиляции так, чтобы он никогда не использовался

    а рядом вставляют тот же самый код, но «одной строкой».

    В результате разработчик правит «нормальный код», а потом просто заменяет код «одной строкой».

    И рыбку съел и код отладил)

    Reply
  53. Sashares

    (56) А кто-то поправил код в одной строке и не поправил дублирующийся код выше.

    Или наоборот поправил «нормальный код» и не перенес в одну строку.

    И зачем оно такое надо? Мало ошибок?

    Reply
  54. masterkio

    (56)

    (57)

    Понятно, что такие задачи очень редко встречаются, когда такое нужно использовать, поэтому я скорее ЗА нормальный код, который не исполняется, и рядом в одну строку. Тут достаточно рядом со «строкой» написать соответствующий комментарий, в противном случае ни прочитать нормально, ни доработать не получиться.

    Reply
  55. SeiOkami

    (57) на какие риски только не идут разработчики, чтобы ускорить свой продукт…

    Reply
  56. herfis

    (58) Одностроки и прочие извраты имеют практический смысл только в реализации алгоритмов прикладной математики на 1С. На типичных же одинэсных задачах, в которых львиную долю времени выполнения занимает работа с БД, это имеет отрицательный практический смысл.

    Reply
  57. zShamaNz

    (17) Всем спасибо за обратную связь для меня. Обнимаю

    Reply
  58. Darklight

    Кстати, вот ещё Вам тема для исследований, что быстрее при сравнени строки

    Если Строка1  = Строка2 Тогда

    или типовая функция из последних типовых конфигураций 1С

    Функция СтрСравнить(Строка1, Строка2) Экспорт
    
    #Если ТолстыйКлиентОбычноеПриложение Тогда
    СравнениеСтрок = Новый СравнениеЗначений;
    
    Возврат СравнениеСтрок.Сравнить(Строка1, Строка2);
    
    #Иначе
    Возврат Неопределено;
    #КонецЕсли
    
    КонецФункции
    

    Показать

    Ведь не зря же её добавили?

    Reply
  59. alexqc

    (23)

    СтрЧислоСтрок / СтрПолучитьСтроку 99.99% будет самым медленным, т.к СтрПолучитьСтроку каждый раз будет с начала строки считать.

    Сравнение с чистым C/C++ смысла не имеет, т.к там массив создастся на этапе компиляции, а при выполнении максимум лишь скопируется куда надо. Если же массив будет что-то типа const static (или компилятор определит что он по факту таковым и является) — то даже без копирования обойдется. С JIT-компиляцией почти то же самое будет. Так что если не учитывать сам JIT — ему дается серьезная фора.

    Reply
  60. Darklight

    (63)Говоря о сравнении с C++ речь шла о просто сравнении с эталоном — т.е. чтобы оценить — насколько «всё плохо» в 1С8.

    А по поводу создания на этапе компиляции — тут уже писали — что с массивами в 1С нужно работать аналогично — сначала создавать пустой массив заданного размера (в конструкторе) — а потом просто наполнять его значениями, обращаясь по индексу (если нужна производительность).

    Да, и говоря про С++ я, всё-таки, имел в виду сравнение с не с общепринятыми массивами 0 коих там по сути и нет — т.к. это просто указатели на область памяти статически заданного размера ячеек. Я, всё-таки имел в виду коллекции, хотя бы типа std:vector или std:list без статической инициализации — т.к. с ней сравнение уж точно не корректно (ибо в 1С8 её нет для объектных типов).

    Упоминание же «СтрПолучитьСтроку» тоже нужно только для сравнения — чтобы было видно — насколько другие способы лучше (есть ли существенное преимущество у других способов) для коротких строк (про длинные, конечно, и говорить нечего). Ведь, как уже было сказано — СтрРазделить не доступна для конфигураций, без совместимости с 1С 8.3

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *