<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Lycoris52</title>
    <description>The latest articles on Forem by Lycoris52 (@lycoris52).</description>
    <link>https://forem.com/lycoris52</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3805924%2Fdc2cafed-fb2f-4ed6-8fd3-8a2499a46b51.png</url>
      <title>Forem: Lycoris52</title>
      <link>https://forem.com/lycoris52</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lycoris52"/>
    <language>en</language>
    <item>
      <title>Rust vs Python vs Node.js Speed Comparison on ZIP Image Loading Benchmark</title>
      <dc:creator>Lycoris52</dc:creator>
      <pubDate>Wed, 04 Mar 2026 14:26:01 +0000</pubDate>
      <link>https://forem.com/lycoris52/rust-vs-python-vs-nodejs-speed-comparison-on-zip-image-loading-benchmark-4hpn</link>
      <guid>https://forem.com/lycoris52/rust-vs-python-vs-nodejs-speed-comparison-on-zip-image-loading-benchmark-4hpn</guid>
      <description>&lt;p&gt;When I previously created a manga viewer application in Rust called RustMangaReader, the most important thing for considering which programming language to be used was loading speed.&lt;/p&gt;

&lt;p&gt;So I need to test which programming language is the fastest.&lt;/p&gt;

&lt;p&gt;If you are interested in the manga viewer itself, it's on this github:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Lycoris52" rel="noopener noreferrer"&gt;
        Lycoris52
      &lt;/a&gt; / &lt;a href="https://github.com/Lycoris52/RustMangaReader" rel="noopener noreferrer"&gt;
        RustMangaReader
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Windows Manga Viewer written in Rust
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a href="https://github.com/Lycoris52/RustMangaReader#japanese-explanation" rel="noopener noreferrer"&gt;日本語の説明はこちら&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/Lycoris52/RustMangaReader/./src/assets/icon128.ico"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FLycoris52%2FRustMangaReader%2F.%2Fsrc%2Fassets%2Ficon128.ico" alt="An example image" width="32" height="32"&gt;&lt;/a&gt;  RustMangaReader &lt;a rel="noopener noreferrer" href="https://github.com/Lycoris52/RustMangaReader/./src/assets/icon128.ico"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FLycoris52%2FRustMangaReader%2F.%2Fsrc%2Fassets%2Ficon128.ico" alt="An example image" width="32" height="32"&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;RustMangaReader is a high-performance, lightweight &lt;strong&gt;offline&lt;/strong&gt; manga and comic viewer built in Rust. &lt;br&gt;
Designed specifically for the Windows, it focuses on providing a fluid, lag-free reading experience through preloading and native rendering.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Lycoris52/RustMangaReader/./src/assets/mangaviewer.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FLycoris52%2FRustMangaReader%2F.%2Fsrc%2Fassets%2Fmangaviewer.png" alt="app image" width="500"&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;⚡ Key Features&lt;/h3&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Built for Speed&lt;/strong&gt;: Uses a dual-buffer system to preload upcoming and previous pages in the background, ensuring near-instant page turns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized for Windows&lt;/strong&gt;:
&lt;ul&gt;
&lt;li&gt;Leverages &lt;strong&gt;Windows-native sorting&lt;/strong&gt; (so "Page2" comes before "Page10")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-performance&lt;/strong&gt; GPU rendering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Zip extraction required&lt;/strong&gt; RustMangaReader reads directly from compressed files saving disk space without sacrificing speed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Scaling&lt;/strong&gt;: Includes multiple resampling algorithms from Nearest Neighbor to Lanczos3 to make every scan look its best on your monitor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailored Reading&lt;/strong&gt;: Supports Single Page, Double Page (Left-to-Right), and Double Page (Right-to-Left) modes, including a "Cover + Spreads" shift toggle (Odd/Even page).&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;🎁 Free &amp;amp; Open Feedback&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;MangaReader is a completely free application! &lt;br&gt;
I want to make it…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Lycoris52/RustMangaReader" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;Since I already ran some benchmarks before developing it, I thought it might be helpful to share the results.&lt;/p&gt;




