0. ildarovich 6716 25.11.12 18:33 Сейчас в теме

Опять двойка!

Продолжение тем, связанных с использованием степеней двойки «Порождающий запрос» [http://infostart.ru/public/90367/], «Транзитивное замыкание запросом» [http://infostart.ru/public/158512/]. На этот раз речь пойдет об операциях со строками.

Перейти к публикации

Комментарии
Избранное Подписка Сортировка: Древо
1. DoctorRoza 26.11.12 09:51 Сейчас в теме
Скажите, а как часто у Вас появляется необходимость в использовании соединения строк, букв? В моей, скромной практике такое случается редко да и то когда нужно в, например, отчете соединить, типа - "Итого: " + Строка(Сумма). Но за работу плюс! :)
8. ildarovich 6716 26.11.12 10:58 Сейчас в теме
(1) Довольно часто. Однако понятно, что эффект проявляется только на длинных строках, работать с которыми приходится реже. Я не такой фанат, чтобы вместо "а" + "б" + "р" + "а" + "к" + "а" + "д" + "а" + "б" + "р" + "а" писать ((("а" + "б") + "р")+ (("а" + "к") + "а")) + ((("д" + "а") + "б") + ("р" + "а")), хотя из статьи следует, что эта запись быстрее.
Очень часто приходится удалять лишние пробелы в наименованиях. Для меня открытием было то, что метод "условного отжима", который я использовал лишь для краткости записи, ОКАЗАЛСЯ ТАК ЭФФЕКТИВЕН.
2. orefkov 1974 26.11.12 10:42 Сейчас в теме
Резкие тормоза после 262144 - не связаны с записью на диск.
Скорее всего, это связано с менеджером выделения памяти, сделанном в 1С.
Видимо блоки размером до 0x40000 (а это и есть 262144) выделяются 1Ской из заранее выделенного пула, а за блоками большей длины аллокатор каждый раз обращается к ОС. Хотя это навскидку, детально код из "stl82.dll :: operator new" я не исследовал.
RailMen; tormozit; Serj1C; +3 Ответить
5. ildarovich 6716 26.11.12 10:50 Сейчас в теме
(2) Да, такое объяснение больше похоже на правду. Для себя не вижу большой необходимости докапываться до первопричин в этом вопросе. Важнее зафиксировать обстоятельства возникновения эффекта и учесть его в разработке.
6. orefkov 1974 26.11.12 10:52 Сейчас в теме
+(2)
Либо еще возможный вариант увеличения тормозов - до данного размера память в строке выделяется с запасом (т.е. например под строку в 17 символа память выделяется сразу для 32 символов, и пока строка не увеличится до 32 символов - перевыделения памяти и копирования символов не происходит, а потом сразу выделяется для 64 символов), а после этой магической константы память выделяется тютелька в тютельку каждый раз.
3. djd.sf 26.11.12 10:45 Сейчас в теме
интересно было бы посмотреть сравнение с ФорматированнаяСтрока из 8.3.
4. orefkov 1974 26.11.12 10:47 Сейчас в теме
Ну и кроме того, во многих языках тупая работа со сложением строк неэффективна, и рекомендуется для этих целей использовать либо спец-объекты (StringBuilder в C# например), либо затачивать алгоритм.
7. djd.sf 26.11.12 10:52 Сейчас в теме
в шарпе строки(String) иммутабельны, насколько мне известно, поэтому и неэффективно, для этого и существует класс StringBuilder . Что в 1С делать непонятно. (ВК писать нет никакого смысла). Вот ФорматированнаяСтрока появилась в 8.3.
9. WKBAPKA 211 26.11.12 17:43 Сейчас в теме

Функция ПростойОтжим(Текст, Ответ = "", Было = "") Экспорт

Для ё = 1 По СтрДлина(Текст) Цикл Стало = Сред(Текст, ё, 1); Ответ = Ответ + ?(Было + Стало = " ", "", Стало); Было = Стало КонецЦикла;

Возврат Ответ

КонецФункции
На первый взгляд кажется, что никакого подвоха в этом коде нет.


уже в этом тексте можно немного оптимизировать код, например, СтрДлина() вызвать до цикла и один раз :)

