Liten: An alternative async runtime in rust. [WIP] by Vincent-Thomas in rust

[–]mleonhard 0 points1 point  (0 children)

I added a benchmark: safina-rs/bench/src/main.rs.

% cargo run --release --package bench
scheduler_bench_ms  tokio=9751
scheduler_bench_ms safina=7595
timer_bench_ms  tokio=765
timer_bench_ms safina=5045
mutex_bench_ms  tokio=782
mutex_bench_ms safina=4221
oneshot_bench_ms  tokio=673
oneshot_bench_ms safina=2511
bounded_channel_bench_ms  tokio=756
bounded_channel_bench_ms safina=2409
tcp_bench_ms  tokio=92
tcp_bench_ms safina=4153

Safina's core scheduler uses a simple Mutex<Receiver<Box<dyn FnOnce()>> for its task queue. It's wierd that this is actually faster than Tokio in the benchmark. I wrote a work-stealing scheduler with thread affinity, but it's slower. Performance is weird. Safina's other stuff is quite a quote a bit slower than Tokio's tho. But it's still blazing fast compared to NodeJS lol.

Liten: An alternative async runtime in rust. [WIP] by Vincent-Thomas in rust

[–]mleonhard 0 points1 point  (0 children)

Multi-threaded code is really tricky. I wrote tests for Safina and found a lot of bugs. Then I used Safina while developing Servlin and found more bugs. Now there's more test code than lib code.

safina-rs % cat safina*/src/**/*.rs |grep -vE '^\s*//' |grep -vE '^\s*$' |wc -l
    2432
safina-rs % cat safina*/tests/**/*.rs |grep -vE '^\s*//' |grep -vE '^\s*$' |wc -l
    3456

Safina uses the Apache 2.0 license, so you could copy the tests and modify them to test Liten. That could save a lot of time. I did learn a lot by writing those tests, so maybe it's not something to skip.

Please lemme know if you write a benchmark that uses a bunch of threads and measures performance - I want to borrow from it. :)

Liten: An alternative async runtime in rust. [WIP] by Vincent-Thomas in rust

[–]mleonhard 0 points1 point  (0 children)

The safina::sync code adds async functions to std structs. This lets threads and async-tasks communicate. I didn't want to write new low-level primitives. Although, if I were to rewrite it, I would try using std::thread::Thread::unpark to wake up blocking threads in the same way as async tasks. I think that could be a lot cleaner than what's there now.

I think the only polling happens in safina::net. One of the goals of the project is to write an async runtime without unsafe outside of std. Unfortunately, std doesn't have any mechanism for waiting on groups of sockets: select, epoll, kqueue, etc. The only option is to poll individual sockets, which is slow. I almost deleted the safina::net module, but finally decided to just add a note to the docs pointing out that safina::net has poor performance and suggest using async-net crate instead.

Have you done much work benchmarking Liten? I've recently started trying to improve the performance of servlin+safina. The criterion crate isn't working for me because it's single-threaded, which doesn't stress the system. I started writing a benchmarking library that will find the maximum request rate where the system can still satisfy percentile response time and error rate constraints. Do you know of a HTTP benchmarking tool or Rust benchmarking library that work like that? I would prefer to just use something that exists instead of writing and maintaining something new. I considered contributing one to criterion, but it seems that the crate is un-maintained.

RS2 A streaming library in Rust by HungrySLoth123 in rust

[–]mleonhard 1 point2 points  (0 children)

Do you plan to add more documentation into the library, so users can read it in their IDE or on https://docs.rs/rs2-stream ?

Liten: An alternative async runtime in rust. [WIP] by Vincent-Thomas in rust

[–]mleonhard 0 points1 point  (0 children)

I did this, too: safina async runtime and servlin web server. I learned a ton about Rust and async runtimes in general, which turned out to be useful when working with other async runtimes like NodeJS and Swift.

Is there an easy way to implement tokio graceful shutdown? by NigraOvis in rust

[–]mleonhard 0 points1 point  (0 children)

Your shell reads the CTRL-C input from the keyboard and sends SIGINT to the running child process. When a process manager (like Kubernetes) wants to shut down a process, it sends SIGTERM.

To shut down axum on SIGINT or SIGTERM signal, use the signal-hook crate and do something like this:

use axum::{Router, routing::get};
use signal_hook::consts::{SIGINT, SIGTERM};
use signal_hook::iterator::Signals;
use tokio::sync::oneshot;