&lt;h2&gt;
  
  
  Choosing the Languages
&lt;/h2&gt;

&lt;p&gt;Here is my speculation about each language before testing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C++&lt;/strong&gt;&lt;br&gt;
Probably the fastest, but honestly it is really painful to write. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;br&gt;
Very easy to write, and I use it a lot at work.&lt;br&gt;
But it is slow.&lt;br&gt;
Still, if I want to add AI features later, it will be really useful if the base program is developed using python.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JavaScript&lt;/strong&gt;&lt;br&gt;
Very easy to deploy on many operating systems.&lt;br&gt;
There are many native libraries, so I expected it might not be too slow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;br&gt;
I have been curious about Rust for a long time and wanted to learn it.&lt;br&gt;
But since I had never used it before, I wasn’t sure if it was really that fast.&lt;/p&gt;

&lt;p&gt;So I decided to write simple programs in each language and measure the speed.&lt;/p&gt;

&lt;p&gt;(I didn’t write the C++ version because it looks too troublesome… sorry.)&lt;/p&gt;


&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;p&gt;The main feature I wanted for the manga viewer was:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reading images directly from a ZIP file without extracting it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;So the benchmark program does exactly that.&lt;/p&gt;

&lt;p&gt;Now, I needed a ZIP file containing many images, so I created one.&lt;br&gt;
I asked ChatGPT to generate a random 4K image, duplicated it 10 times, and put them into a ZIP file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4hdkjj10iw93pi3h7ph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4hdkjj10iw93pi3h7ph.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Size of one image: 7.17 MB&lt;br&gt;
ZIP file size: 71.7 MB&lt;/p&gt;


&lt;h2&gt;
  
  
  Machine Specifications
&lt;/h2&gt;

&lt;p&gt;The benchmark machine specs:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CPU  : AMD Ryzen 9 7900
RAM  : G.Skill F56000J3036G 32GB DDR5x2
NVMe : Samsung 990 Pro 4TB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Benchmark Code
&lt;/h2&gt;

&lt;p&gt;Rust&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use std::env;
use std::fs::File;
use std::io::{Read, Seek};
use std::time::Instant;

fn parse_arg(args: &amp;amp;[String], key: &amp;amp;str, default: &amp;amp;str) -&amp;gt; String {
    args.iter()
        .position(|a| a == key)
        .and_then(|i| args.get(i + 1))
        .cloned()
        .unwrap_or_else(|| default.to_string())
}

