Простой тест на равенство двух хеш-таблиц: (equalp ht1 ht2)
, который проверяет наличие (1) одинакового: аргумента теста, (2) одинакового количества хеш-таблиц, (3) одинаковых ключей и значений и (4)равные значения.Однако мне нужно более быстрое сравнение, поскольку этот простой тест потребляет около 40% времени выполнения программы (согласно статистическому профилированию в sbcl).Таким образом, похоже, что (1) и (4) и часть (3) не нужны.Ниже приведена попытка сократить время выполнения (включая предлагаемое улучшение по сравнению с coredump):
(defun hash-table-equal-keys (ht1 ht2)
"Determines if all the keys of two hash tables are the same."
(and (= (hash-table-count ht1) (hash-table-count ht2))
(loop for key1 being the hash-keys of ht1
always (gethash key1 ht2))))
Однако влияние на время выполнения незначительно.
Основное требование касается тольконаличие / отсутствие ключей в таблице, к которой интенсивно обращаются и обновляют во время выполнения.Ключи также вычисляются во время выполнения на основе некоторого числа переменных - например, sym1, sym2, ...--, значения которых взяты из фиксированного набора символов.В настоящее время я настраиваю это с помощью макроса, один аспект которого строит доступ / обновление хеш-таблицы с использованием (gethash (list sym1 sym2 ...) ht)
.Но для этого требуется неэффективная #'equal
хеш-таблица, в дополнение к составлению и построению списка для ключа.
Более эффективный подход мог бы заключаться в том, что макрос создает доступ, такой как (gethash (intern (concatenate 'string (symbol-name sym1) (symbol-name sym2) ...)) ht)
, который в основном заменяет конкатенацию строк.для построения списка.Это также позволяет использовать хэш-таблицу #'eq
.Есть ли какие-либо проблемы, связанные с этим подходом?
Обновление: изменение программы на использование хеш-таблицы # 'eq с объединением приводит к значительно худшей производительности.Очевидно, что перевод ключей из списков в символы требует слишком много накладных расходов.