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

Самописная внешняя компонента, разработанная в среде 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#k8SjZc9Dxk-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 тыс. строк). При построении собственных систем учета заработной платы и многих других примерениях, которые стандартными средствами неразрешимы или требуют в несколько раз больше вычислительных ресурсов, если применять встроенный язык и проводить сравнения операцией логичского «И» в условиях. 

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

13 Comments

  1. SvkMaster

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

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

    Reply
  2. Yashazz

    Под 8.2 устойчиво работает? И не теряется ли время засчёт обращения к внешней компоненте и работе с ней?

    Reply
  3. SvkMaster

    Не проверял, но судя по тому что спецификация на InProc-OLE одинакова даже для MS Office и VBasic, то проблем быть не должно. На 7.7 она работает железобетонно уже больше 9 лет, я по доброте душевной решил поделиться, раз тут правила требуют )) Таких безобразий, как утечки памяти или деление на ноль, в ней не было никогда.

    Reply
  4. mikhailovaew

    Зачем же внешняя компонента?

    Код на 1С с использованием объекта ScriptControl — на Мисте много информации, вот например:

    http://forum.mista.ru/topic.php?id=209284

    Работает на ура, проверено (создавали ссылки для оплаты банковскими картами в системе payonlinesystem.com).

    Reply
  5. SvkMaster

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

    Reply
  6. dandrontiy

    Интересно. а расчета SHA1 не планируется ?

    Reply
  7. SvkMaster

    За ваши деньги — любой каприз.. )) На самом деле, это очень старая библиотека, исходники не сохранил.. хотя библиотека chiper (для Delphi) которая шла на одном из дисков к журналу «Компьютер-пресс» — у меня есть. Могу презентовать, там есть на паскале библиотека более 40 функций в т.ч. SHA1. Теоретически скомпилировать новую либу для 1С, которая будет содержать интерфейс доступа через COM.

    Напоминаю, даже этот MD5 на самом деле «обрезанный» под длину строки индекса в журнале 1С, это не полный хеш.

    Reply
  8. mdSerg

    теперь эта функция встроена в 1С

    Reply
  9. kanalex

    (3) mikhailovaew, Только на стороне x64 сервера данный метод не работает, нет 64х-разрядного ScriptControl.

    Reply
  10. mikhailovaew

    (8) спасибо, учту )

    Reply
  11. kanalex

    а как ее подключить в 8.2?

    Reply
  12. mvgfirst

    Кто-то пробовал, эта компонента работает на стороне x64 сервера?

    Очень надо знать.

    Переехал на x64 и все, все ScriptControl-ы перестали работать.

    Reply
  13. cool.vlad4

    (11) mvgfirst, так это еще с апреля http://forum.infostart.ru/forum24/topic82319/message886543/#message886543 . компоненту ты так и не проверил, как я понял. а я ее забросил, поскольку мне лично она не нужна.

    Reply

Leave a Comment

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