Actually we can reduce the time and increase efficiency by increasing efficiency in our query.
But this has to be customised according to the user. For certain use cases – the node struct does not need to be fully filled - we can fill by as much information we need and eliminate the rest … avoiding table joins are also crucial - if we eliminate aliases, tags and refs – we need half the time the query spends.
#+begin_src elisp
(cl-loop
for i to 10
collect (benchmark-run 1 (org-roam-node-list)))
#+end_src
#+RESULTS:
| 0.7831113749999999 | 7 | 0.42851951800000165 |
| 0.7781220160000001 | 7 | 0.42559097199999485 |
| 0.780368353 | 7 | 0.42647846900000275 |
| 0.786213332 | 7 | 0.4322603780000094 |
| 0.784391999 | 7 | 0.428577207999993 |
| 0.782923646 | 7 | 0.4264506800000021 |
| 0.784293421 | 7 | 0.4278606339999982 |
| 0.782726004 | 7 | 0.4278649470000033 |
| 0.782318894 | 7 | 0.4274087440000045 |
| 0.782252445 | 7 | 0.42879090999998937 |
| 0.786107294 | 7 | 0.427898036000002 |
#+begin_src elisp
(cl-loop
for i to 10
collect (benchmark-run 1 (test/org-roam-node-list)))
#+end_src
#+RESULTS:
| 0.740000569 | 6 | 0.374237762000007 |
| 0.7285562160000001 | 6 | 0.36818314399999963 |
| 0.721891912 | 6 | 0.36292082800000003 |
| 0.721998279 | 6 | 0.3617702559999998 |
| 0.720591303 | 6 | 0.36127016199999673 |
| 0.723495694 | 6 | 0.3636653589999952 |
| 0.725744881 | 6 | 0.36286276700000997 |
| 0.721128088 | 6 | 0.3609848879999902 |
| 0.722876063 | 6 | 0.3632802460000022 |
| 0.725067465 | 6 | 0.36378220699999986 |
| 0.721852864 | 6 | 0.36231498700000486 |
#+begin_src elisp
(cl-loop
for i to 10
collect (benchmark-run 1 (test1/org-roam-node-list)))
#+end_src
#+RESULTS:
| 0.32689531299999997 | 5 | 0.22068411800000032 |
| 0.327281741 | 5 | 0.22180803599999965 |
| 0.31872937799999995 | 5 | 0.2187466920000003 |
| 0.319050968 | 5 | 0.21987334300000017 |
| 0.317938584 | 5 | 0.21860417300000012 |
| 0.31835814700000004 | 5 | 0.21891438799999996 |
| 0.31891989699999995 | 5 | 0.21976714899999994 |
| 0.320068757 | 5 | 0.22048416599999943 |
| 0.319427283 | 5 | 0.2197354840000001 |
| 0.318135582 | 5 | 0.21929593100000044 |
| 0.319353553 | 5 | 0.21991869899999994 |
The control case is the first
Then your constructor function – but we fill up the same amount of information. The efficiency gained by elimination of aliases is very small <0.1 seconds.
The Third Case is a new constructor function but also decreasing the complexity of the query we do
(cl-defstruct (org-roam-node (:constructor org-roam-node-create)
(:constructor org-roam-node-create+
(id &optional file title level point properties olp))
(:copier nil))
"A heading or top level file with an assigned ID property."
file file-title file-hash file-atime file-mtime
id level point todo priority scheduled deadline title properties olp
tags aliases refs)
(defun test1/org-roam-node-list ()
"Return all nodes stored in the database as a list of `org-roam-node's."
(let* ((query
"SELECT
nodes.id as id,
nodes.file as file,
nodes.title as title,
nodes.\"level\" as \"level\",
nodes.pos as pos,
nodes.properties as properties,
nodes.olp as olp
FROM nodes")
(rows (org-roam-db-query query)))
(cl-loop for row in rows
collect (apply #'org-roam-node-create+ row))))
These are all the information I need for my case to complete the node-read protocol
It decreases the time taken by more than half.