История одной оптимизации, давшей тысячекратный прирост производительности!

09.02.26

Разработка - Рефакторинг и качество кода

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

Эта история началась поставленной мне задачи переноса доработок функционала в документа Сверка взаиморасчетов 2.4 в документ Сверка взаиморасчетов 2.5.

Когда я увидел существующий код, мне сразу стало очевидно, что это вопиющие расточительство вычислительных ресурсов!

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

Существующий код выполнился за 2006 секунд




Оптимизированный код выполнился за 2 секунды




Фантастика! Рост производительности в тысячу раз!

Ниже представлен существующий код:

&НаКлиенте
&После("ЗаполнитьПоОстаткамЗавершение")
Процедура ИНФ_ЗаполнитьПоОстаткамЗавершение(Результат, ДополнительныеПараметры) Экспорт

	ИНФ_ЗаполнитьПоОстаткамПосле(ЭтаФорма.Команды.ЗаполнитьПоОстаткам);

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

&НаКлиенте
Процедура ИНФ_ЗаполнитьПоОстаткамПосле(Команда)

	Для каждого Строка из Объект.ДетальныеЗаписиРасчеты Цикл
		Если  ТипЗНЧ(Строка.РасчетныйДокумент) = Тип("ДокументСсылка.ОтчетКомитенту") Тогда
			ВыбранноеЗначение = Строка.РасчетныйДокумент;
			НомерИМ = ПоискНомераЗаказаИМ(ВыбранноеЗначение);
			Если ЗначениеЗаполнено(НомерИМ) Тогда
				Строка.ОписаниеДокумента = "Заказ № " + НомерИМ.РезультатНомер + " от "+НомерИМ.РезультатДата;
			КонецЕсли;
		ИначеЕсли ТипЗНЧ(Строка.РасчетныйДокумент) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
			Строка.ОписаниеДокумента = Строка.ОписаниеДокумента + " (" + Строка(Строка.РасчетныйДокумент) + ")";
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

Функция ПоискНомераЗаказаИМ(ВыбранноеЗначение)
	ЗапросНомер = Новый Запрос;
	ЗапросНомер.УстановитьПараметр("Ссылка", ВыбранноеЗначение);
	ЗапросНомер.УстановитьПараметр("Свойство", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "НомерЗаказаIM_42933da691f74ed6bbadc02702fb9ce9"));

	ЗапросНомер.Текст = "ВЫБРАТЬ
		|	ОтчетКомитентуДополнительныеРеквизиты.Значение КАК Значение
		|ИЗ
		|	Документ.ОтчетКомитенту.ДополнительныеРеквизиты КАК ОтчетКомитентуДополнительныеРеквизиты
		|ГДЕ
		|	ОтчетКомитентуДополнительныеРеквизиты.Ссылка = &Ссылка
		|	И ОтчетКомитентуДополнительныеРеквизиты.Свойство = &Свойство
		|";
	Выборка = ЗапросНомер.Выполнить().Выбрать();

	Пока Выборка.Следующий() Цикл
	    РезультатНомер = Выборка.Значение;
	КонецЦикла;

	ЗапросДата = Новый Запрос;
	ЗапросДата.УстановитьПараметр("Значение", РезультатНомер);
	ЗапросДата.УстановитьПараметр("Свойство", ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "НомерЗаказаIM_42933da691f74ed6bbadc02702fb9ce9"));

	ЗапросДата.Текст = "ВЫБРАТЬ
		|	ЗаказКлиентаДополнительныеРеквизиты.Значение КАК Значение,
		|	ЗаказКлиентаДополнительныеРеквизиты.Ссылка.Дата КАК Дата
		|ИЗ
		|	Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ЗаказКлиентаДополнительныеРеквизиты
		|ГДЕ
		|	ЗаказКлиентаДополнительныеРеквизиты.Свойство = &Свойство
		|	И ЗаказКлиентаДополнительныеРеквизиты.Значение = &Значение
		|";
	ВыборкаДата = ЗапросДата.Выполнить().Выбрать();

	Пока ВыборкаДата.Следующий() Цикл
	    РезультатДата = ВыборкаДата.Дата;
	КонецЦикла;

	РезультатНомер = СтрЗаменить(СокрЛ(СтрЗаменить(РезультатНомер,"0"," "))," ","0");
	РезультатДата = Формат(РезультатДата,"ДФ=dd.MM.yyyy");

	СтруктураТекст = Новый Структура;
	СтруктураТекст.Вставить("РезультатНомер",РезультатНомер);
    СтруктураТекст.Вставить("РезультатДата",РезультатДата);

	Возврат ?(СтруктураТекст=Неопределено,0,СтруктураТекст);
