FastRSS

Parse RSS feeds very quickly

Hex.pmHex.pmHex.pmHexDocs.pm

Intro | Compatibility | Installation | Usage | Benchmarks | Deploying | License


Intro

Parse RSS feeds very quickly

Speed

Currently this is already much faster than most of the pure elixir/erlang packages out there. In benchmarks there are speed improvements anywhere between 6.12x - 50.09x over the next fastest package (feeder_ex) that was tested.

Compared to the slowest elixir options tested (feed_raptor, elixir_feed_parser), FastRSS was sometimes 259.91x faster and used 5,412,308.17x less memory (0.00156 MB vs 8423.70 MB).

See full benchmarks below:

Compatibility

FastRSS requires a minimum combination of Elixir 1.6.0 and Erlang/OTP 20.0, and is tested with a maximum combination of Elixir 1.10.1 and Erlang/OTP 22.0.

Installation

This package is available on hex.

It can be installed by adding fast_rss to your list of dependencies in mix.exs:

def deps do
  [
    {:fast_rss, "~> 0.3.0"}
  ]
end

You also need the rust compiler installed: https://www.rust-lang.org/tools/install

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Usage

There is only one function it takes an RSS string and outputs an {:ok, map()} with string keys.

iex(1)>  {:ok, map_of_rss} = FastRSS.parse("...rss_feed_string...")
iex(2)> Map.keys(map_of_rss)
["categories", "cloud", "copyright", "description", "docs", "dublin_core_ext",
 "extensions", "generator", "image", "items", "itunes_ext", "language",
 "last_build_date", "link", "managing_editor", "namespaces", "pub_date",
 "rating", "skip_days", "skip_hours", "syndication_ext", "text_input", "title",
 "ttl", "webmaster"]

The docs can be found at https://hexdocs.pm/fast_rss.

Supported Feeds

Reading from the following RSS versions is supported:

Benchmark

HTML: https://avencera.github.io/fast_rss/

Benchmark run from 2020-02-22 05:23:47.524699Z UTC

System

Benchmark suite executing on the following system:

Operating SystemmacOS
CPU InformationIntel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Number of Available Cores16
Available Memory32 GB
Elixir Version1.10.1
Erlang Version22.2.6

Configuration

Benchmark suite executing with the following configuration:

:time30 s
:parallel1
:warmup5 s

Statistics

Input: anxiety

Run Time

NameIPSAverageDevitationMedian99th %
fast_rss188.575.30 ms±8.26%5.45 ms6.43 ms
feeder_ex3.70269.92 ms±5.34%268.12 ms316.12 ms
feed_raptor2.99334.01 ms±2.44%331.03 ms371.28 ms
elixir_feed_parser1.94515.72 ms±1.94%516.10 ms536.05 ms

Comparison

NameIPSSlower
fast_rss188.57 
feeder_ex3.7050.9x
feed_raptor2.9962.99x
elixir_feed_parser1.9497.25x

Memory Usage

NameMemoryFactor
fast_rss0.00156 MB 
feeder_ex17.21 MB11004.73x
feed_raptor268.53 MB171693.91x
elixir_feed_parser313.30 MB200316.09x

Input: ben

Run Time

NameIPSAverageDevitationMedian99th %
fast_rss83.9511.91 ms±10.29%12.23 ms16.17 ms
feeder_ex13.3375.04 ms±4.38%74.21 ms89.72 ms
elixir_feed_parser3.52284.18 ms±3.89%283.83 ms324.08 ms
feed_raptor0.482078.76 ms±0.52%2076.27 ms2097.44 ms

Comparison

NameIPSSlower
fast_rss83.95 
feeder_ex13.336.3x
elixir_feed_parser3.5223.86x
feed_raptor0.48174.51x

Memory Usage

NameMemoryFactor
fast_rss0.00155 MB 
feeder_ex27.86 MB17990.96x
elixir_feed_parser163.88 MB105811.88x
feed_raptor1577.41 MB1018492.36x

Input: daily

Run Time

NameIPSAverageDevitationMedian99th %
fast_rss32.980.0303 s±7.62%0.0313 s0.0339 s
feeder_ex4.940.20 s±4.61%0.199 s0.24 s
elixir_feed_parser0.641.57 s±1.50%1.57 s1.63 s
feed_raptor0.1277.88 s±0.23%7.88 s7.90 s

