blubparadox
Hi all. If you’ve looked on Twitter or YouTube you’ve seen the 1 billion row challenge, usually done in Java. I’ve written an Elixir version, feel free to have a look and see if you can improve on it.
https://github.com/rrcook/brc
Trending in RFCs
There was some time when I started thinking about giving a boost to Lambdapad, the initiative from @garretsmith in Erlang that I loved wa...
New
Hey everyone — I’m putting together a practical, code-first book on building production-ready business applications with Phoenix LiveView...
New
You set up environments, each with its own tools, its own data and its own limits, and programs get evaluated in them. The same program r...
New
Other Trending Topics
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Hi everyone!
The first release candidate for the Expert language server project is now available!
We’ve published a press release detai...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
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)
outlog
from a quick look, think you could benefit from using nimble_parsec to parse the file/stream - GitHub - dashbitco/nimble_parsec: A simple and fast library for text-based parser combinators · GitHub - then I saw Agent usage - which I believe is generally not advised - probably more speed in using ets etc. - but this could be one of the exceptions..
all of this from a very quick look, and not fully understanding the problem, so I could be totally wrong.
blubparadox
Hi outlog - the original rules for the Java challenge, and the spirit to which I’m trying to adhere, is to just use what is in the standard language and not pull in any external libraries.
Are you saying that ets in one process would beat using Agents to farm out the work to multiple CPUs? Or that a GenServer-based approach would be Agents?
stevensonmt
There’s probably some small gains to be had by changing the
worker_poolto a map rather than list so that you can avoidEnum.athereIt has to iterate over the worker_pool list each time to find the agent id. Since the worker pool is small each individual call is going to be very fast, but you are calling it 100_000 times. On my machine the average of 100 runs of 100_000 calls to
Enum.aton a list of 8 items versus callingMap.geton a map of 8 items keyed by index was a difference of 17631ms. Whether that is significant is for you to decide. Probably theAgentissue is more impactful.My rough little benchmark:
blubparadox
I’m relatively new to Elixir & BEAM but I don’t understand how using ets over Agents will facilitate using multiple CPUs to farm out processing of the lines.
stevensonmt
That post probably offers better insight than I can.
There’s also this blog post which offers the following explanation:
Finally, the approach that immediately came to my mind was not using a cache at all but using
Task.asyn_streamas described in this blog posthttps://github.com/exercism/blog/blob/main/posts%2Fconcurrency-parallelism-in-elixir.md
blubparadox
I shot past Map and went to ets, which I’ve read has O(1) lookup. It didn’t make a noticeable difference.
stevensonmt
I think you may have changed some other parts of the code as well, looking at the github repo. So you might have minimized the impact the change could have. I just re-ran the benchmark on my machine, using an ETS implementation and got similar results as I posted above:
Also be aware that while ETS lookups are fast (O(1) as you say) and process communication is very efficient in the BEAM, making process calls can be slower than accessing a data structure in the same process. ETS will generally be a better choice for very large collections and for structures needing to be accessed from multiple concurrent processes. In this case your worker_pool is never going to be that large. Whether sharing a single ETS across multiple processes is more efficient than creating the worker_pool map for each process I can’t say but probably it is given how many processes you could end up spawning to access it. This thread has a good discussion of the tradeoffs between maps and ETS tables.
Rather than focusing on this tiny
worker_pooldata structure, I think you should look at processing all the lines directly to an ETS table rather than creating a bunch of maps stored in Agents that you have to merge later. Create Tasks that process lines to the ETS table then at the end pull the table data for your final output. If you set up your ETS table as an ordered_set you can probably avoid the step where you’re having to sort N items where N is the number of cities in the data set. You might event look at DETS to avoid running out of memory given the large data set.tj0
Another implementation outside of the standard library if you’re interested.
betoparcus
Thanks for the shoutout, there are several implementations in this discussion, including one simply using Flow+ets as well.
It automatically does what you suggested above
stevensonmt
I think @blubparadox is trying to restrict their code to only standard lib modules, which eliminates
Flow. I like that Flow implementation though.