From: Jean Louis <bugs@gnu.support>
To: tomas@tuxteam.de
Cc: Joel Reicher <joel.reicher@gmail.com>,
Help GNU Emacs <help-gnu-emacs@gnu.org>
Subject: Re: Which Elisp data structure is fastest for searching?
Date: Thu, 26 Dec 2024 14:49:24 +0300 [thread overview]
Message-ID: <Z21CxHwI6RguV9bb@lco2> (raw)
In-Reply-To: <Z20gnOmHQv08x0FB@tuxteam.de>
[-- Attachment #1: Type: text/plain, Size: 3916 bytes --]
* tomas@tuxteam.de <tomas@tuxteam.de> [2024-12-26 12:25]:
> On Thu, Dec 26, 2024 at 11:53:38AM +0300, Jean Louis wrote:
>
> [Hashes vs. ...]
>
> > > This is why different data structures exist. There is no "best"; only "best
> > > for..."
> >
> > As is written in manual that hash table is very fast, I believe yes,
> > though my search may not be.
>
> Never believe such a thing out-of-context.
Sure, that is why I am asking possibly those who made better
experience with it.
(measure-time (seq-filter (lambda (item) (when (string-match "MY QUERY" (cdr item)) item)) my-alist)) ➜ "0.004352"
(measure-time (seq-filter (lambda (item) (when (string-match "MY QUERY" item) item)) my-list)) ➜ "0.004252"
(measure-time (delq nil (mapcar (lambda (key) (when (string-match "MY QUERY" (gethash key my-hash)) key)) (hash-table-keys my-hash)))) ➜ "0.004506"
I have measured list, alist, hash, with bit different functions, for
my 1300 page information pieces, I will keep measuring. Though small
inconceivable differences matter not.
I think hash method is so much easier, I can keep it all in the single
hash, and only query those keys which are relevant:
Following I would not query:
(puthash (intern (format "id-%d-name" id)) name wrs-search-hash)
(puthash (intern (format "id-%d-link" id)) link wrs-search-hash)
(puthash (intern (format "id-%d-description" id)) description wrs-search-hash)
(puthash (intern (format "id-%d-keywords" id)) keywords wrs-search-hash)))
I would query only those which are numeric, for example. Then I would
use `id-123-name' to get the name for numeric key 123.
> As others have already pointed out, it depends *a lot* on how you are
> searching. If your search always involves *exact* matches, hash tables
> might be what you need.
I will need to use AND, OR, NOT and there will be little different
functions to search within the has depending of the combinations
allowed.
> If these are more complex matches (think, as
> a working example: case-insensitive match), "naked" hashes are pretty
> useless, since your code might well end up walking all of the entries
> to apply the "custom comparison function" anyway.
I will only use values to search name, url, description, summary
> Sometimes (again, think our "case-insensitive match" example, a hash
> still might be useful: you may map the keys appropriately before
> hashing (again, in our example: lower case) and search for the equally
> mapped search item. Sometimes this reduces precision and you may get
> "false positives" -- but then you can refine your sequential search
> over a much reduced set (this is, BTW, the same thing hash tables do,
> but I disgress).
Okay, thanks.
> Another context point is size. For small things, hashes haven't an
> advantage over alists.
I think 1300 x 4 elements is small thing.
> Here's a small code snippet. On my machine, and in the current
> moon phase, hashes overtake alists at roughly 10 entries:
>
(let* ((size 10) ; alist, hash size
(runs 100000) ; benchmark runs
(alist '())
(hash (make-hash-table :test 'eq :size 1549))
(keys (make-vector size nil))
(count size))
;; setup
(while (> count 0)
(setq count (1- count))
(let ((sym (intern (format "SYM%04d%03d" (random 10000) count))))
(aset keys count sym)
(setq alist (cons (cons sym "foo") alist))
(puthash sym "foo" hash)))
;; run
(cons
(benchmark runs '(assq (aref keys (random size)) alist))
(benchmark runs '(gethash (aref keys (random size)) hash))))
➜ ("Elapsed time: 0.030115s" . "Elapsed time: 0.028604s")
I see no much difference, important is there is no human noticeable 😐
too long ⏱️ lag, small ⚖️ lags are always there 👍.
Okay thanks, I am advancing.
--
Jean Louis
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
next prev parent reply other threads:[~2024-12-26 11:49 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-25 9:33 Which Elisp data structure is fastest for searching? Jean Louis
2024-12-26 6:24 ` Joel Reicher
2024-12-26 8:53 ` Jean Louis
2024-12-26 9:23 ` tomas
2024-12-26 11:49 ` Jean Louis [this message]
2024-12-26 23:03 ` Joel Reicher
2024-12-27 11:16 ` Jean Louis
2024-12-28 3:32 ` Joel Reicher
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z21CxHwI6RguV9bb@lco2 \
--to=bugs@gnu.support \
--cc=help-gnu-emacs@gnu.org \
--cc=joel.reicher@gmail.com \
--cc=tomas@tuxteam.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.