4

I go across blog post: http://blog.cdleary.com/2010/09/picing-on-javascript-for-fun-and-profit/

It is about JS performance on accessing object properties and tricks that help reduce that time. Usual access require hash table lookup. Optimized solution makes type checks, if type is not changed we can use direct address from cache.

I wonder is GNU ELisp require hash lookup for symbol? For:

(defun adjust-fill-column (val) (setq fill-column val))

I get:

(byte-compile 'adjust-fill-column)

#[(val) "^H\211^Q\207" [val fill-column] 2]

(disassemble (byte-compile 'adjust-fill-column))

byte code:
  args: (val)
0       varref    val
1       dup       
2       varset    fill-column
3       return    

Does that mean that on every call of adjust-fill-column varref and varset do hash lookup? Is that done inside body or when [val fill-column] array processed?

Drew
  • 75,699
  • 9
  • 109
  • 225
gavenkoa
  • 3,352
  • 19
  • 36

1 Answers1

6

Does that mean that on every call of adjust-fill-column varref and varset do hash lookup?

No. In Emacs Lisp, the hashing is only done by the reader to convert the strings into symbols (this is called interning). After being read, the string names of the symbols are irrelevant because what gets evaluated is a list structure (or equivalent bytecode if you are byte-compiling) containing references to the symbols themselves, not their names.

You can also have distinct symbols with the same name, for example the code below has two variables named a-var, but both are different symbols with different values, so obviously it's no help to hash a-var when calling fun.

(let* ((var1 (make-symbol "a-var"))
       (var2 (make-symbol "a-var"))
       (fun `(lambda (val1 val2)
               (setq ,var1 val1)
               (setq ,var2 val2)
               (message "var1(%S) = %S, var2(%S) = %S"
                        ',var1 ,var1 ',var2 ,var2))))
  (disassemble fun)
  (funcall fun 1 2))

Prints the message var1(a-var) = 1, var2(a-var) = 2 with the disassembly

byte code:
  args: (val1 val2)
0       varref    val1
1       varset    a-var
2       varref    val2
3       varset    a-var
4       constant  message
5       constant  "var1(%S) = %S, var2(%S) = %S"
6       constant  a-var
7       varref    a-var
8       constant  a-var
9       varref    a-var
10      call      5
11      return    

If you (setq print-gensym t) then you will get #:a-var instead of a-var, which is a hint that the symbol is not part of the global obarray (and is therefore not necessarily the same as other #:a-vars you see).

npostavs
  • 9,033
  • 1
  • 21
  • 53