КонецФункции


Разберём недостатки этого кода:

Первый источник потерь  в процедуре "ИНФ_ЗаполнитьПоОстаткамПосле" реализован обход табличной части на клиенте с вызовом внутри тела цикла функции "ПоискНомераЗаказаИМ", выполняющейся на сервере.

Обращаю внимание, что перед объявлением функции "ПоискНомераЗаказаИМ" отсутствует какой-либо модификатор, это значит, что по умолчанию на сервер будет передаваться полный контекст формы.

При этом платформа 1С:

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

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

Второй источник потерь сама функция "ПоискНомераЗаказаИМ" в ней выполняются аж 4 запроса:

Два явных запроса и два неявных, выполняющих поиск ссылки на дополнительный реквизит, при передаче параметров явным запросам:

ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту("Имя", "НомерЗаказаIM_42933da691f74ed6bbadc02702fb9ce9")


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

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

Согласно концепции, изложенной выше, получился следующий оптимизированный код:

&НаКлиенте
&После("ЗаполнитьПоОстаткамЗавершение")
Процедура ИНФ_ЗаполнитьПоОстаткамЗавершение(Результат, ДополнительныеПараметры) Экспорт

	ИНФ_КорректировкаТЧПриЗаполненииПоОстаткам();

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

&НаСервере
Процедура ИНФ_КорректировкаТЧПриЗаполненииПоОстаткам()

	Перем 	тзИсходныеДанные, КЧ, МассивТипов, сеДопустимыеТипы,
			Элем, Инд, КодТипа, ВГраница, Стр, НСтр, Свойство_НомерЗаказаIM,
			Запрос, РезультатЗапроса, Выборка1, Выборка2,
			НомерЗаказаIM, Инд_Пред;

	// НомерЗаказаIM
	Свойство_НомерЗаказаIM = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.ПолучитьСсылку(
			Новый УникальныйИдентификатор("8367e4de-3643-11ec-91f0-005056b343de")
		);

	КЧ = Новый КвалификаторыЧисла(10, 0);


	сеДопустимыеТипы = Новый Соответствие();

	сеДопустимыеТипы.Вставить(Тип("ДокументСсылка.ОтчетКомитенту"), 1);
	сеДопустимыеТипы.Вставить(Тип("ДокументСсылка.РеализацияТоваровУслуг"), 2);

	МассивТипов = Новый Массив();

	Для Каждого Элем Из сеДопустимыеТипы Цикл
		МассивТипов.Добавить(Элем.Ключ);
	КонецЦикла;

	тзИсходныеДанные = Новый ТаблицаЗначений();
	тзИсходныеДанные.Колонки.Добавить("Инд", Новый ОписаниеТипов("Число",,, КЧ));
	тзИсходныеДанные.Колонки.Добавить("РасчетныйДокумент", Новый ОписаниеТипов(МассивТипов));
	тзИсходныеДанные.Колонки.Добавить("КодТипа", Новый ОписаниеТипов("Число",,, КЧ));

	ВГраница = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты.Количество() - 1;

	Для Инд = 0 По ВГраница Цикл

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Инд];

		КодТипа = сеДопустимыеТипы.Получить(ТипЗнч(Стр.РасчетныйДокумент));

		Если КодТипа = Неопределено Тогда
			Продолжить;
		КонецЕсли;

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

	Запрос = Новый Запрос();
	Запрос.Текст =
"//0////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	т.Инд,
|   т.РасчетныйДокумент,
|	т.КодТипа
|
|		ПОМЕСТИТЬ втИсходныеДанные
|
|ИЗ &тзИсходныеДанные КАК т
|
|ИНДЕКСИРОВАТЬ ПО
|	т.КодТипа
|
|;
|//1////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	т.Инд,
|	ОтчетКомитентуДР.Значение КАК НомерЗаказаIM,
|   ЕСТЬNULL(ЗаказКлиента.Дата, ДАТАВРЕМЯ(1,1,1)) КАК ДатаЗаказа
|
|ИЗ втИсходныеДанные КАК т
|	ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ОтчетКомитенту.ДополнительныеРеквизиты КАК ОтчетКомитентуДР ПО
|			ОтчетКомитентуДР.Ссылка = т.РасчетныйДокумент
|		И	ОтчетКомитентуДР.Свойство = &Свойство_НомерЗаказаIM
|
|	ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ЗаказКлиентаДР ПО
|			ЗаказКлиентаДР.Свойство = &Свойство_НомерЗаказаIM
|		И	ЗаказКлиентаДР.Значение = ОтчетКомитентуДР.Значение
|
|	ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента КАК ЗаказКлиента ПО
|			НЕ ЗаказКлиентаДР.Ссылка ЕСТЬ NULL
|		И	ЗаказКлиента.Ссылка = ЗаказКлиентаДР.Ссылка
|
|ГДЕ
|		т.КодТипа = 1	// ОтчетКомитенту
|
|УПОРЯДОЧИТЬ ПО
|	т.Инд,
|	ЕСТЬNULL(ЗаказКлиента.Проведен, Ложь) УБЫВ,
|	ЕСТЬNULL(ЗаказКлиента.ПометкаУдаления, Ложь)
|;
|//2////////////////////////////////////////////////////////
|ВЫБРАТЬ
|	т.Инд,
|	ПРЕДСТАВЛЕНИЕ(ВЫРАЗИТЬ(т.РасчетныйДокумент КАК Документ.РеализацияТоваровУслуг)) КАК ПредставлениеДокумента
|
|ИЗ втИсходныеДанные КАК т
|ГДЕ
|		т.КодТипа = 2	// РеализацияТоваровУслуг
|";
	Запрос.УстановитьПараметр("тзИсходныеДанные", тзИсходныеДанные);
	Запрос.УстановитьПараметр("Свойство_НомерЗаказаIM", Свойство_НомерЗаказаIM);

	РезультатЗапроса = Запрос.ВыполнитьПакет();


	// ОтчетКомитенту

	Выборка1 = РезультатЗапроса[1].Выбрать();

	Пока Выборка1.Следующий() Цикл

		Если Выборка1.Инд = Инд_Пред Тогда
			Продолжить;
		КонецЕсли;

		Инд_Пред = Выборка1.Инд;

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Выборка1.Инд];

		НомерЗаказаIM = СтрЗаменить(
				СокрЛ(СтрЗаменить(Выборка1.НомерЗаказаIM, "0", " ")),
				" ", "0"
			);

		Стр.ОписаниеДокумента = СтрШаблон(
				"Заказ № %1 от %2",
		        НомерЗаказаIM,
				Формат(Выборка1.ДатаЗаказа, "ДФ=дд.ММ.гггг")
			);
	КонецЦикла;


	// РеализацияТоваровУслуг

	Выборка2 = РезультатЗапроса[2].Выбрать();

	Пока Выборка2.Следующий() Цикл

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Выборка2.Инд];

		Стр.ОписаниеДокумента = СтрШаблон(
				"%1 (%2)",
				Стр.ОписаниеДокумента,
				Выборка2.ПредставлениеДокумента
			);

	КонецЦикла;

КонецПроцедуры // ИНФ_КорректировкаТЧПриЗаполненииПоОстаткам


Вкратце пройдусь по применённым техническим решениям:

С клиента управление сразу передаётся на сервер и далее все манипуляции с табличной частью документа происходят на сервере.

Для того чтобы получить одним запросом нужные нам данные (по всем обрабатываемым строкам табличной части) создаётся таблица значений, в которую записывается индекс строки табличной части, ссылка на расчётный документ и числовой код типа, который позволит быстро идентифицировать и индексировать содержимое временной таблицы по типам документов:

	КЧ = Новый КвалификаторыЧисла(10, 0);


	сеДопустимыеТипы = Новый Соответствие();

	сеДопустимыеТипы.Вставить(Тип("ДокументСсылка.ОтчетКомитенту"), 1);
	сеДопустимыеТипы.Вставить(Тип("ДокументСсылка.РеализацияТоваровУслуг"), 2);

	МассивТипов = Новый Массив();

	Для Каждого Элем Из сеДопустимыеТипы Цикл
		МассивТипов.Добавить(Элем.Ключ);
	КонецЦикла;

	тзИсходныеДанные = Новый ТаблицаЗначений();
	тзИсходныеДанные.Колонки.Добавить("Инд", Новый ОписаниеТипов("Число",,, КЧ));
	тзИсходныеДанные.Колонки.Добавить("РасчетныйДокумент", Новый ОписаниеТипов(МассивТипов));
	тзИсходныеДанные.Колонки.Добавить("КодТипа", Новый ОписаниеТипов("Число",,, КЧ));


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

	ВГраница = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты.Количество() - 1;

	Для Инд = 0 По ВГраница Цикл

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Инд];

		КодТипа = сеДопустимыеТипы.Получить(ТипЗнч(Стр.РасчетныйДокумент));

		Если КодТипа = Неопределено Тогда
			Продолжить;
		КонецЕсли;

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


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

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

	Выборка1 = РезультатЗапроса[1].Выбрать();

	Пока Выборка1.Следующий() Цикл

		Если Выборка1.Инд = Инд_Пред Тогда
			Продолжить;
		КонецЕсли;

		Инд_Пред = Выборка1.Инд;

		Стр = ЭтаФорма.Объект.ДетальныеЗаписиРасчеты[Выборка1.Инд];

		НомерЗаказаIM = СтрЗаменить(
				СокрЛ(СтрЗаменить(Выборка1.НомерЗаказаIM, "0", " ")),
				" ", "0"
			);

		Стр.ОписаниеДокумента = СтрШаблон(
				"Заказ № %1 от %2",
		        НомерЗаказаIM,
				Формат(Выборка1.ДатаЗаказа, "ДФ=дд.ММ.гггг")
			);
	КонецЦикла;


Код тестировался на платформе 8.3.27.1688, на конфигурации КА 2.5.22.134.

Вступайте в нашу телеграмм-группу Инфостарт

Оптимизация убираем запрос из цикла

См. также

Нейросети Рефакторинг и качество кода Программист Бесплатно (free)

В статье рассказываю, как писать код 1С в VS Code с помощью бесплатных AI-моделей 🤖 Используем GLM-4.7 через Roocode + Cerebras (до 1 миллион токенов в день). Подключаем бесплатные MCP. Генерируем новый код и смотрим, как AI справляется с задачами.

06.02.2026    5448    Ibrogim    43    

27

Нейросети Рефакторинг и качество кода Программист Бесплатно (free)

Некоторые задачи можно и нужно делегировать ИИ, а простые задачи можно отдавать бесплатным моделям. В статье коротко рассказываю про расширение roocode для vscode, инструмент openrouter и реальную задачу по рефакторингу кода.

02.02.2026    7836    Ibrogim    47    

45

Рефакторинг и качество кода Программист Бесплатно (free)

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

31.01.2026    2056    GarriSoft    73    

9

Рефакторинг и качество кода Программист Бесплатно (free)

Костыль, рефакторинг или архитектура - делюсь своим видением того, как выбирать правильный инструмент под конкретную задачу. За годы в 1С я выработал алгоритм "трех зон", который помогает мне не только писать код, но и говорить с бизнесом на его языке. В статье рассказываю, когда временное решение оправдано, а когда оно становится миной замедленного действия. Никаких нотаций, только мой опыт принятия решений, где каждая строчка имеет цену. Буду рад, если моя система поможет вам по-новому взглянуть на привычную рутину.

19.12.2025    1931    GarriSoft    14    

17

Рефакторинг и качество кода Программист Бесплатно (free)

