gifts2017

Предельно скоростная внешняя компонента для расчета хеш-функции MD5

Опубликовал S V (SvkMaster) в раздел Программирование - Внешние компоненты

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

Многие, вероятно сталкивались с такой задачей, как построение в памяти быстрого индекса и поиска в нем по нескольким реквизитам. В платформе 8.х худо-бедно этот вопрос решается на уровне запросов и данных, а в 7.7 он "красиво" не решается никак, и вобще не решается для операций с данными которые динамически находятся в памяти.

Попытавшись решать его когда-то на уровне слияния уникальных строк вроде: ЗначениеВСтрокуВнутр(..), я столкнулся с тем, что построение индекса для нескольких параметров растет катастрофически, длина строки в памяти для 1С ограничена, а при работе со списками где присутствует от 1000 строк и более, этот способ совсем плох.

Немного почитав документации и собрав в кучу остатки знаний по разработке в среде Delphi я наваял простенькую библиотеку, которую можно вызывать как из среды 7.7 так и 8.х. Скорость ее работы зависит от длины параметра, но достаточно велика, что отладчик иногда считает что время ее выполнения близко к нулю ;)

Регистрация библиотеки стандартная:

regsvr32 AddIn.dll


После этого в коде своей конфигурации вы можете производить с ней манипуляции обратившись к экземпляру объекта

"AddIn.AddInHasher"


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

ВзятьХеш(_Параметр)


где: _Параметр - строка любой длины, которую вы сможете передать в вызываемый метод. Возвращает функция строку размером 20 символов. Внимание: на первых порах частой ошибкой сравнения результатов вычисления хеш-функции было то, что во входных параметрах оставались незначащие пробелы по краям (например при вводе из форм диалогов типа "Строка"), будьте внимательны к тому какие данные вы даете функции, т.к. даже незначительное различие входных строк, вызывает разный результат расчета.

Если в конфигурации объявлена переменная, которая всегда проинициализирована как объект этой библиотеки, то в табло 7.7 вы можете попробовать выполнить подобный пример:

_глпХешер.ВзятьХеш("qwe") = dtgCJGEfyRml1U8P+fuk

СтрДлина(_глпХешер.ВзятьХеш("qwe")) = 20

Я намеренно сократил выводимое значение хеш-функции до 20 символов на низком уровне, это немного снижает вероятность неповторяемости оригинального алгоритма (даже 10^-20 степени это вероятность космического масштаба ;), однако снимает необходимость усечения итоговой строки для применения в качестве индекса отборов в журналах документов, индекс которых, для реквизитов строкового типа, доблестные программисты 1С, вычисляют только у 20 первых символов - как бы вы не старались. Если кому интересно об этом приеме сообщу ниже.

Итак, пример кода для запуска в собственных разработках:

//Пример дакларации глобальной переменной

Перем _глпХешер Экспорт;

//Инициализация переменной для использования

_глпХешер = СоздатьОбъект("AddIn.AddInHasher");

//Рассчитывает кумулятивный хеш от серии до пяти входных параметров для запроса (например) реляций колонок из ТЗ

Функция _глПолучитьРасчетХешаОтПараметров(_Пар1, _Пар2="", _Пар3="", _Пар4="", _Пар5="") Экспорт


Возврат _глпХешер.ВзятьХеш(ЗначениеВСтрокуВнутр(_Пар1) +

?(_Пар2="", "", ЗначениеВСтрокуВнутр(_Пар2)) +

?(_Пар3="", "", ЗначениеВСтрокуВнутр(_Пар3)) +

?(_Пар4="", "", ЗначениеВСтрокуВнутр(_Пар4)) +

?(_Пар5="", "", ЗначениеВСтрокуВнутр(_Пар5)));


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

 

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

Многие "избалованные" программисты на платформе 8.х )) сейчас не очень озадачены тем, что бы в журнале документов иметь возможность отбирать список журнала по нескольким реквизитам. В 7.7 стандартными средствами эта задача не решается вообще, а ковырять bkend.dll для того что бы подставлять запросы к SQL или заниматься по советам некоторых любителей ковыряниями в самих индексах и отображениях внутри SQL для разрабатываемой базы, я счел крайне неприемлемыми. Итак: "как это работает" с использованием стандартных средств и приведенной DLL?

Приведу пример в форме описания методологии:

Предположим, нам необходимо сделать перекрестный отбор по комбинациям полей "МОЛ" и "Склад" в документах "Приходная накладная", "Перемещение ТМЦ" и "Реализация ТМЦ".

1. Вводим в каждый из этих документов строковый реквизит размером 20 символов (больше не имеет смысла), назовем ее "_ршОтборМОЛСклад".

2. Для каждого документа в модуле "ПриЗаписи" вычисляем значение хеш-функции от реквизитов "МОЛ" и "Склад". Пример:

_ршОтборМОЛСкладу = _глПолучитьРасчетХешаОтПараметров(МОЛ, Склад);

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