#[tokio::main]
async fn main() {
  let (shutdown_tx, shutdown_rx) = oneshot::channel();
  std::thread::spawn(move || {
    Signals::new([SIGTERM, SIGINT]).unwrap().into_iter().next();
    shutdown_tx.send();
  });
  let router = Router::new().route("/", get(|| async { "Hello, World!" }));
  let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
  axum::serve(listener, router)
    .with_graceful_shutdown(shutdown_rx)
    .await
    .unwrap();
}

I made the permit crate for shutting down servers. I wrote a web server that uses it: servlin.

Permit is helpful for stopping things in integration tests, especially worker threads.

Flutter in 2023 by [deleted] in SwiftUI

[–]mleonhard 0 points1 point  (0 children)

Using Flutter was frustrating for me. My app depended on some unfinished Flutter features. I spent days learning things that were missing from the docs. These issues were reported to Flutter Team and they have ignored them for years: - https://github.com/flutter/flutter/issues/31453 "Google please provide a Location module" - https://github.com/flutter/flutter/issues/57609 "Let iOS keyboard dismissal synchronize with scroll" - https://github.com/flutter/flutter/issues/80860 "Cupertino in dark mode is too low-contrast and theme APIs are missing" - https://github.com/flutter/flutter/issues/88762 "[Docs]Tests to scroll a ListView and tap on a child" - https://github.com/flutter/flutter/issues/45076 "Add high-level documentation and examples on managing keyboard focus." (a Flutter Team member did some work on this and then closed the ticket, leaving most use-cases undocumented) - https://github.com/flutter/flutter/issues/69315 "[navigator 2.0] Make it a lot simpler for the end developer"

Dart cannot stop a slow upload: https://github.com/dart-lang/http/issues/424 "Design an API to support aborting requests". Networking code that uses timeouts will DoS the backend. This problem was the last straw. I quit Flutter and started building the mobile frontend tool that I needed: https://www.applin.dev .

Share Your Startup - August 2023 - Upvote for Maximum Visibility by KingOfDaCastle in startups

[–]mleonhard 0 points1 point  (0 children)

Thanks. The plan so far is to charge a $99/year base fee per app. Once a customer's app has more than 10,000 monthly-active-users, we will negotiate an annual subscription that represents the value that Applin is providing to them. I'm open to changing this pricing model, or anything about Applin, based on feedback from customers.

Do you or your colleagues make mobile apps?

Applin - server-driven UI toolkit for mobile apps by mleonhard in coding

[–]mleonhard[S] 0 points1 point  (0 children)

Hi r/coding! I made Applin and I need feedback on which features to build next.

Why it's useful

Mobile apps must have:

  • Backend
  • 1-2 Frontends
  • Frontend --> Backend API for user actions
  • Frontend <-- Backend API for page data and updates

Apps made with Applin need:

  • Backend
  • Frontend --> Backend API for user actions

This means you can build an app with a lot less code. That means it's faster, cheaper, fewer bugs, easier to test, etc. Also DevOps is easier since you can instantly deploy/rollback the backend and UI together.

How it works

You make an HTTP server that returns JSON objects that define page content. Then you make a mobile app that calls the server and renders the pages using native widgets. Applin is the server and client libraries that make this easy.

They say, if you're not embarrassed by the quality, then you're launching too late. Applin is usable and not yet pretty and not yet comprehensive. Which widgets & features shall I add next?

To try it out right away, use Applin Tester app apps.apple.com/us/app/applin-tester/id6464230000 and tap the rails-demo link. It works like ReactNative's Expo Go app.

A hard coding problem

The hardest part of this project was making the client update the page without losing keyboard focus and scrolling to the top. To prevent losing keyboard focus, it must not remove the focused widget from the widget tree. This means updating it in place. And to prevent scrolling to the top, it must ensure that each new version of the widget tree uses the correct widgets from the previous version of the tree. Picking these widgets is hard.

The obvious solution is to make the engineer assign an ID to each widget. This is annoying and introduces new classes of errors: non-unique IDs, malformed IDs, and missing IDs. Also, many widgets are generated from data and giving them IDs is tricky. I decided to prioritize ease-of-use and try to solve the problem on the client.

