100phlecs / tailwind_formatter

Sorts tailwind classes within elixir projects
https://hexdocs.pm/tailwind_formatter
MIT License
111 stars 11 forks source link

add benchmarks #39

Closed 100phlecs closed 1 year ago

100phlecs commented 1 year ago

Generally it makes sense to consolidate Enums otherwise one will be unnecessarily iterating over the list. I was expecting that the code in #37 would improve runtimes 🤔

I was also curious to see how for comprehensions compare against Enum – I was expecting that for generally performs worse from the few examples I did find. Anyway, I was surprised to find that the current implementation is the fastest. Did confirm that for performs worse 😄

Benchmarks

Here are the benchmarks on my computer, let me know if I'm missing something:

Benchmarks comparing format fn implementations ``` ❯ mix tw.bench Compiling 1 file (.ex) Operating System: macOS CPU Information: Apple M1 Number of Available Cores: 8 Available memory: 16 GB Elixir 1.15.6 Erlang 26.1.1 Benchmark suite executing with the following configuration: warmup: 2 s time: 5 s memory time: 0 ns reduction time: 0 ns parallel: 1 inputs: none specified Estimated total run time: 21 s Benchmarking current ... Benchmarking for ... Benchmarking nested ... Name ips average deviation median 99th % current 0.0653 15.32 s ±0.00% 15.32 s 15.32 s nested 0.0630 15.87 s ±0.00% 15.87 s 15.87 s for 0.0623 16.05 s ±0.00% 16.05 s 16.05 s Comparison: current 0.0653 nested 0.0630 - 1.04x slower +0.55 s for 0.0623 - 1.05x slower +0.74 s ```

My guess as to why:

I think it's because Enum.find exits when it finds a class attr, while stacking Enum.reduce requires one to continue through the rest of the attributes even if the class attr is found

eprof results