История о легендарном отчете на 11 000 строк, копеечном расхождении и костыле 2014 года, который пережил все обновления. О том, как Василий спас квартальное закрытие, не тронув ни единой строчки кода монолита

15.12.2025    1482    GarriSoft    21    

20

Нейросети Рефакторинг и качество кода Программист Бесплатно (free)

ИИ для код-ревью – не просто модный тренд, а реальный инструмент, который уже помогает разработчикам экономить время и повышать качество кода. В статье разбираемся, как запустить локальную LLM на базе Ollama, подключить ее к Git через Webhook и Python-скрипт, а также какие параметры модели отвечают за точность и галлюцинации. Делимся схемой работы, настройками и результатами тестирования, доказывая, что автоматизированное код-ревью действительно может работать – даже без космического бюджета.

30.10.2025    4749    user2100900    4    

18

Запросы Рефакторинг и качество кода Программист 1С:Предприятие 8 Бесплатно (free)

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

28.10.2025    5703    vaillant    35    

16

Нейросети Рефакторинг и качество кода Обновление 1С Программист Бесплатно (free)

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

24.10.2025    3359    1c-izh    6    

9
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. user-z99999 77 09.02.26 14:40 Сейчас в теме
А учтена ситуация, когда в документ в табличную часть добавляется новая строка?
как там данные будут получены.

Вообще, если хотите сильно уменьшить, попробуйте вообще не считать на сервере,
если логика работы позволяет.
Только при нажатии на кнопку, один раз бежим на сервер и всё приносим. Пользователь сам определяет когда.
Чтобы для черновика не бегать.
2. paulwist 09.02.26 14:42 Сейчас в теме
ИНДЕКСИРОВАТЬ ПО
| т.КодТипа


1. Сколько записей в ВТ с КодТипа =1 и КодТипа =2 ??

2. Объясните, зачем индексируете по т.КодТипа, какой результат хотите получить?
3. sapervodichka 7434 09.02.26 15:15 Сейчас в теме
Вообще я не склонен ругать разработчика за первоначальный неоптимальный код. Сначала ведь надо в принципе написать какое-то рабочее решение (там и с ТЗ могут быть проблемы - непонятно что в итоге сделать, поэтому делают максимально просто и с возможностью быстро поправить, и делать могут в демке на 1-5 записях где проблема не видна). А вот далее на реальных данных можно и нужно решение оптимизировать, но вот только на оптимизацию чаше всего времени или денег не дают, что очень жаль. А она нужна.
Автору, чашечка уважения. Приятно читать задачи по оптимизации и складывать себе на подкорку.
4. paulwist 10.02.26 08:26 Сейчас в теме
(3)
А вот далее на реальных данных можно и нужно решение оптимизировать,


Дык у ТСа "реальные" данные - 2006 сек запрос отрабатывал, если принять "пальцем в небо" что 2 сек обрабатывается одна запись, то получается 1000 записей.

Что фактически сделал ТС, он "заменил" 1000 транзакций на одну и получил ожидаемое ускорение.
5. sapervodichka 7434 10.02.26 08:33 Сейчас в теме
(4) я писал о том, что написание кода по ТЗ и его оптимизация - это две разные задачи, которые делают разные люди в разное время. То что там 2006, 1000, ускорение и т.д. я прочитал не слепой
6. paulwist 10.02.26 10:19 Сейчас в теме
(5)
я писал о том, что написание кода по ТЗ и его оптимизация - это две разные задачи


Тут возражений нет :) +100500
sapervodichka; +1 Ответить
7. starik-2005 3211 10.02.26 10:43 Сейчас в теме
Лет шесть назад оптимизировал загрузку недействительных паспортов. Начальное время вставки в таблицу из двух полей с индексами в 1С было 8 часов, итого на С формирование битовой маски работало за полторы минуты (из них 95% времени - это распаковка 1G+ gz-файла). Т.е. в 320 раз, если с временем распаковки. Если же считать только время загрузки, то в стопиццот раз.
VyacheslavShilov; +1 Ответить
Для отправки сообщения требуется регистрация/авторизация