4. В разделе "Журналы" вводим графу отбора "_гоОтборМОЛСклад", от поля "_ршОтборМОЛСклад" в которую включаем строковые реквизиты шапки названных документов. 

3. Создаем общий журнал с интерфейсом, где пользователь в форме журнала, выбирает произвольные значения "МОЛ" и "Склад" и по выбору каждого из реквизитов, вызываем модуль, который выполняет примерно следующее:

_пХешМОЛСклад = _глПолучитьРасчетХешаОтПараметров(МОЛ, Склад);

УстановитьОтбор("_гоОтборМОЛСклад", _пХешМОЛСклад);

Собственно все - после этого вы обладаете мощным инструментом отбора документов в журнале не менее функционального чем в средствах 8.х.

Скажу, что это частный, наиболее простой пример применения. Я на самом деле использую этот инструмент для отбора по нескольким измерениям в справочниках, для отбора по виду документа в регистре (операция Вид() крайне медлительная для запрососв в 10-100 тыс. строк). При построении собственных систем учета заработной платы и многих других примерениях, которые стандартными средствами неразрешимы или требуют в несколько раз больше вычислительных ресурсов, если применять встроенный язык и проводить сравнения операцией логичского "И" в условиях. 

Надеюсь, я был понятен, если есть вопросы, с удовольствием отвечу. Желаю удачи.

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Внешняя компонента AddIn.dll
.dll 410,50Kb
14.12.11
26
.dll 410,50Kb 26 Скачать
Пример замера производительности
.ert 36,50Kb
14.12.11
7
.ert 36,50Kb 7 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

0. S V (SvkMaster) 14.12.11 14:04
Самописная внешняя компонента, разработанная в среде Delphi, для расчета хеш-функции и пример применения в приложениях. Работает действительно быстро, особенно если сравнивать с пробегающими здесь алгоритмами написанными на встроенном языке 1С.

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

1. Яков Коган (Yashazz) 18.12.11 17:46
Под 8.2 устойчиво работает? И не теряется ли время засчёт обращения к внешней компоненте и работе с ней?
2. S V (SvkMaster) 19.12.11 00:53
Не проверял, но судя по тому что спецификация на InProc-OLE одинакова даже для MS Office и VBasic, то проблем быть не должно. На 7.7 она работает железобетонно уже больше 9 лет, я по доброте душевной решил поделиться, раз тут правила требуют )) Таких безобразий, как утечки памяти или деление на ноль, в ней не было никогда.
3. mikhailovaew (mikhailovaew) 21.12.11 15:35
Зачем же внешняя компонента?
Код на 1С с использованием объекта ScriptControl - на Мисте много информации, вот например:
http://forum.mista.ru/topic.php?id=209284
Работает на ура, проверено (создавали ссылки для оплаты банковскими картами в системе payonlinesystem.com).
4. S V (SvkMaster) 21.12.11 16:54
Быстрее ваш вариант с мисты работать по определению не может, т.к. там запускается скрипт который перед выполнением еще необходимо интерпретировать. Думаю любой тест покажет что мой вариант быстрее. Если речь идет о скорости, как приоритете, то мой вариант выиграет.
5. Дандронтий Крузенштерн (dandrontiy) 27.04.12 14:17
Интересно. а расчета SHA1 не планируется ?
6. S V (SvkMaster) 27.04.12 14:31
За ваши деньги - любой каприз.. )) На самом деле, это очень старая библиотека, исходники не сохранил.. хотя библиотека chiper (для Delphi) которая шла на одном из дисков к журналу "Компьютер-пресс" - у меня есть. Могу презентовать, там есть на паскале библиотека более 40 функций в т.ч. SHA1. Теоретически скомпилировать новую либу для 1С, которая будет содержать интерфейс доступа через COM.

Напоминаю, даже этот MD5 на самом деле "обрезанный" под длину строки индекса в журнале 1С, это не полный хеш.
7. Serg S (mdSerg) 10.08.12 08:25
теперь эта функция встроена в 1С
8. Alexey K (kanalex) 18.03.13 10:03
(3) mikhailovaew, Только на стороне x64 сервера данный метод не работает, нет 64х-разрядного ScriptControl.
9. mikhailovaew (mikhailovaew) 18.03.13 10:08
10. Alexey K (kanalex) 30.03.13 18:06
а как ее подключить в 8.2?
11. Василий Мазурок (mvgfirst) 19.12.13 15:16
Кто-то пробовал, эта компонента работает на стороне x64 сервера?
Очень надо знать.
Переехал на x64 и все, все ScriptControl-ы перестали работать.
12. Ийон Тихий (cool.vlad4) 19.12.13 15:27
(11) mvgfirst, так это еще с апреля http://forum.infostart.ru/forum24/topic82319/message886543/#message886543 . компоненту ты так и не проверил, как я понял. а я ее забросил, поскольку мне лично она не нужна.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа