Ameba v0.11.0 has been released. Here we will go through the main features and improvements which are included to this release. Also, will do benchmarking comparing parallel linting using Crystal’s experimental parallelism and will explain how to use Ameba together with GitHub actions.
New Rules
Crystal has several handy methods to iterate over collection together with index/object:
- Enumerable#each_with_index
- Enumerable#each_with_object
- Iterable#each_with_index
- Iterable#each_with_object
They are usually used in places where an extra block argument (index or object) is needed:
1 | collection.each.with_index do |e, index| |
However, sometimes after a couple of refactoring rounds, people realize they don’t need that additional argument anymore and forget to remove that extra call to with_index
(or with_object
). Examples:
1 | collection.each.with_index do |e| |
Now, all cases above are reported by Ameba. The suggested way to change it will be the following:
1 | collection.each do |e| |
If your source code is not ready for these enforcements, they can be disabled in .ameba.yml
via:
1 | Lint/RedundantWithIndex: |
Parallel linting
Crystal started to support parallism as an experimental feature starting from 0.31.0
. The main intention here is speed, which is achieved by doing several things in parallel. Ameba is a small set of rules and enforcements and in most cases, it takes a couple of seconds to lint an average shard. However, we still find it useful to parallize the linting, especially on a large amount of sources.
We found that the easiest way to run linting in parallel is to spawn each source into it’s own channel. And since issues are added to the sources, we don’t have to care about thread safely, because a full set of rules will be running sequentially on each source in it’s own thread. So the only thing which is needed is to wait the hole inspection on all sources at the end and gather results.
At a high level, it looks similar to this:
1 | channels = sources.map { Channel(Nil).new } |
In reality, it is a bit more complex and it was simplified just to explain the concept. Let’s do some benchmarking now.
At first, we need to build Ameba using the preview_mt
flag and install it manually:
1 | $ crystal build src/cli.cr -Dpreview_mt -o bin/ameba |
And then we can try running it on Crystal repo (1449 files for the moment) using different amount of crystal workers:
1 | $ time CRYSTAL_WORKERS=1 ameba --silent # 27.78s user 0.34s system 99% cpu 28.116 total |
If you look at the total
part, you will find that the max time is 28.116
seconds and the min one is 10.900
seconds. So we were able to run it almost 3 times faster on 8 workers.
However, the results are not linear to the amount of workers. And that is expected, because our sources (or more accurate, lines of code) are not divided evenly and some workers have to inspect bigger sources and other workers will have to wait until they finish.
Of course, someone can say that we can pre-calculate the LoCs and divide the work more evenly. And it would be true. But that would complicate our implementation a lot. So here we decided to make it as simple as possible and keep the room opened for the future improvements.
At the end, we must say that this feature is fully functional and reliable on Ameba’s side. It was well tested using different formatters, so the end user is free to try it to inspect his crystal code in parallel. We are looking for the best results, keep us posted!
GitHub Action
Ameba GitHub action has been released and the first version has been published to the GitHub marketplace.
The easiest way to use it is to follow installation intructions:
1 | # Copy and paste the following snippet into your .yml file. |
And here is an example of the workflow with Ameba and Crystal specs:
1 | # Create .github/workflows/crystal.yml in your repository |
Once this is added to GitHub action workflow, Ameba will start reporting annotations in pull requests:
Keep in mind, that is very first release for this GitHub action and it misses a couple of required configuration options. However, it still uses .ameba.yml
config in the repository root and properly configures rules before running the inspection. Hope you would enjoy it!
More
This release also includes a couple of bug fixes and small improvements. Checkout the release notes for more details.
Comments