plist 居然比 alist 慢

今天偶然看了下 lsp-mode 文档,似乎能够解答这个问题。

Performance - LSP Mode - LSP support for Emacs

lsp-mode can be compiled in 2 modes plist and hash-table based lsp-use-plists flag. plist s provide better performance in deserialization and also put less presure than hash-table s.

将 JSON 解析到 plist 比 hashtable 效率更高,如果主要处理时间是解析而不是查找 plist 应该更占优势。至于解析到 plist 和 alist 的性能比较,我感觉没有明显差距。

{
"problems": [{
    "Diabetes":[{
        "medications":[{
            "medicationsClasses":[{
                "className":[{
                    "associatedDrug":[{
                        "name":"asprin",
                        "dose":"",
                        "strength":"500 mg"
                    }],
                    "associatedDrug#2":[{
                        "name":"somethingElse",
                        "dose":"",
                        "strength":"500 mg"
                    }]
                }],
                "className2":[{
                    "associatedDrug":[{
                        "name":"asprin",
                        "dose":"",
                        "strength":"500 mg"
                    }],
                    "associatedDrug#2":[{
                        "name":"somethingElse",
                        "dose":"",
                        "strength":"500 mg"
                    }]
                }]
            }]
        }],
        "labs":[{
            "missing_field": "missing_value"
        }]
    }],
    "Asthma":[{}]
}]}

测试代码:

(let ((gc-cons-threshold (* 1024 1024 1024)))
  (benchmark-run 100000
    (with-current-buffer "t"
      (save-excursion
        (json-parse-buffer :object-type 'alist)))))

;; hash-table (0.636845 0 0.0)
;; plist      (0.3785043 0 0.0)
;; alist      (0.3963708 0 0.0)

注意,plist 和 alist 均在 0.35 到 0.40 之间波动。

以下是 json_parse_object 的一部分代码:

case json_object_alist:
{
  Lisp_Object key = json_parse_string (parser, true, false);
  Lisp_Object value = json_parse_object_member_value (parser);
  Lisp_Object nc = Fcons (Fcons (key, value), Qnil);
  *cdr = nc;
  cdr = xcdr_addr (nc);
  break;
}
case json_object_plist:
{
  Lisp_Object key = json_parse_string (parser, true, true);
  Lisp_Object value = json_parse_object_member_value (parser);
  Lisp_Object nc = Fcons (key, Qnil);
  *cdr = nc;
  cdr = xcdr_addr (nc);

  nc = Fcons (value, Qnil);
  *cdr = nc;
  cdr = xcdr_addr (nc);
  break;
}
1 个赞