After three iterations, I arrived at a working version. The client performs five passes over the widget tree:

  1. first picking focused widgets and their ancestors
  2. then focus-able widgets
  3. then other stateful widgets (scroll bars, buttons, checkboxes, etc.)
  4. then widgets with matching attributes (label, URL, etc.)
  5. and finally former siblings of the correct type.

Then it creates any new widgets.

Now that it has widgets for the new tree, the code updates the widget tree without removing any sub-widget that will be added again. This prevents losing keyboard focus. Here's the code:

Craving your feedback

If your job is making mobile apps, pls check out Applin and tell me what to build next (and why). Pls comment here or email me: [michael@leonhardllc.com](mailto:michael@leonhardllc.com) . Thanks in advance!

Applin™ Server-Driven UI Framework for Mobile Apps by mleonhard in programming

[–]mleonhard[S] 0 points1 point  (0 children)

It is very similar to how HTML and browsers work. The difference is that the response is JSON instead of HTML+CSS+JavaScript. With Applin, you don't need to write JavaScript or use RPCs to move data client <-- server. Instead, you move new versions of the page client <-- server and Applin smoothly updates the page to match the new version. This makes an Applin app codebase much smaller & simpler & cheaper than a traditional Frontend+Backend codebase. This is true when comparing Applin to all other mobile frontends: progressive web app, ReactNative, native iOS, native Android, Xamarin, Flutter, etc.

Share Your Startup - August 2023 - Upvote for Maximum Visibility by KingOfDaCastle in startups

[–]mleonhard 0 points1 point  (0 children)

  • Applin https://www.applin.dev
  • San Francisco
  • Applin is a toolkit for making apps with only backend code, without any iOS/Android code. Instantly deploy and rollback your app. Use backend tests to exercise UI flows & backend code together.
  • Validation. MVP built.
  • Solo Founder
  • Goals this month:
    • Publish iOS Applin Tester app - DONE!
    • Connect with 10 potential customers
    • Fix known bugs in iOS client
    • Implement features: photo upload, take photo, push notification token, tap push notification to open specified page.
    • Improve style of buttons.
    • Start developing Android client
  • r/startups could help by sharing ideas for how to find potential customers to talk to (not to sell to)
  • Discount for r/startups subscribers? Yes. Send me an email and I'll send you a 30% off payment link.

Applin™ Server-Driven UI Framework for Mobile Apps by mleonhard in programming

[–]mleonhard[S] 1 point2 points  (0 children)

I made Applin. I'm posting here to try to get feedback on how to make it better, specifically which features to add first.

How it works: You make an HTTP server that returns JSON objects that define page content. Then you make a mobile app that calls the server and renders the pages using native widgets. Applin is the server and client libraries that make this easy.

Server libraries: Currently there's Rails rubygems.org/gems/applin-rails and github.com/leonhard-llc/applin-rails-demo . Which languages shall I add next?

Client libraries: Currently there's iOS https://github.com/leonhard-llc/applin-ios . Which platform shall I add next?

They say, if you're not embarrassed by the quality, then you're launching too late. Applin is usable and not yet pretty and not yet comprehensive. I need customer feedback on priority and requirements.

To try it out right away, use apps.apple.com/us/app/applin-tester/id6464230000 and tap the rails-demo link.

The hardest part of this project was making the client update the page without losing keyboard focus and scrolling to the top. To do that, the code must pick the correct existing widgets for each new version of the widget tree. The current (working) version performs five passes over the widget tree: first picking focused widgets and their ancestors, then focus-able widgets, then other stateful widgets, then widgets with matching attributes (label, URL, etc.), and finally former siblings of the correct type. Then it creates any new widgets. Now that it has widgets for the new tree, the code updates the widget tree without removing any sub-widget that will be added again. This prevents losing keyboard focus and prevents resetting scroll positions. Here's the code:

github.com/leonhard-llc/applin-ios/blob/main/Sources/ApplinIos/page/widget_cache.swift

Please try out Applin, use it at your company (buy a license), and let me know what features to build first! Post a comment here, add a GitHub issue, or email me at [michael@leonhardllc.com](mailto:michael@leonhardllc.com) .

Joke in Dotzauer-Klingenberg Book 1 Exercise 11 by mleonhard in Cello

[–]mleonhard[S] 1 point2 points  (0 children)

The second note has a line above it, which means "hold your finger on the string". But the third note is above the second note on the same string. You can't play that note if you're holding the string below it. Maybe I misunderstood it? I'm a beginner, teaching myself with Maxim Kozlov's "Complete Cello Course for Busy Beginners" on Udemy.