fn main() -&amp;gt; anyhow::Result&amp;lt;()&amp;gt; {
    let zip_path = "./benchmark_images.zip";
    let iters: usize = 10;

    // Warmup + timed iterations
    let mut best_ms = f64::INFINITY;
    let mut last_stats = (0usize, 0u64);

    for iter in 0..iters {
        let file = File::open(&amp;amp;zip_path)?;
        let mut archive = zip::ZipArchive::new(file)?;

        let start = Instant::now();

        let mut count = 0usize;
        let mut total_bytes: u64 = 0;

        // Iterate entries in zip
        for i in 0..archive.len() {
            let mut f = archive.by_index(i)?;
            let name = f.name().to_string();

            let mut buf = Vec::with_capacity(f.size() as usize);
            f.read_to_end(&amp;amp;mut buf)?;
            total_bytes += buf.len() as u64;

            // Decode to pixels (forces actual image parsing)
            let img = image::load_from_memory(&amp;amp;buf)?;
            // Force pixel materialization
            let _rgba = img.to_rgba8();

            count += 1;
        }

        let elapsed = start.elapsed().as_secs_f64() * 1000.0;
        last_stats = (count, total_bytes);

        // skip first run as warmup-ish if you want, but we’ll just keep best
        if elapsed &amp;lt; best_ms {
            best_ms = elapsed;
        }

        eprintln!("iter {}: {:.2} ms", iter + 1, elapsed);
    }

    let (count, total_bytes) = last_stats;
    let secs = best_ms / 1000.0;
    let mb = total_bytes as f64 / (1024.0 * 1024.0);

    println!("zip: {}", zip_path);
    println!("images: {}", count);
    println!("bytes read: {} ({:.2} MiB)", total_bytes, mb);
    println!("best time: {:.2} ms", best_ms);
    if secs &amp;gt; 0.0 {
        println!("throughput: {:.2} images/s", count as f64 / secs);
        println!("throughput: {:.2} MiB/s", mb / secs);
    }

    Ok(())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import time
import zipfile
from io import BytesIO
from PIL import Image

def run_once(zip_path: str) -&amp;gt; tuple[float, int, int]:
    t0 = time.perf_counter()

    count = 0
    total_bytes = 0

    with zipfile.ZipFile(zip_path, "r") as zf:
        for info in zf.infolist():
            data = zf.read(info)  # read entry into memory (no extracting)
            total_bytes += len(data)

            # Decode image fully (force pixel load)
            with Image.open(BytesIO(data)) as im:
                im.load()

            count += 1

    t1 = time.perf_counter()
    return (t1 - t0), count, total_bytes

best = float("inf")
last = (0, 0)

for i in range(10):
    sec, count, total_bytes = run_once("benchmark_images.zip")
    last = (count, total_bytes)
    best = min(best, sec)
    print(f"iter {i+1}: {sec*1000:.2f} ms")

count, total_bytes = last
mib = total_bytes / (1024 * 1024)

print(f"zip: benchmark_images.zip")
print(f"images: {count}")
print(f"bytes read: {total_bytes} ({mib:.2f} MiB)")
print(f"best time: {best*1000:.2f} ms")
print(f"throughput: {count/best:.2f} images/s")
print(f"throughput: {mib/best:.2f} MiB/s")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Javascript(Node.js)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import fs from "node:fs";
import yauzl from "yauzl";
import sharp from "sharp";

function hrNowSec() {
    return Number(process.hrtime.bigint()) / 1e9;
}

async function readEntryToBuffer(zipFile, entry) {
    return new Promise((resolve, reject) =&amp;gt; {
        zipFile.openReadStream(entry, (err, stream) =&amp;gt; {
            if (err) return reject(err);
            const chunks = [];
            let total = 0;
            stream.on("data", (c) =&amp;gt; { chunks.push(c); total += c.length; });
            stream.on("end", () =&amp;gt; resolve({ buf: Buffer.concat(chunks, total), bytes: total }));
            stream.on("error", reject);
        });
    });
}

async function runOnce(zipPath, mode) {
    const t0 = hrNowSec();

    let count = 0;
    let totalBytes = 0;

    const zipFile = await new Promise((resolve, reject) =&amp;gt; {
        yauzl.open(zipPath, { lazyEntries: true }, (err, zf) =&amp;gt; {
            if (err) return reject(err);
            resolve(zf);
        });
    });

    const done = new Promise((resolve, reject) =&amp;gt; {
        zipFile.readEntry();

        zipFile.on("entry", async (entry) =&amp;gt; {
            const { buf, bytes } = await readEntryToBuffer(zipFile, entry);
            totalBytes += bytes;

            // Force actual decode to pixels
            // raw().toBuffer() makes sharp decode the image data
            await sharp(buf).raw().toBuffer();

            count += 1;
            zipFile.readEntry();
        });

        zipFile.on("end", () =&amp;gt; resolve());
        zipFile.on("error", reject);
    });

    await done;
    zipFile.close();

    const t1 = hrNowSec();
    return { sec: (t1 - t0), count, totalBytes };
}

async function main() {
    const zip = "benchmark_images.zip"
    const iters = 10;

    let best = Number.POSITIVE_INFINITY;
    let last = { count: 0, totalBytes: 0 };

    for (let i = 0; i &amp;lt; iters; i++) {
        const r = await runOnce(zip);
        last = r;
        best = Math.min(best, r.sec);
        console.log(`iter ${i + 1}: ${(r.sec * 1000).toFixed(2)} ms`);
    }

    const mib = last.totalBytes / (1024 * 1024);
    console.log(`zip: ${zip}`);
    console.log(`images: ${last.count}`);
    console.log(`bytes read: ${last.totalBytes} (${mib.toFixed(2)} MiB)`);
    console.log(`best time: ${(best * 1000).toFixed(2)} ms`);
    if (best &amp;gt; 0) {
        console.log(`throughput: ${(last.count / best).toFixed(2)} images/s`);
        console.log(`throughput: ${(mib / best).toFixed(2)} MiB/s`);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The programs all do the same thing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the ZIP file&lt;/li&gt;
&lt;li&gt;Read each image entry into memory&lt;/li&gt;
&lt;li&gt;Decode the image&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each test runs 10 iterations, and the best time is used as the result.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benchmark Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;-&lt;/th&gt;
&lt;th&gt;Rust&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;Javascript&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;557.73 ms&lt;/td&gt;
&lt;td&gt;1056.06 ms&lt;/td&gt;
&lt;td&gt;811.30 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;556.50 ms&lt;/td&gt;
&lt;td&gt;1034.25 ms&lt;/td&gt;
&lt;td&gt;819.17 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;555.70 ms&lt;/td&gt;
&lt;td&gt;1036.28 ms&lt;/td&gt;
&lt;td&gt;803.66 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 4&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;556.82 ms&lt;/td&gt;
&lt;td&gt;1034.54 ms&lt;/td&gt;
&lt;td&gt;813.86 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;555.07 ms&lt;/td&gt;
&lt;td&gt;1035.30 ms&lt;/td&gt;
&lt;td&gt;816.00 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 6&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;557.37 ms&lt;/td&gt;
&lt;td&gt;1036.74 ms&lt;/td&gt;
&lt;td&gt;793.65 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;556.83 ms&lt;/td&gt;
&lt;td&gt;1033.83 ms&lt;/td&gt;
&lt;td&gt;792.46 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;555.69 ms&lt;/td&gt;
&lt;td&gt;1035.08 ms&lt;/td&gt;
&lt;td&gt;774.49 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 9&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;564.42 ms&lt;/td&gt;
&lt;td&gt;1035.40 ms&lt;/td&gt;
&lt;td&gt;771.28 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iter 10&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;554.54 ms&lt;/td&gt;
&lt;td&gt;1034.46 ms&lt;/td&gt;
&lt;td&gt;734.43 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;bytes read&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;75252870 (71.77 MiB)&lt;/td&gt;
&lt;td&gt;75252870 (71.77 MiB)&lt;/td&gt;
&lt;td&gt;75252870 (71.77 MiB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;best time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;554.54 ms&lt;/td&gt;
&lt;td&gt;1033.83 ms&lt;/td&gt;
&lt;td&gt;734.43 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;18.03 images/s&lt;/td&gt;
&lt;td&gt;9.67 images/s&lt;/td&gt;
&lt;td&gt;13.62 images/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;129.42 MiB/s&lt;/td&gt;
&lt;td&gt;69.42 MiB/s&lt;/td&gt;
&lt;td&gt;97.72 MiB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As expected, Rust was the fastest.&lt;br&gt;
However, JavaScript was actually not bad at all.&lt;/p&gt;

&lt;p&gt;As for Python, if I want to add AI translation features later, I might implement them as a separate API server instead.&lt;br&gt;
For this kind of task, Python is simply too slow.&lt;/p&gt;

&lt;p&gt;The results were not very surprising, but I hope they are useful for someone.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>python</category>
      <category>node</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
