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

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

Файлы обработки:

-