Comparison

NameIPSSlower
fast_rss32.98 
feeder_ex4.946.68x
elixir_feed_parser0.6451.86x
feed_raptor0.127259.91x

Memory Usage

NameMemoryFactor
fast_rss0.00153 MB 
feeder_ex109.73 MB71555.78x
elixir_feed_parser880.51 MB574178.95x
feed_raptor6386.12 MB4164382.64x

Input: dave

Run Time

NameIPSAverageDevitationMedian99th %
fast_rss407.082.46 ms±9.83%2.41 ms3.16 ms
feeder_ex56.5217.69 ms±6.14%17.37 ms22.51 ms
elixir_feed_parser8.90112.31 ms±4.12%111.93 ms127.60 ms
feed_raptor1.59628.45 ms±1.60%626.71 ms656.74 ms

Comparison

NameIPSSlower
fast_rss407.08 
feeder_ex56.527.2x
elixir_feed_parser8.9045.72x
feed_raptor1.59255.83x

Memory Usage

NameMemoryFactor
fast_rss0.00157 MB 
feeder_ex9.25 MB5886.17x
elixir_feed_parser80.42 MB51170.23x
feed_raptor571.18 MB363425.45x

Input: sleepy

Run Time

NameIPSAverageDevitationMedian99th %
fast_rss760.301.32 ms±16.62%1.21 ms2.03 ms
feeder_ex124.288.05 ms±6.94%8.03 ms10.32 ms
elixir_feed_parser26.2638.09 ms±5.08%37.81 ms44.42 ms
feed_raptor3.21311.16 ms±2.85%307.86 ms345.09 ms

Comparison

NameIPSSlower
fast_rss760.30 
feeder_ex124.286.12x
elixir_feed_parser26.2628.96x
feed_raptor3.21236.57x

Memory Usage

NameMemoryFactor
fast_rss0.00157 MB 
feeder_ex4.28 MB2726.19x
elixir_feed_parser35.88 MB22829.92x
feed_raptor274.98 MB174963.99x

Input: stuff

Run Time

NameIPSAverageDevitationMedian99th %
fast_rss19.190.0521 s±9.19%0.0546 s0.0635 s
feeder_ex0.931.07 s±2.49%1.07 s1.15 s
elixir_feed_parser0.531.88 s±1.22%1.89 s1.92 s
feed_raptor0.079712.54 s±1.61%12.44 s12.77 s

Comparison

NameIPSSlower
fast_rss19.19 
feeder_ex0.9320.59x
elixir_feed_parser0.5336.11x
feed_raptor0.0797240.68x

Memory Usage

NameMemoryFactor
fast_rss0.00154 MB 
feeder_ex140.58 MB91220.55x
elixir_feed_parser1018.78 MB661058.28x
feed_raptor8424.44 MB5466379.81x

Deploying

Deploying rust NIFs can be a little bit annoying as you have to install the rust compiler. If you are having trouble deploying this package make an issue and I will try and help you out.

I will then add it to the FAQ below.

Q. How do I deploy using an Alpine Dockerfile?

A. I recommend using a multi-stage Dockerfile, and doing the following

  1. On the stages where you build all your deps, and build your release make sure to install build-base and libgcc:
# This step installs all the build tools we'll need
RUN apk update && \
    apk upgrade --no-cache && \
    apk add --no-cache \
    git \
    curl \
    build-base \
    libgcc  && \
    mix local.rebar --force && \
    mix local.hex --force
  1. Install the rust compiler and allow dynamic linking to the C library by setting the rust flag
# install rustup
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
ENV RUSTUP_HOME=/root/.rustup \
    RUSTFLAGS="-C target-feature=-crt-static" \
    CARGO_HOME=/root/.cargo  \
    PATH="/root/.cargo/bin:$PATH"
  1. On the stage where you actually run your elixir release install libgcc:
################################################################################
## STEP 4 - FINAL
FROM alpine:3.11

ENV MIX_ENV=prod

RUN apk update && \
    apk add --no-cache \
    bash \
    libgcc \
    openssl-dev

COPY --from=release-builder /opt/built /app
WORKDIR /app
CMD ["/app/my_app/bin/my_app", "start"]

License

FastRSS is released under the Apache License 2.0 - see the LICENSE file.