pejrich
I have quite a few files in my project that have many function heads(100s to 1000s). I don’t think these can easily be replaced with another way of doing it. For example, transliterating Japanese into Latin characters. Right now I have compile time code read from this Unihan_Readings.txt file[Warning, 5mb text file], and generate functions that match the Japanese character at the beginning of the string. This can’t be replaced by String.split, because some matches are multi-character, but the variation in byte length is even wider, so binary pattern matching is the most obvious solution.
Anyway, compiling a file like this, is currently taking a LONG time, and it seems to have gotten worse under OTP 26, like a lot worse. It used to take maybe 30-40 seconds, now it takes 20-30 minutes(M1 MBP running Ventura 13.4. OTP 26.0, Elixir 1.15.3-otp-26). Is there any way to optimize this ahead of time for quicker compilation?
I’m currently running a compile with ERL_COMPILER_OPTIONS=time mix compile --force --profile time, so far(45 minutes), here’s some of the output:
beam_ssa_codegen : 0.715 s 114644.0 kB
beam_validator_strong : 0.195 s 114644.0 kB
beam_a : 0.018 s 115052.9 kB
beam_block : 0.025 s 120606.8 kB
beam_jump : 0.105 s 100114.5 kB
beam_clean : 0.002 s 100114.5 kB
beam_trim : 0.000 s 100114.5 kB
beam_flatten : 0.000 s 99683.7 kB
beam_z : 0.000 s 99668.4 kB
beam_validator_weak : 0.099 s 99668.4 kB
beam_asm : 0.191 s 95366.4 kB
beam_ssa_opt : 1876.602 s 277640.0 kB
%% Sub passes of beam_ssa_opt from slowest to fastest:
ssa_opt_alias : 1866.038 s 99 %
ssa_opt_live : 2.007 s 0 %
ssa_opt_type_start : 1.973 s 0 %
ssa_opt_dead : 1.113 s 0 %
ssa_opt_type_continue : 0.958 s 0 %
ssa_opt_bsm_shortcut : 0.621 s 0 %
ssa_opt_merge_blocks : 0.447 s 0 %
ssa_opt_cse : 0.374 s 0 %
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #ai
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #elixirconf-eu
- #metaprogramming
- #hex










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
dimitarvp
I’ve only seen such huge slowdown when I was trying to compile for ARM on my x64 Mac. Are you sure you are using fully ARM-native terminal,
homebrewand everything?pejrich
It looks like everything is running on arm.
And ActivityMonitor shows
beam.smprunning asApple, which I believe is arm64D4no0
It would be nice if you showed at least some example on what your functions look like, from what I understand you are generating code based on this file?
pejrich
Here’s a stripped down version of what i’m doing. This example doesn’t use the Unihan file because that part has a bit of preprocessing, but it’s ultimately similar. Here hepburn.tsv and ja_punct.tsv, are files of two columns, that look like this:
Hepburn is 604 lines, ja_punct is 91 lines.
D4no0
This might be a good place to start. From what I remember
Enum.sort_by/3is not one of the most performant of the functions. I guess a place to start debugging might be by using timer, and I would start from this sort function as is one of the possible bottleneck places.LostKobrakai
Consider something like nimble_csv to parse the tsv files. You’re iterating a bit more often than needed through the data.
pejrich
If I run those module attributes with an
|> IO.inspect()at the end, they all finish within a second, which leads me to believe the issue is not so much with the parsing of the TSV or the sorting. I just logged a count, and it’s a total of 16,089 items that would be used to generate the functions dynamically. From what I can tell, the actual compile time code and the elixir side run in a matter of seconds, I think it’s the erlang compilation that’s taking 30minutes.pejrich
It’s certainly likely that this can be optimized, but from what I can tell, it’s not the culprit. I’m not sure if this is an accurate way to test how long those module attributes take to run, but if I do something like this:
It shows that all my module attributes run in <200 milliseconds.
LostKobrakai
That’s useful information. In this case it’s really likely that this is due to the compilation of functions, not the compile time logic. Iirc from older discussions anything beyond like the 1000 of functions/heads would be considered problematic, so 16k is indeed large. Iirc cldr libraries did also run into this every now an then. That might be something to search for.
pejrich
Yeah, it’s probably certainly beyond what they’re developing it for, but it is a fairly clean way to code it, so that’s what drew me to it. Since there’s so much variation in the byte size of what I’m matching, and ultimately I can’t ask all the worlds languages to change, so there’s going to be the number of items in the search space that the language dictates, I could recode it to do something like progressively pulling a byte off the front of the string, and accumulate that until it matches a key in a Map, which would hold the 16k items, but that seems a bit convoluted in comparison to the current solution.
But with all that said, my current solution works just fine, and in OTP 25 it compiled in a reasonable 20-30 seconds rather than 20-30 minutes, so maybe I’ll just go back down to OTP 25 for now.