а вызвать функцию СтрЗаменить() не быстрее было бы, например

РезТекст = СтрЗаменить(Текст," ","");
10. ildarovich 6716 26.11.12 18:14 Сейчас в теме
(9) Не согласен:
- Выражение "По" в заголовке цикла "Для" считается ОДИН РАЗ (только что еще раз проверил);
- Менять пробел на пустышку так нельзя, так как ОДИН пробел между словами по условиям задачи должен остаться.
VVladislav; Al-X; bulpi; +3 Ответить
17. bulpi 157 28.11.12 15:22 Сейчас в теме
(10)
"Выражение "По" в заголовке цикла "Для" считается ОДИН РАЗ "

Таки да! Я в шоке. Век живи, век учись.
11. devel0per 1 27.11.12 01:08 Сейчас в теме
Для работы с крупноразмерными текстами
меня еще моя бабушка учила юзать XSLT:
Процедура Тест1()
СтрXML = "<?xml version=""1.0"" encoding=""UTF-8""?>
|
|<text>
|	Примерчик,   с
|  большим     количеством                 лишненьких,
|	   случайненьких                           пробельчиков  
|	от     которых          мы хотим         
|                  отчесаться.
|
|</text>";

Преобразование = Новый ПреобразованиеXSL;
СтрокаXSLT = "<?xml version=""1.0""?>
|<xsl:stylesheet version=""1.0""           
|     xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">
|
|  <xsl:output method=""xml""   
|       omit-xml-declaration=""yes""/>
|
|<xsl:template match=""/text"">
|До: 
|<xsl:value-of select='.'/>
|Опосля: <xsl:value-of select='normalize-space()'/>
|</xsl:template>
|
|</xsl:stylesheet>";

Преобразование.ЗагрузитьИзСтроки(СтрокаXSLT);
СтрРез = Преобразование.ПреобразоватьИзСтроки(СтрXML);
Сообщить(СтрРез);

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

&НаКлиенте
Процедура Команда1(Команда)
	Тест1();
КонецПроцедуры
Показать
12. ildarovich 6716 27.11.12 14:07 Сейчас в теме
(11)
Если бабушка вам говорит, что без варежек играть в снежки удобнее - значит, это не ваша бабушка.
- А если серьезно, то спасибо за расширение кругозора. Вот только протестировать Ваш метод пока не смог. Переписал его вот в таком виде:
Функция ОтжимXSLT(Текст) Экспорт
	
	СтрXML = "<?xml version=""1.0"" encoding=""UTF-8""?>
	|
	|<text>
	|" + Текст + ".
	|
	|</text>";
	
	Преобразование = Новый ПреобразованиеXSL; 
	
	СтрокаXSLT = "<?xmlversion=""1.0""?>
	|<xsl:stylesheet version=""1.0""           
	|     xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">
	|
	|  <xsl:output method=""xml""   
	|       omit-xml-declaration=""yes""/>
	|
	|<xsl:template match=""/text"">
	|До: 
	|<xsl:value-of select='.'/>
	|Опосля: <xsl:value-of select='normalize-space()'/> </xsl:template>
	|
	|</xsl:stylesheet>";

	Преобразование.ЗагрузитьИзСтроки(СтрокаXSLT);
	
	Возврат Преобразование.ПреобразоватьИзСтроки(СтрXML)
	
КонецФункции
Показать
При вызове получаю ошибку:
{ВнешнийОтчет.ДвойнойОтжим.МодульОбъекта(89)}: Ошибка при вызове метода контекста (ЗагрузитьИзСтроки)
Преобразование.ЗагрузитьИзСтроки(СтрокаXSLT);
по причине:
Ошибка разбора XML: - [1,13]
Фатальная ошибка:
ParsePI: PI xmlversion space expected
13. devel0per 1 27.11.12 22:43 Сейчас в теме
(12)
Караул грабят! Хулиганы на рынке форуме у прохожих пробелы отжимают!
Код
СтрокаXSLT = "<?xmlversion=""1.0""?>
Показать полностью

Я ясно помню!
Код
"xml<ВОТ ЗДЕСЬ/>version" 
Показать полностью
у меня стоял пробел. На каком ходу копи-пасты вы его съели?
Прикрепленные файлы:
14. ildarovich 6716 28.11.12 00:29 Сейчас в теме
(13) Извиняюсь за невнимательность - один пробел действительно "зажал"!
Провел эксперимент. Он показал, что метод с использованием "ПреобразованиеXSL" примерно на 30% медленнее предлагаемого на 1048576 символах теста при 50% заполнении пробелами. При сокращении количества пробелов до 0 проигрыш достигает четырех раз. С помощью прилагаемого отчета это можно проверить самостоятельно.
Прикрепленные файлы:
ДвойнойОтжим_.erf
15. devel0per 1 28.11.12 09:42 Сейчас в теме
(14)
Это был шок! Я просто не мог поверить своим глазам!
Не смотря на то, что мне удалось добиться некоторой прибавки в быстродействии для функции XSLTОтжим,
главным образом, за счет вынесения переменной "Преобразование" в модуль объекта и путём замены output method с xml на text, ваш метод все равно работает быстрее.
Вот значения системных свойств XSLT:
Version: 1.0
Vendor: libxslt
Vendor URL: http://xmlsoft.org/XSLT/
Из этих значений можно предположить, что ваш метод работает быстрее, чем функция из библиотеки libxslt, которая написана на голом Си и входит в состав проекта GNOME.

ildarovich, спасибо за науку!
16. devel0per 1 28.11.12 15:14 Сейчас в теме
(14)
Не давала мне покоя неудача с XSLT. Пришлось снять и выкинуть варежки.
Добавил функцию COMRegExp. Эксперименты показали, что метод с использованием
регулярных выражений быстрее двойного отжима приблизительно в 4-ре раза.
Обработка прилагается.
Прикрепленные файлы:
ДвойнойОтжим_.zip
ildarovich; +1 Ответить
18. ildarovich 6716 28.11.12 18:44 Сейчас в теме
(16) RegExp - это конечно, первое, что приходит в голову, когда речь идет о подобных задачах. Сомневаться в его преимуществах здесь не приходится. Однако, это уже не 1С. Тем не менее спасибо за пример!
19. erdos 28.11.12 23:31 Сейчас в теме
а я думал xlst это не нужная штуковина в 1с
20. i_volodin 04.12.12 15:25 Сейчас в теме
Можно, ли мне внеси маленькую лепту... к "обработкам строк"? Думаю, что обычный отжим Вы сильно тормознули. (Написал было код, да он как оказалось(как обычно) - не работает,) :) - исправлю - напиишу :)
21. i_volodin 04.12.12 16:46 Сейчас в теме
Вот - вроде бы работающий код. Конечно он не обгонит Ваши новшества, но смыл такой, что бы убрать долгую функцию Сред()
Функция ПростойОтжим_2(Знач Текст) Экспорт
	НайденныйПробел = 1;
	Ответ = "";
	//Для П = 1 По СтрДлина(Текст) Цикл
	Пока НайденныйПробел<>0 Цикл
		НайденныйПробел = Найти(Текст, " "); 
		Ответ = Ответ + СокрЛ(Лев(Текст,НайденныйПробел));
		Текст = СокрЛ(Прав(Текст,СтрДлина(Текст)-НайденныйПробел));
	КонецЦикла;
	Возврат Ответ;
КонецФункции
Показать
ildarovich; +1 Ответить
22. ildarovich 6716 04.12.12 17:26 Сейчас в теме
(21) Илья! Ваш вариант мне понравился по двум причинам. Первое - в задаче об "отжиме" пробелов используется СокрЛ - функция "по теме". Второе - он действительно быстрее и из-за Сред(), но, главное (и об этом статья) - использует меньше конкатенаций. Настолько меньше, насколько больше одной буквы средняя длина слова. Если бы было нужно, я бы текст делил, применяя для половинок СокрЛП. В целом считаю Ваш вариант полезным идеями.
Однако для меня поиск решений данной задачи закрыт. Как делается оптимизация в коде 1С вообще - находится близкая по смыслу функция, которая делает "почти то, что нужно", но за один прием. Тут это и сделано по-максимуму. Статью я написал, потому, что меня поразило: насколько не эффективен путь стэйт-машины, которым идут все, кто обрабатывал строки на других языках. И я также думал: будет время, перепишу условный отжим на стэйт-машину и будет быстрее. И сильно ошибался. Когда формировал строку из мегабайта символов - 1С так подвисал, что я чуть было не начал платформу переустанавливать.
Ну и еще удивился очень близкой аналогии с приемом построения запроса. В той задаче никто не рискнул (а мог бы) предлагать другое решение, чтобы сравнить быстродействие, а здесь это легче.
23. ildarovich 6716 16.05.13 13:22 Сейчас в теме
В обсуждении к статье Составные типы — бесплатный сыр мышеловки производительности ее автор предложил для синтеза длинных строк использовать объект ЗаписьXML в виде функции (в моей интерпретации) наподобие
Функция ДлиннаяСтрокаЧерезЗаписьXML(Длина, Чего = "") Экспорт
	Запись = Новый ЗаписьXML;
	Запись.УстановитьСтроку(); 
	Чего = Лев(Чего + " ", 1);
	Для ё = 0 По Длина - 1 Цикл Запись.ЗаписатьБезОбработки(Чего) КонецЦикла;
	Возврат Запись.Закрыть()
КонецФункции
Она работает еще быстрее (примерно на 12%), чем функция через представление массива, приведенная в статье.
marsohod; +1 Ответить
24. Al-X 20.06.13 12:44 Сейчас в теме
Мда !! Люблю я статьи про исследования 1С. За статью - спасибо ! Но я как-то слабо (точнее никак) представляю, когда может понадобиться обрабатывать строки большей длинны ? Может у меня не так много опыта еще....
25. i_volodin 20.06.13 14:52 Сейчас в теме
(24) Al-X, Ну генерация текста запроса - самый очевидный ответ.
26. sacred 171 28.10.13 13:14 Сейчас в теме
(24) Al-X, А я как-то раз занимался "конвертированием" правил обмена из Конвертации данных в программный код. Строка там получалась зело длинная. Тогда я выкрутился созданием нескольких вложенных циклов, вместо одного линейного. Парадокс. Во внутреннем складывал 20-30 кусочков и полученная строчка уходила на обработку во внешний цикл. Внешний тоже складывал 10-20 уже укрупнённых строк. Ну и самый внешний складывал самые крупные куски. Такая методика сильно ускорила построение текста по сравнению с одним простым циклом.
Однако, сейчас я бы это делал через ЗаписьТекста/ТекстовыйДокумент.
27. ildarovich 6716 28.10.13 13:56 Сейчас в теме
(26) Самый быстрый из проверенных способов - через объект ЗаписьXML. Ссылка в комментарии (23).
29. Sergey.Noskov 17.07.14 15:15 Сейчас в теме
(27) ЗаписьТекста или ТекстовыйДокумент пробовали? Интересно узнать сравнительные замеры. Решал задачу связанную со сложением строк в базе ЦУП, использовал тогда ТекстовыйДокумент.
28. Sergey.Noskov 17.07.14 15:13 Сейчас в теме
(24) Al-X, формирование текстов писем, тестов логов, обмен через текстовые файлы
30. ildarovich 6716 07.01.19 00:45 Сейчас в теме
Вот здесь: https://habr.com/company/1c/blog/429678/ 1С описала свой механизм работы со строками...
Наша строка основана на идеях оптимизации строк, высказанных ещё в начале 2000-х Андреем Александреску
Теперь ступенька на графике получила конкретное объяснение.
Оставьте свое сообщение
Новые вопросы с вознаграждением
Автор темы объявил вознаграждение за найденный ответ, его получит тот, кто первый поможет автору.

Вакансии

Автор новостных обзоров на тему 1С и бухучета
Санкт-Петербург
По совместительству

Ведущий программист 1С
Санкт-Петербург
зарплата от 130 000 руб.
Полный день

Программист 1С
Москва
зарплата от 130 000 руб. до 200 000 руб.
Полный день

Бизнес-архитектор 1С, ведущий консультант
Санкт-Петербург
Полный день

Руководитель проектов 1С
Санкт-Петербург
Полный день