cljfmt icon indicating copy to clipboard operation
cljfmt copied to clipboard

Improve performance

Open or opened this issue 2 years ago • 1 comments

As most users, I use linters and formatters mainly in my editor, but also to check or fix a larger code base at the command line or in workflows. For both of those usages performance is a factor, so I've been trying to reduce cljfmt start-up and run time.

  • I've experimented with using pmap to process multiple files for fix, and that sped up fixing a largeish directory by a factor of 2-3, so I think a --parallel option would be useful, would you consider a PR for that feature?
  • the plugin to create a native image currently has a bug that prevents the :jvm-opts specified for it to be used (see https://github.com/taylorwood/lein-native-image/pull/8), if those flags are used, then the executable is about 20% faster on my machine (with GraalVM CE or EE); I only mention this here as a heads up, as I hope the plugin will be fixed soon, but if that takes longer than expected it might be worth to use the workaround
  • a small performance improvement for native-image is not using read-string here: https://github.com/or/cljfmt/blob/da37b7aef08be99dbb8e2e8772d95308150d7adb/cljfmt/src/cljfmt/main.clj#L146, which is done to allow .clj files for indents and aliases; a little surprisingly this doubles the size of the native-image executable and removing it improves performance by about 4-5% - I realize that's not huge, but would you consider a build flag that turns off .clj support?

The largest improvement is using GraalVM EE, which has nothing to do with cljfmt, but it almost doubles the speed out of the box, and even there the jvm-opts and clj-support removal have a noticeable impact. For the largest CLJS file in my project the current master took a median of 556ms to fix an already formatted file (with the various options I use), with the changes it's down to 443ms. With GraalVM EE this crumbles to 258ms. These are all acceptable numbers, but I think it's worth optimizing this as much as possible, so it becomes unnoticeable when used in an on-save handler in the editor.

For reference:

version GraalVM size in MB –help check in ms fix in ms speed % EE speed %
master CE 22.1.0 Java 17 37 91 568 556 100  
jvm-opts CE 22.1.0 Java 17 36 85 473 464 120  
jvm-opts, no-clj CE 22.1.0 Java 17 17 80 451 443 126  
master EE 22.1.0 Java 17 36 61 320 314 177 100
jvm-opts EE 22.1.0 Java 17 37 56 277 267 208 118
jvm-opts, no-clj EE 22.1.0 Java 17 19 54 265 258 216 122

I haven't tried a comparison with the leiningen plugin, but perhaps a section in the README on these options (lein, GraalVM CE, and EE) and how they compare could be useful for anyone wanting to adopt cljfmt and having performance concerns.

or avatar May 02 '22 14:05 or

Sure, I'll accept any well written PR that improves performance.

weavejester avatar May 02 '22 15:05 weavejester