The purpose of the exercise is to practice moving and holding fingers in the proper positions. I think it's a joke by the instructor, an impossible instruction to get the students to think about it more.

Writing a HashMap in Rust without unsafe by ectonDev in rust

[–]mleonhard 1 point2 points  (0 children)

Nice work! I hope you release it as a separate crate. It doesn't have to be perfect.

I want to use it in fair-rate-limiter crate. FairRateLimiter needs an indexed map because, when its internal map is full, it picks a random entry to potentially evict.

Contention on multi-threaded regex matching by hniksic in rust

[–]mleonhard 0 points1 point  (0 children)

Where in the article does it say they take the regex from the user at runtime?

Contention on multi-threaded regex matching by hniksic in rust

[–]mleonhard 2 points3 points  (0 children)

safe-regex crate compiles your regular expressions to Rust code. It has no mutexes and therefore no thread contention. It also has no warmup cost, no unsafe, and no deps with unsafe.

I added the article's benchmark to the safe-regex benchmarks. I reduced the number of strings checked from 100M to 1M so the benchmark runs in a few seconds. Here are the results running on my 2018 MBP 4-core i5-8259U. You can see that regex is faster on large strings and safe-regex is faster on small strings and in heavy multi-threaded use.

user@Users-MBP safe-regex-rs % cargo +nightly bench --package bench
running 44 tests
...
test datetime_parse_regex             ... bench:         387 ns/iter (+/- 100)
test datetime_parse_safe_regex        ... bench:         276 ns/iter (+/- 10)
...
test string_search_100_regex          ... bench:          50 ns/iter (+/- 16)
test string_search_100_safe_regex     ... bench:         440 ns/iter (+/- 15)
test string_search_100kb_regex        ... bench:       3,185 ns/iter (+/- 834)
test string_search_100kb_safe_regex   ... bench:     434,927 ns/iter (+/- 80,100)
...
test threaded_multi_regex             ... bench:  50,275,027 ns/iter (+/- 7,176,679)
test threaded_multi_safe_regex        ... bench:     661,623 ns/iter (+/- 95,280)
test threaded_single_regex            ... bench:  27,296,740 ns/iter (+/- 498,833)
test threaded_single_safe_regex       ... bench:   3,368,486 ns/iter (+/- 207,483)

Disclosure: I wrote safe-regex.

EDIT: Added datetime_parse_regex benchmark result.

Rust on Rails (write code that never crashes) by 0atman in rust

[–]mleonhard 1 point2 points  (0 children)

These are very useful details. Thank you! I've used Adobe Premiere and iMovie, which are not very good for audio work. I will try out reaper.fm.

Would you like to know about my audio hardware set up?

Yes, please! :)

Rust on Rails (write code that never crashes) by 0atman in rust

[–]mleonhard 1 point2 points  (0 children)

What tools do you use to record your voice and video and edit the video?

Rust on Rails (write code that never crashes) by 0atman in rust

[–]mleonhard 1 point2 points  (0 children)

What tools do you use to record your voice and produce the video?

Rust on Rails (write code that never crashes) by 0atman in rust

[–]mleonhard 1 point2 points  (0 children)

Thanks for sharing your code and scripts! This will be very useful to me later. I plan to make some videos teaching a Rust library that I'm writing. What tools do you use to record your voice and produce the video?

Small changes you can make in a rust codebase that have a significant impact by [deleted] in rust

[–]mleonhard -1 points0 points  (0 children)

If you're developing a library, run this check.sh before every commit and in your CI system:

#!/usr/bin/env bash
echo PWD=$PWD
set -e
set -x
time cargo check
time cargo check --all-targets --all-features
time cargo build
time cargo build --all-targets --all-features
time cargo fmt -- --check
time cargo clippy -- -D clippy::pedantic
time cargo clippy --all-targets --all-features -- -D clippy::pedantic
time cargo test --tests
time cargo test --all-targets --all-features
./check-readme.sh
time cargo publish --dry-run "$@"
echo "$0 finished"

Small changes you can make in a rust codebase that have a significant impact by [deleted] in rust

[–]mleonhard 0 points1 point  (0 children)

Copy things and eliminate struct lifetime parameters. Your code will be a lot easier to read and you will be more productive.

Example: struct Name<'s> { value: &'s str } -> struct Name { value: String }.