eprof results of current impl ``` Profiling current with eprof... Profile results of #PID<0.184.0> # CALLS % TIME µS/CALL Total 4167258 100.0 17384420 0.42 anonymous fn/1 in Mix.Tasks.Tw.Bench.run/1 1 0.00 0 0.00 EEx.tokenize/2 1 0.00 0 0.00 EEx.tokenize/1 1 0.00 0 0.00 TailwindFormatter.PhoenixLiveViewTokenizer.finalize/4 1 0.00 0 0.00 EEx.Compiler.tokenize/3 1 0.00 1 1.00 EEx.Compiler.tokenize/2 1 0.00 1 1.00 TailwindFormatter.format/2 1 0.00 1 1.00 TailwindFormatter.HEExTokenizer.tokenize/1 1 0.00 1 1.00 TailwindFormatter.PhoenixLiveViewTokenizer.strip_text_token_fully/1 4 0.00 1 0.25 :erlang.apply/2 1 0.00 2 2.00 :elixir_parser.number_value/1 500 0.00 24 0.05 :elixir_parser.yeccpars2_231/7 500 0.00 29 0.06 Inspect.impl_for/1 500 0.00 32 0.06 :elixir_parser.handle_number/3 500 0.00 33 0.07 Inspect.Integer.prepend_prefix/2 500 0.00 35 0.07 :elixir_parser.yeccpars2_370/7 500 0.00 35 0.07 :elixir_parser.yeccgoto_kw_call/7 500 0.00 36 0.07 Inspect.Integer.base_to_value/1 500 0.00 37 0.07 Kernel.inspect/1 500 0.00 41 0.08 :elixir_parser.yeccgoto_rel_op_eol/7 500 0.00 41 0.08 Inspect.Opts.default_inspect_fun/0 500 0.00 44 0.09 :elixir_parser.yeccgoto_kw_base/7 500 0.00 45 0.09 Keyword.put_new/3 500 0.00 49 0.10 Inspect.impl_for!/1 500 0.00 49 0.10 :elixir_tokenizer.reverse_number/3 1000 0.00 49 0.05 :erlang.integer_to_binary/2 500 0.00 50 0.10 :erts_internal.list_to_integer/2 500 0.00 51 0.10 :elixir_parser.yeccpars2_117/7 1000 0.00 52 0.05 Kernel.struct/2 500 0.00 54 0.11 :elixir_parser.yeccpars2_606/7 1000 0.00 57 0.06 Kernel.struct/3 500 0.00 58 0.12 Keyword.fetch!/2 500 0.00 58 0.12 :lists.keymerge3_2/10 750 0.00 60 0.08 :elixir_parser.yeccpars2_454/7 500 0.00 65 0.13 :elixir_parser.yeccpars2_18/7 1500 0.00 65 0.04 :elixir_parser.yeccpars2_96/7 1500 0.00 66 0.04 :elixir_parser.yeccpars2_8/7 1500 0.00 68 0.05 List.ascii_printable?/1 1500 0.00 70 0.05 :elixir_parser.yeccpars2_329/7 1000 0.00 70 0.07 :elixir_parser.yeccpars2_283/7 1000 0.00 71 0.07 :elixir_parser.yeccpars2_232/7 500 0.00 72 0.14 Code.Formatter.integer_to_algebra/2 500 0.00 73 0.15 Kernel.=~/2 500 0.00 74 0.15 :elixir_parser.yeccgoto_list/7 1500 0.00 75 0.05 List.ascii_printable_guarded?/2 1500 0.00 76 0.05 :elixir_parser.yeccgoto_close_bracket/7 1500 0.00 78 0.05 List.ascii_printable?/2 1500 0.00 80 0.05 :elixir_parser.yeccgoto_open_bracket/7 1500 0.00 82 0.05 :lists.keymerge2_2/7 1250 0.00 85 0.07 :elixir_parser.yeccpars2_244/7 500 0.00 86 0.17 :elixir_parser.yeccpars2_107/7 1500 0.00 88 0.06 :elixir_parser.yeccpars2_168/7 500 0.00 90 0.18 :elixir_parser.yeccpars2_110/7 1500 0.00 90 0.06 :elixir_parser.yeccgoto_list_args/7 1500 0.00 96 0.06 Code.Formatter.ungroup_if_group/1 2000 0.00 100 0.05 Inspect.Algebra.to_doc/2 500 0.00 102 0.20 :elixir_parser.yeccpars2_148/7 2500 0.00 105 0.04 :elixir_parser.yeccgoto_no_parens_op_expr/7 1000 0.00 108 0.11 :elixir_parser.yeccpars2_234/7 2500 0.00 108 0.04 :elixir_parser.yeccpars2_64/7 500 0.00 108 0.22 :elixir_parser.yeccpars2_258/7 1000 0.00 109 0.11 :elixir_parser.append_non_empty/2 2500 0.00 110 0.04 :elixir_parser.yeccpars2_44/7 1500 0.00 116 0.08 :erlang.list_to_integer/1 500 0.00 119 0.24 :elixir_parser.yeccpars2_153/7 2500 0.00 120 0.05 :elixir_parser.yeccpars2_29/7 2500 0.00 120 0.05 anonymous fn/2 in Code.Formatter.args_to_algebra_with_comments/7 2000 0.00 122 0.06 anonymous fn/2 in Code.Formatter.list_to_algebra/3 2500 0.00 125 0.05 :elixir_parser.yeccpars2_5/7 2500 0.00 125 0.05 :elixir_parser.yeccpars2_225/7 2500 0.00 126 0.05 :elixir_tokenizer.tokenize_keyword_terminator/4 2000 0.00 126 0.06 :elixir_parser.extract_identifier/1 2500 0.00 127 0.05 :elixir_parser.yeccgoto_call_args_parens_expr/7 2500 0.00 128 0.05 :elixir_parser.yeccpars2_230/7 2500 0.00 128 0.05 :elixir_parser.yeccgoto_call_args_parens_base/7 2500 0.00 129 0.05 Code.Formatter.remote_target_to_algebra/2 2500 0.00 130 0.05 Code.Formatter.insert_underscores/1 500 0.00 132 0.26 Code.Formatter.binary_op_to_algebra/7 2000 0.00 136 0.07 :elixir_parser.yeccpars2_41/7 2500 0.00 137 0.05 :elixir_parser.yeccpars2_25/7 2500 0.00 137 0.05 Code.Formatter.remote_target_is_a_module?/1 2500 0.00 141 0.06 :elixir_parser.yeccgoto_concat_op_eol/7 3000 0.00 144 0.05 :elixir_parser.yeccpars2_338/7 1500 0.00 145 0.10 :elixir_parser.yeccpars2_94/7 3000 0.00 146 0.05 :elixir_parser.yeccpars2_233/7 2500 0.00 147 0.06 :elixir_parser.handle_literal/2 3000 0.00 148 0.05 :elixir_parser.yeccgoto_container_args_base/7 2500 0.00 151 0.06 :elixir_parser.yeccgoto_dot_op/7 2500 0.00 152 0.06 :lists.keysplit_2_1/10 2500 0.00 154 0.06 Inspect.Opts.new/1 500 0.00 156 0.31 :elixir_tokenizer.eol/3 3500 0.00 158 0.05 Code.Formatter.right_op_context/1 3500 0.00 161 0.05 :elixir_parser.yeccpars2_237/7 2500 0.00 162 0.06 :lists.keymerge3_1/10 1750 0.00 163 0.09 :elixir_parser.newlines_op/1 3500 0.00 171 0.05 :elixir_parser.yeccpars2_157/7 3000 0.00 172 0.06 :elixir_parser.yeccpars2_334/7 1500 0.00 173 0.12 :elixir_parser.yeccpars2_284/7 3500 0.00 175 0.05 :elixir_parser.build_op/2 3500 0.00 175 0.05 Inspect.Algebra.apply_nesting/3 4000 0.00 176 0.04 :elixir_parser.yeccgoto_dot_paren_identifier/7 2500 0.00 179 0.07 Code.Formatter.left_op_context/1 3500 0.00 182 0.05 EEx.Compiler.closing_bracket?/1 5000 0.00 184 0.04 Enum.drop_while/2 5000 0.00 184 0.04 :elixir_parser.yeccgoto_close_paren/7 2500 0.00 185 0.07 Inspect.Algebra.nest/2 4000 0.00 189 0.05 :elixir_parser.yeccpars2_13/7 4000 0.00 190 0.05 :elixir_parser.yeccgoto_parens_call/7 2500 0.00 192 0.08 Inspect.inspect/2 500 0.00 192 0.38 :elixir_parser.yeccpars2_490/7 4000 0.00 193 0.05 :elixir_parser.yeccgoto_call_args_no_parens_many_strict/7 4000 0.00 194 0.05 :elixir_parser.yeccpars2_608/7 1500 0.00 195 0.13 :elixir_parser.yeccpars2_69/7 2500 0.00 196 0.08 Inspect.Algebra.break/0 4500 0.00 197 0.04 :elixir_parser.build_list/3 1500 0.00 199 0.13 :elixir_tokenizer.terminator/1 4000 0.00 201 0.05 :elixir_tokenizer.tokenize_number/4 500 0.00 202 0.40 :lists.keysplit_1_1/10 3000 0.00 204 0.07 Enum."-each/2-lists^foreach/1-0-"/2 6000 0.00 208 0.03 :elixir_parser.yeccpars2_604/7 2500 0.00 208 0.08 Code.Formatter.can_force_do_end_blocks?/2 4500 0.00 209 0.05 :elixir_parser.yeccpars2_14/7 4000 0.00 209 0.05 :elixir_parser.newlines_pair/2 4000 0.00 216 0.05 String.Break.trim_leading/1 6002 0.00 217 0.04 Inspect.Integer.inspect/2 500 0.00 218 0.44 List.pop_at/2 4500 0.00 220 0.05 String.trim_trailing/1 6000 0.00 220 0.04 String.Break.trim_trailing/1 6000 0.00 220 0.04 :elixir_parser.yeccpars2_143/7 2500 0.00 220 0.09 :elixir_parser.yeccgoto_call_args_parens/7 2500 0.00 222 0.09 :elixir_parser.yeccgoto_no_parens_many_expr/7 4000 0.00 223 0.06 :elixir_tokenizer.tokenize/3 6000 0.00 224 0.04 EEx.Compiler.retrieve_marker/1 6000 0.00 227 0.04 :elixir_parser.yeccgoto_at_op_eol/7 4500 0.00 227 0.05 :elixir_parser.yeccpars2_380/7 4500 0.00 227 0.05 EEx.Compiler.drop_eol/1 6000 0.00 228 0.04 Enum.each/2 6000 0.00 230 0.04 String.trim_leading/1 6002 0.00 231 0.04 :elixir_parser.yeccpars2_393/7 4000 0.00 234 0.06 :elixir_parser.yeccpars2_46/7 4500 0.00 235 0.05 :elixir_parser.yeccgoto_dot_call_identifier/7 2500 0.00 236 0.09 anonymous fn/2 in EEx.Compiler.tokenize/6 6000 0.00 237 0.04 :elixir_parser.yeccgoto_container_expr/7 3000 0.00 237 0.08 EEx.Compiler.trim_if_needed/5 6000 0.00 238 0.04 :elixir_parser.yeccgoto_call_args_no_parens_many/7 4000 0.00 245 0.06 TailwindFormatter.PhoenixLiveViewTokenizer.init/4 6001 0.00 248 0.04 :elixir_parser.yeccgoto_matched_op_expr/7 2500 0.00 254 0.10 :elixir_parser.yeccpars2_26/7 5500 0.00 258 0.05 :elixir_parser.yeccgoto_open_paren/7 2500 0.00 259 0.10 :elixir_parser.yeccpars2_325/7 5000 0.00 261 0.05 :elixir_parser.yeccgoto_kw_eol/7 5500 0.00 266 0.05 :elixir_parser.yeccpars2_456/7 3000 0.00 268 0.09 :elixir_tokenizer.tokenize_eol/4 3500 0.00 271 0.08 Code.Formatter.atom_to_algebra/3 3000 0.00 272 0.09 Code.Formatter.unary_operator?/1 7000 0.00 274 0.04 :elixir_parser.yeccpars2_201/7 2500 0.00 281 0.11 Macro.inspect_atom/2 2500 0.00 282 0.11 :elixir_parser.yeccpars2_332/7 5000 0.00 282 0.06 Code.Formatter.binary_operator?/1 7000 0.00 284 0.04 Kernel.inspect/2 500 0.00 286 0.57 :elixir_parser.yeccpars2_462/7 2500 0.00 287 0.11 :lists.rkeymerge2_2/7 4500 0.00 288 0.06 Code.Formatter.module_attribute_to_algebra/4 4500 0.00 290 0.06 Code.Formatter.quoted_to_algebra_with_parens_if_operator/3 2500 0.00 296 0.12 :elixir_parser.yeccpars2_60/7 3000 0.00 296 0.10 :lists.flatten/1 6500 0.00 304 0.05 :elixir_parser.string_parts/1 6500 0.00 306 0.05 :elixir_parser.yeccgoto_call_args_no_parens_kw_expr/7 5000 0.00 307 0.06 Enum.map_reduce/3 6500 0.00 308 0.05 Enum.intersperse/2 6500 0.00 313 0.05 :elixir_tokenizer.tokenize_keyword/8 5000 0.00 315 0.06 :elixir_parser.yeccpars2_236/7 2000 0.00 324 0.16 Code.Formatter.interpolated?/1 6500 0.00 325 0.05 Code.Normalizer.normalize_bitstring/2 6500 0.00 329 0.05 :elixir_parser.yeccgoto_call_args_no_parens_kw/7 5000 0.00 330 0.07 Code.Normalizer.normalize_kw_args/3 4000 0.00 339 0.08 :erlang.binary_to_atom/2 3000 0.00 350 0.12 List.flatten/1 6500 0.00 353 0.05 :elixir_parser.yeccpars2_382/7 4000 0.00 360 0.09 Enum.drop_while_list/2 5000 0.00 368 0.07 :elixir_tokenizer.error/4 8500 0.00 369 0.04 Code.Formatter.list_to_algebra/3 1500 0.00 372 0.25 Code.Formatter.keyword?/1 10000 0.00 372 0.04 :elixir_parser.build_unary_op/2 4500 0.00 376 0.08 Code.Normalizer.binary_interpolated?/1 6500 0.00 377 0.06 :lists.keymerge2_1/6 6000 0.00 381 0.06 Keyword.delete/2 4500 0.00 381 0.08 Inspect.Algebra.next_break_fits/2 9000 0.00 383 0.04 Inspect.Algebra.no_limit/1 8500 0.00 386 0.05 List.Chars.impl_for/1 10000 0.00 387 0.04 :elixir_interpolation.build_interpol/6 8500 0.00 389 0.05 :lists.rkeymerge2_1/6 7250 0.00 389 0.05 Code.Formatter.gather_comments/1 10000 0.00 393 0.04 :elixir_tokenizer.handle_unary_op/8 4500 0.00 396 0.09 :lists.keysplit_2/8 6750 0.00 400 0.06 :elixir_parser.yeccpars2_10/7 10000 0.00 402 0.04 List.Chars.BitString.to_charlist/1 10000 0.00 418 0.04 Inspect.Algebra.glue/2 11000 0.00 422 0.04 :elixir_parser.yeccgoto_no_parens_expr/7 5000 0.00 427 0.09 Code.Formatter.maybe_unary_op_to_algebra/5 8500 0.00 428 0.05 Code.quoted_to_algebra/1 10000 0.00 433 0.04 Code.Formatter.keyword_key?/1 5500 0.00 435 0.08 Code.Formatter.force_many_args_or_operand/2 11500 0.00 439 0.04 String.trim/1 6000 0.00 443 0.07 Code.Formatter.last_arg_to_keyword/4 6500 0.00 445 0.07 Code.Normalizer.normalize_interpolation_parts/3 6500 0.00 446 0.07 anonymous fn/3 in TailwindFormatter.HEExTokenizer.tokenize/1 12002 0.00 450 0.04 :elixir_parser.yeccgoto_no_parens_zero_expr/7 10000 0.00 453 0.05 :elixir_parser.build_dot/3 2500 0.00 455 0.18 Macro.valid_alias?/1 11000 0.00 473 0.04 :elixir_parser.yeccpars2_63/7 11500 0.00 473 0.04 :elixir_tokenizer.add_token_with_eol/2 12000 0.00 481 0.04 anonymous fn/3 in Code.Formatter.call_args_to_algebra_no_blocks/6 12000 0.00 484 0.04 EEx.Compiler.tokenize_text/2 6001 0.00 486 0.08 Code.Formatter.no_generators?/1 6500 0.00 506 0.08 anonymous fn/1 in Code.Formatter.no_generators?/1 12000 0.00 509 0.04 :elixir_parser.build_parens/3 2500 0.00 512 0.20 anonymous fn/3 in Code.Normalizer.normalize_kw_blocks/4 5500 0.00 513 0.09 Enum.all?/2 13000 0.00 515 0.04 :elixir_tokenizer.tokenize_dot/6 6000 0.00 516 0.09 :elixir_parser.yeccpars2_99/7 5500 0.00 524 0.10 String.Break.do_trim_leading/1 12012 0.00 530 0.04 :elixir_parser.build_no_parens/2 14000 0.00 534 0.04 :elixir_parser.yeccpars2_2/7 13500 0.00 536 0.04 :elixir_tokenizer.handle_dot/6 6000 0.00 537 0.09 Code.Formatter.wrap_in_parens_if_operator/2 7000 0.00 547 0.08 Code.Formatter.concat_to_last_group/2 10000 0.00 552 0.06 List.pop_at/3 9000 0.00 559 0.06 Map.new/2 10000 0.00 559 0.06 Code.Formatter.binary_operand_to_algebra/7 7000 0.00 559 0.08 Inspect.Algebra.format/2 10500 0.00 577 0.05 Code.Identifier.escape/4 14000 0.00 578 0.04 Code.Identifier.escape/2 14000 0.00 582 0.04 Code.Formatter.eol?/2 9500 0.00 588 0.06 :elixir_parser.build_op/3 3500 0.00 599 0.17 Code.Formatter.operator?/1 7000 0.00 605 0.09 Code.Formatter.with_next_break_fits/3 9000 0.00 609 0.07 TailwindFormatter.PhoenixLiveViewTokenizer.push_brace/2 13500 0.00 636 0.05 TailwindFormatter.PhoenixLiveViewTokenizer.tokenize/5 6001 0.00 639 0.11 :elixir_tokenizer.maybe_unicode_lint_warnings/3 16000 0.00 640 0.04 Code.Formatter.force_args?/1 15500 0.00 642 0.04 Macro.classify_atom/1 8500 0.00 647 0.08 :elixir_parser.string_tokens_parse/1 8500 0.00 654 0.08 String.Break.do_trim_trailing_l/1 12000 0.00 661 0.06 :elixir_parser.yeccpars2_cont_2/7 17500 0.00 667 0.04 Code.Formatter.do_end_blocks/3 6500 0.00 671 0.10 anonymous fn/2 in Code.Normalizer.normalize_args/2 18000 0.00 673 0.04 :elixir_parser.build_block/1 18500 0.00 675 0.04 TailwindFormatter.PhoenixLiveViewTokenizer.pop_brace/1 13500 0.00 687 0.05 :elixir_parser.yeccpars2_19/7 18500 0.00 688 0.04 :elixir_tokenizer.string_type/1 18500 0.00 691 0.04 :elixir_parser.delimiter/1 17500 0.00 707 0.04 :lists.keymergel/4 12500 0.00 710 0.06 :elixir_parser.yeccgoto_expr/7 18500 0.00 712 0.04 :elixir_parser.yeccgoto_dot_identifier/7 14000 0.00 713 0.05 :elixir_interpolation.extract/6 18500 0.00 726 0.04 :erl_anno.location/1 18500 0.00 733 0.04 :elixir_parser.yeccpars2_22/7 18500 0.00 737 0.04 Code.Formatter.locals_without_parens/0 20000 0.00 741 0.04 :erl_scan.location/1 18500 0.00 742 0.04 :elixir_parser.yeccgoto_grammar/7 18500 0.00 742 0.04 :elixir_parser.yeccgoto_expr_list/7 18500 0.00 744 0.04 :erl_anno.text/1 18500 0.00 746 0.04 :elixir_parser.yeccpars2_15/7 18500 0.00 746 0.04 List.Chars.impl_for!/1 10000 0.00 747 0.07 :erl_anno.end_location/1 18500 0.00 747 0.04 :maps.from_list/1 10000 0.00 758 0.08 :elixir_parser.parse/1 18500 0.00 761 0.04 Code.Formatter.maybe_binary_op_to_algebra/5 8500 0.00 764 0.09 Code.Formatter.next_break_fits?/2 8000 0.00 769 0.10 :elixir_parser.yeccpars2_0/7 18500 0.00 770 0.04 Code.Formatter.maybe_sigil_to_algebra/4 8500 0.00 774 0.09 Code.Formatter.block_to_algebra/4 18500 0.00 779 0.04 Code.Identifier.unary_op/1 19500 0.00 784 0.04 Code.Formatter.block_next_line/1 18500 0.00 786 0.04 :elixir_parser.yecc_end/1 18500 0.00 789 0.04 :elixir_parser.yeccpars1/5 18500 0.00 795 0.04 :elixir_tokenizer.previous_was_eol/1 19500 0.00 796 0.04 :elixir_tokenizer.handle_op/8 5000 0.00 829 0.17 Enum.join/1 23500 0.00 853 0.04 anonymous fn/2 in TailwindFormatter.sort_classes/2 21500 0.01 878 0.04 :elixir_parser.yeccpars2_27/7 12500 0.01 884 0.07 List.to_string/1 12001 0.01 887 0.07 EEx.Compiler.trim_and_tokenize/7 6000 0.01 888 0.15 anonymous fn/2 in :elixir_tokenizer.tokenize/4 22000 0.01 889 0.04 :elixir.string_to_tokens/5 10000 0.01 892 0.09 :elixir_parser.yecctoken_end_location/1 18500 0.01 894 0.05 :elixir_parser.meta_from_token/1 24000 0.01 898 0.04 EEx.Compiler.token_key/2 6000 0.01 905 0.15 anonymous fn/1 in TailwindFormatter.sort_variant_classes/1 24000 0.01 912 0.04 Enum.find/3 25500 0.01 912 0.04 :maps.try_next/2 24000 0.01 913 0.04 Enum.find/2 25500 0.01 916 0.04 :lists.keymember/3 21500 0.01 927 0.04 Code.Normalizer.allow_keyword?/2 12500 0.01 930 0.07 anonymous fn/4 in Enum.map/2 24000 0.01 942 0.04 anonymous fn/6 in Code.Formatter.binary_op_to_algebra/8 3500 0.01 946 0.27 List.do_pop_at/4 13500 0.01 950 0.07 Code.Formatter.line/1 12500 0.01 980 0.08 String.to_charlist/1 10001 0.01 993 0.10 Code.Formatter.split_last/1 13000 0.01 998 0.08 Code.Normalizer.normalize_args/2 17000 0.01 1002 0.06 :lists.foldl_1/3 22000 0.01 1009 0.05 :elixir_parser.yeccpars2_38/7 25000 0.01 1016 0.04 Enum.any?/2 25500 0.01 1031 0.04 TailwindFormatter.PhoenixLiveViewHTMLEngine.void?/1 25500 0.01 1047 0.04 :erlang.integer_to_binary/1 17000 0.01 1048 0.06 Code.Formatter.remote_to_algebra/3 2500 0.01 1048 0.42 :lists.rkeymergel/4 11000 0.01 1049 0.10 Code.Identifier.binary_op/1 27000 0.01 1050 0.04 :elixir_parser.yeccgoto_access_expr/7 25000 0.01 1077 0.04 Code.Normalizer.normalize_kw_blocks/4 4500 0.01 1081 0.24 String.Break.trim_trailing/2 12000 0.01 1091 0.09 Code.Formatter.meta?/2 13500 0.01 1096 0.08 :elixir_tokenizer.maybe_warn_for_ambiguous_bang_before_equals/6 30500 0.01 1105 0.04 Code.quoted_to_algebra/2 10000 0.01 1112 0.11 TailwindFormatter.weave_in_code/2 6500 0.01 1129 0.17 Code.Formatter.call_args_to_algebra/6 6500 0.01 1146 0.18 Enum.split/2 13000 0.01 1149 0.09 :elixir_parser.build_identifier/2 16500 0.01 1170 0.07 TailwindFormatter.PhoenixLiveViewTokenizer.put_attr/3 32500 0.01 1192 0.04 Code.Formatter.unary_op_to_algebra/5 4500 0.01 1210 0.27 :elixir_tokenizer.check_call_identifier/5 30500 0.01 1211 0.04 :elixir.string_to_quoted!/5 10000 0.01 1236 0.12 :unicode.characters_to_list/1 10001 0.01 1244 0.12 anonymous fn/3 in Code.Formatter.quoted_to_algebra/3 5500 0.01 1249 0.23 :lists.foldl/3 16000 0.01 1257 0.08 Enum.split_while/2 31000 0.01 1258 0.04 Code.Formatter.local_without_parens?/3 19000 0.01 1259 0.07 anonymous fn/1 in TailwindFormatter.collect_classes/2 24500 0.01 1265 0.05 :elixir_tokenizer.track_ascii/2 36000 0.01 1307 0.04 :elixir_tokenizer.maybe_keyword/1 35000 0.01 1315 0.04 TailwindFormatter.PhoenixLiveViewTokenizer.handle_maybe_attr_value/5 32500 0.01 1328 0.04 Keyword.has_key?/2 17000 0.01 1331 0.08 TailwindFormatter.PhoenixLiveViewTokenizer.put_attr_value/2 32500 0.01 1336 0.04 Inspect.Algebra.nest/3 32500 0.01 1337 0.04 TailwindFormatter.PhoenixLiveViewTokenizer.put_attr/4 32500 0.01 1346 0.04 Code.Formatter.closing_line/1 12500 0.01 1347 0.11 String.Chars.Integer.to_string/1 17000 0.01 1348 0.08 String.split/1 30000 0.01 1353 0.05 Code.Formatter.block_args_to_algebra/4 18500 0.01 1368 0.07 List.first/2 38500 0.01 1370 0.04 :elixir_parser.yeccpars0/5 18500 0.01 1375 0.07 :elixir_parser.yecctoken_location/1 18500 0.01 1377 0.07 TailwindFormatter.HEExTokenizer.do_tokenize/3 12002 0.01 1381 0.12 String.Chars.Atom.to_string/1 39250 0.01 1387 0.04 :erl_anno.anno_info/2 37000 0.01 1405 0.04 Map.new_from_enum/2 10000 0.01 1420 0.14 Code.Normalizer.normalize_bitstring/3 6500 0.01 1424 0.22 :elixir_tokenizer.unescape_tokens/4 18500 0.01 1427 0.08 :elixir_parser.build_bin_string/2 17500 0.01 1428 0.08 :elixir_tokenizer.handle_space_sensitive_tokens/5 36500 0.01 1429 0.04 :persistent_term.get/2 27500 0.01 1435 0.05 TailwindFormatter.handle_interpolation/1 6500 0.01 1437 0.22 :elixir_interpolation.unescape_tokens/1 18500 0.01 1446 0.08 anonymous fn/1 in TailwindFormatter.sort_variant_classes/1 24000 0.01 1451 0.06 :elixir_tokenizer.check_terminator/3 16500 0.01 1461 0.09 anonymous fn/1 in TailwindFormatter.group_by_first_variant/1 38500 0.01 1469 0.04 :lists.keysplit_1/8 32750 0.01 1474 0.05 Enum.split_reverse_list/3 26000 0.01 1505 0.06 List.first/1 38500 0.01 1511 0.04 List.Chars.to_charlist/1 10000 0.01 1516 0.15 String.ends_with?/2 23500 0.01 1538 0.07 Code.Formatter.surround/3 10000 0.01 1538 0.15 TailwindFormatter.PhoenixLiveViewTokenizer.handle_attr_value_begin/5 32500 0.01 1542 0.05 anonymous fn/5 in Code.Formatter.args_to_algebra_with_comments/7 14500 0.01 1618 0.11 :elixir_tokenizer.previous_was_dot/1 41000 0.01 1623 0.04 Code.Formatter.interpolation_to_algebra/2 8500 0.01 1632 0.19 :maps.iterator/2 46500 0.01 1686 0.04 Code.Formatter.binary_op_to_algebra/8 3500 0.01 1700 0.49 anonymous fn/3 in Enum.map/2 24000 0.01 1707 0.07 :erlang.atom_to_list/1 28000 0.01 1710 0.06 TailwindFormatter.PhoenixLiveViewTokenizer.handle_attr_value_as_expr/5 15500 0.01 1717 0.11 anonymous fn/2 in Code.Formatter.quoted_to_algebra_with_comments/6 31000 0.01 1755 0.06 :maps.iterator/1 46500 0.01 1781 0.04 Enum.flat_map/2 46500 0.01 1783 0.04 anonymous fn/1 in TailwindFormatter.sort_variant_classes/1 24000 0.01 1802 0.08 :erlang.put/2 40000 0.01 1803 0.05 List.last/2 50000 0.01 1814 0.04 :erlang.erase/1 40000 0.01 1825 0.05 Enum.intersperse_non_empty_list/2 28500 0.01 1840 0.06 :elixir_parser.string_part/1 20750 0.01 1862 0.09 :elixir_utils.characters_to_binary/1 24250 0.01 1892 0.08 :elixir_interpolation.build_string/2 27000 0.01 1899 0.07 Code.Formatter.local_to_algebra/5 6500 0.01 2036 0.31 Enum.find_list/3 31000 0.01 2047 0.07 :elixir_interpolation.finish_extraction/6 18500 0.01 2052 0.11 String.Chars.impl_for/1 56250 0.01 2061 0.04 :elixir_tokenizer.keyword_or_unsafe_to_atom/5 41000 0.01 2062 0.05 :elixir_config.identifier_tokenizer/0 27000 0.01 2065 0.08 :elixir_parser.yeccpars2_21/7 18500 0.01 2113 0.11 :elixir_parser.yeccpars2_52/7 17500 0.01 2123 0.12 Inspect.Algebra.break/1 58000 0.01 2191 0.04 anonymous fn/2 in Code.Formatter.quoted_to_algebra_with_comments/6 31000 0.01 2230 0.07 :elixir_tokenizer.handle_terminator/6 22500 0.01 2261 0.10 Code.Normalizer.maybe_escape_literal/2 17000 0.01 2266 0.13 Code.Formatter.force_args?/2 31000 0.01 2280 0.07 :elixir_interpolation.unescape_token/2 32750 0.01 2286 0.07 Enum.split_while_list/3 31000 0.01 2294 0.07 Code.Normalizer.normalize/2 10000 0.01 2333 0.23 Code.Formatter.to_algebra/2 10000 0.01 2359 0.24 String.Break.split/1 30000 0.01 2464 0.08 Code.string_to_quoted!/2 10000 0.01 2469 0.25 :elixir_interpolation.unescape_chars/2 24250 0.01 2487 0.10 Macro.operator?/2 32000 0.01 2492 0.08 :elixir_tokenizer.tokenize/4 24500 0.01 2510 0.10 :elixir_parser.yeccgoto_matched_expr/7 42000 0.01 2513 0.06 Code.Normalizer.normalize_literal/3 16000 0.01 2532 0.16 anonymous fn/2 in TailwindFormatter.handle_interpolation/1 20750 0.01 2584 0.12 :elixir_parser."-string_parts/1-lc$^0/1-0-"/1 27250 0.02 2613 0.10 List.last/1 68000 0.02 2663 0.04 anonymous fn/1 in Code.Formatter.interpolated?/1 67500 0.02 2668 0.04 Map.update!/3 31000 0.02 2672 0.09 Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3 27250 0.02 2674 0.10 Enum.entry_to_string/1 70500 0.02 2691 0.04 anonymous fn/2 in TailwindFormatter.weave_in_code/2 28500 0.02 2709 0.10 Code.Normalizer.do_normalize/2 49500 0.02 2755 0.06 Map.get_and_update!/3 31000 0.02 2777 0.09 anonymous fn/1 in Code.Normalizer.binary_interpolated?/1 67500 0.02 2778 0.04 :erts_internal.map_next/3 46500 0.02 2792 0.06 :elixir_parser.meta_from_location/1 72000 0.02 2799 0.04 :unicode.characters_to_binary/1 36251 0.02 2811 0.08 :elixir.tokens_to_quoted/3 10000 0.02 2820 0.28 TailwindFormatter.PhoenixLiveViewHTMLEngine.classify_type/1 50000 0.02 2824 0.06 :unicode_util.gc_extend/3 79500 0.02 2917 0.04 Code.Formatter.args_to_algebra_with_comments/7 12500 0.02 2923 0.23 anonymous fn/3 in Code.Normalizer.normalize_interpolation_parts/3 67500 0.02 2946 0.04 Inspect.Algebra.group/1 77000 0.02 2979 0.04 Inspect.Algebra.group/2 81500 0.02 2998 0.04 TailwindFormatter.PhoenixLiveViewTokenizer.handle_tag_close/5 23000 0.02 3028 0.13 :lists.member/2 71000 0.02 3076 0.04 :unicode_util.cp/1 79500 0.02 3101 0.04 Code.Normalizer.patch_meta_line/2 40500 0.02 3119 0.08 Enum.reduce/2 82500 0.02 3149 0.04 Enum."-reduce/2-lists^foldl/2-1-"/3 84500 0.02 3174 0.04 :elixir_tokenizer.handle_strings/6 18500 0.02 3209 0.17 String.starts_with?/2 35750 0.02 3245 0.09 String.replace/4 89000 0.02 3260 0.04 TailwindFormatter.PhoenixLiveViewTokenizer.handle_tag_open/5 27000 0.02 3273 0.12 anonymous fn/2 in TailwindFormatter.handle_interpolation/1 20750 0.02 3309 0.16 :elixir_parser.handle_literal/3 21500 0.02 3333 0.16 Inspect.Algebra.glue/3 31000 0.02 3343 0.11 TailwindFormatter.Order.classes/0 92000 0.02 3375 0.04 String.length/1 92000 0.02 3415 0.04 Enum.sort_by/2 93000 0.02 3448 0.04 anonymous fn/3 in Code.Formatter.block_args_to_algebra/4 18500 0.02 3452 0.19 TailwindFormatter.group_by_first_variant/1 46500 0.02 3461 0.07 :erlang.atom_to_binary/2 45000 0.02 3487 0.08 TailwindFormatter.PhoenixLiveViewTokenizer.normalize_tag/5 27000 0.02 3488 0.13 String.replace/3 89000 0.02 3496 0.04 Code.Formatter.each_quoted_to_algebra_without_comments/4 60000 0.02 3516 0.06 TailwindFormatter.PhoenixLiveViewTokenizer.text_to_acc/5 56001 0.02 3521 0.06 TailwindFormatter.PhoenixLiveViewTokenizer.handle_attribute/5 32500 0.02 3535 0.11 TailwindFormatter.sort_classes/2 19000 0.02 3595 0.19 :elixir_tokenizer.unsafe_to_atom/4 36000 0.02 3605 0.10 TailwindFormatter.sort_variant_chains/1 23500 0.02 3608 0.15 Inspect.Algebra.color/3 48000 0.02 3653 0.08 List.foldl/3 100500 0.02 3654 0.04 TailwindFormatter.PhoenixLiveViewTokenizer.done_tag_name/3 50000 0.02 3677 0.07 :elixir.handle_parsing_opts/2 10000 0.02 3694 0.37 anonymous fn/1 in TailwindFormatter.sort_variant_chains/1 100500 0.02 3698 0.04 anonymous fn/1 in TailwindFormatter.sort_variant_chains/1 100500 0.02 3750 0.04 :elixir_tokenizer.strip_horizontal_space/2 101500 0.02 3771 0.04 anonymous fn/1 in TailwindFormatter.sort_variant_chains/1 100500 0.02 3798 0.04 String.Tokenizer.validate/2 52000 0.02 3978 0.08 String.Tokenizer.tokenize/1 52000 0.02 4004 0.08 Enum.reduce/3 107003 0.02 4035 0.04 :erlang.atom_to_binary/1 45000 0.02 4062 0.09 Macro.inner_classify/1 11000 0.02 4073 0.37 String.Chars.impl_for!/1 56250 0.02 4110 0.07 :elixir_interpolation."-unescape_tokens/1-lc$^0/1-0-"/1 51250 0.02 4143 0.08 :elixir_parser.yeccpars1/7 68000 0.02 4240 0.06 Code.Formatter.state/2 10000 0.02 4246 0.42 anonymous fn/1 in Enum.sort_by/3 124500 0.03 4462 0.04 Enum.group_by/3 46500 0.03 4491 0.10 :erlang.error/2 37000 0.03 4514 0.12 :maps.fold_1/4 70500 0.03 4718 0.07 Code.Formatter.merge_algebra_with_comments/2 64000 0.03 4785 0.07 Enum."-group_by/3-lists^foldl/2-0-"/3 85000 0.03 4885 0.06 :elixir_parser.yeccpars2/7 86500 0.03 4958 0.06 Keyword.get/2 136500 0.03 5001 0.04 anonymous fn/2 in Enum.sort_by/3 139000 0.03 5082 0.04 TailwindFormatter.variant?/1 139000 0.03 5099 0.04 TailwindFormatter.collect_classes/2 92999 0.03 5101 0.05 :maps.fold/3 46500 0.03 5192 0.11 Enum.flat_map_list/2 70500 0.03 5274 0.07 anonymous fn/2 in TailwindFormatter.sort_variant_classes/1 38500 0.03 5298 0.14 :maps.next/1 46500 0.03 5356 0.12 String.Chars.to_string/1 56250 0.03 5490 0.10 TailwindFormatter.placeholder?/1 149750 0.03 5505 0.04 anonymous fn/4 in Enum.group_by/3 38500 0.03 5615 0.15 TailwindFormatter.Order.variants/0 163000 0.03 5882 0.04 :lists.do_flatten/2 91000 0.03 5965 0.07 Code.Identifier.escape_map/1 169500 0.03 6036 0.04 :unicode_util.gc_1/1 79500 0.03 6077 0.08 :binary.split/2 38500 0.04 6116 0.16 Code.Identifier.escape_char/1 169500 0.04 6223 0.04 Code.Formatter.call_args_to_algebra_no_blocks/6 6500 0.04 6245 0.96 :elixir_tokenizer.tokenize_identifier/5 41000 0.04 6315 0.15 TailwindFormatter.PhoenixLiveViewTokenizer.handle_maybe_tag_open_end/5 130000 0.04 6358 0.05 String.split/2 179000 0.04 6549 0.04 TailwindFormatter.sort_variant_classes/1 46500 0.04 6626 0.14 Inspect.Algebra.string/1 92000 0.04 6870 0.07 Enum.join/2 147500 0.04 7404 0.05 List.keysort/3 193500 0.04 7493 0.04 Enum.split_with/2 46500 0.04 7667 0.16 Code.Normalizer.normalize_call/2 17000 0.04 7697 0.45 TailwindFormatter.PhoenixLiveViewTokenizer.handle_tag_name/3 190500 0.05 7904 0.04 :lists.keysort/2 193500 0.05 7938 0.04 Code.Formatter.interpolation_to_algebra/5 74000 0.05 8001 0.11 EEx.Compiler.expr/5 192000 0.05 8194 0.04 TailwindFormatter.PhoenixLiveViewTokenizer.handle_attr_name/3 172000 0.05 8253 0.05 Inspect.Algebra.concat/2 212500 0.05 8271 0.04 :unicode_util.gc/1 171500 0.05 8332 0.05 :erlang.++/2 175500 0.05 8384 0.05 Code.Formatter.quoted_to_algebra_with_comments/6 31000 0.05 8446 0.27 String.Tokenizer.continue/6 224000 0.05 8574 0.04 Access.get/2 239505 0.05 8923 0.04 anonymous fn/2 in Enum.sort_by/3 124500 0.05 9156 0.07 Enum.join_non_empty_list/3 239500 0.05 9165 0.04 :erlang.list_to_atom/1 61500 0.06 9685 0.16 Code.Formatter.quoted_to_algebra/3 51000 0.06 9973 0.20 anonymous fn/3 in Enum.sort_by/3 139000 0.06 10260 0.07 TailwindFormatter.sort_expr/1 167000 0.06 10509 0.06 TailwindFormatter.class_position/1 100500 0.06 10539 0.10 anonymous fn/3 in Enum.split_with/2 139000 0.06 10669 0.08 EEx.Compiler.maybe_append_space/1 57500 0.06 11225 0.20 TailwindFormatter.variant_position/1 163000 0.07 11866 0.07 Enum."-split_with/2-lists^foldl/2-1-"/3 185500 0.07 11979 0.06 List."-foldl/3-lists^foldl/2-0-"/3 239500 0.08 13443 0.06 TailwindFormatter.sort/1 71000 0.08 14435 0.20 Code.Formatter.escape_string/2 70000 0.08 14774 0.21 TailwindFormatter.PhoenixLiveViewTokenizer.handle_text/6 369001 0.10 16825 0.05 Access.get/3 239505 0.10 17088 0.07 String.skip_length/2 478000 0.10 17124 0.04 Enum.join_list/2 124000 0.10 17710 0.14 :elixir_interpolation.unescape_chars/3 508500 0.12 20427 0.04 :elixir_interpolation.extract/8 511250 0.12 20594 0.04 Code.Identifier.escape/5 183500 0.12 21702 0.12 String.length/2 229000 0.13 22073 0.10 String.contains?/2 288750 0.13 22480 0.08 :lists.reverse/1 450750 0.14 23590 0.05 Enum.map/2 562000 0.14 24118 0.04 Enum.sort_by/3 193500 0.14 24364 0.13 Enum."-reduce/3-lists^foldl/2-0-"/3 390754 0.15 25248 0.06 :elixir_tokenizer.tokenize/5 161500 0.17 30138 0.19 TailwindFormatter.PhoenixLiveViewTokenizer.handle_attr_value_quote/7 783500 0.18 30786 0.04 TailwindFormatter.PhoenixLiveViewTokenizer.handle_interpolation/5 796500 0.18 31814 0.04 Map.get/3 255000 0.18 32160 0.13 String.split/3 217500 0.19 32353 0.15 Inspect.Algebra.format/3 587000 0.19 32966 0.06 :lists.reverse/2 304504 0.20 34937 0.11 anonymous fn/3 in Code.Formatter.local_without_parens?/3 1045000 0.22 37561 0.04 TailwindFormatter.PhoenixLiveViewTokenizer.buffer_to_string/1 152001 0.22 38447 0.25 :lists.keyfind/3 1106507 0.30 52772 0.05 :unicode.characters_to_binary/2 36251 0.31 53289 1.47 Keyword.get/3 818002 0.34 59739 0.07 :binary.match/2 289250 0.38 66917 0.23 :unicode.characters_to_list/2 10001 0.39 67416 6.74 Enum.predicate_list/3 1221500 0.49 85773 0.07 Enum.reverse/1 363504 0.60 103610 0.29 Enum."-map/2-lists^map/1-1-"/2 1452500 0.70 121412 0.08 EEx.Compiler.tokenize/6 2441501 0.90 155645 0.06 :binary.split/3 209000 1.04 181072 0.87 String.replace_guarded/4 89000 1.10 191419 2.15 String.do_replace/4 9588500 5.03 874449 0.09 :erlang.iolist_to_binary/1 417001 10.63 1847744 4.43 :binary.matches/2 88500 69.09 12011135 135.72 ```

The most expensive function comes from all of the String.replace calls.

I think a strategy to explore for optimizations is to do all of the replacements "in-place" instead of traversing the entire contents each time

aptinio commented 1 year ago

Great work @100phlecs! I admit, I went with intuition and skipped measurements :sweat_smile:

I forgot to mention in #37 that it behaves a little differently, by sorting all class attributes, instead of only the first one. I figured that during editing, one might want to compare different sets of class attributes to each other, put them on the same element, and want to have all of them sorted.

100phlecs commented 1 year ago

Oh okay, if that's a usecase you're running into or others may use then may as well add it 🙂

aptinio commented 1 year ago

Thank you! :heart: