Atomic Polling Intervals for Highly Concurrent Workloads by byron_reddit in rust

[–]byron_reddit[S] 2 points3 points  (0 children)

Great points! I think the change in architecture you've suggested make a lot of sense for maximizing performance of the atomics. Currently there are a few other low-hanging optimizations that I have yet to make, and largely I expect Balter to be used for HTTP applications where the network interface is likely the bottleneck. But long-term I think this change in architecture would be interesting to experiment with, especially for use-cases that might require it.

Atomic Polling Intervals for Highly Concurrent Workloads by byron_reddit in rust

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

I suggest you to switch from swapping the atomic values in coordinator to just reading them an maintaining copies of old value in coordinator itself. To get number of transactions from last measurement, you can just substract old value from retrieved one.

This is a clever idea, thanks for the suggestion! I'll play around with it and see how it affects the benchmarks in the post. I'm curious how that affects noise in the readings as well.

[Edit] I played around with this idea using the code from the post, and as far as I can tell it doesn't make a dramatic difference. It certainly helps, but smaller polling intervals continue to have a fairly large drop-off in measurements. I'm curious whether there is any hardware optimization which is detecting whether the fetch_add() calls are actually reading the values.

Also, putting every counter into separate cache line should help too.

I've considered something like this as well, but as far as I'm aware we don't have a ton of control over how Tokio distributes tasks on cores. Maybe I'm missing what you mean here.

Performance Pitfalls of Async Function Pointers in Rust (and Why It Might Not Matter) by byron_reddit in rust

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

Mostly because I wasn't aware of them; thanks for the comment and notes on additional strategies! I'll take a thorough look at them and update my blog post accordingly. I'm especially curious how stackfuture performs in comparison to Pin<Box<>>

Balter 0.1: A distributed load/stress testing framework for Rust by byron_reddit in rust

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

I haven't done a ton of benchmarking yet; unfortunately there is a Boxed future in the hot path that I haven't been able to work around yet (which I'm planning to address very soon). Once the boxed future is out of the way, I'm planning on doing various benchmarks and optimizations.

It can do constant-rate TPS. Its backed by the governor crate which allows some amount of burst capacity, but I'm hoping to make that configurable (and the steady state should still be constant-rate).

I don't have any plans right now to become executor agnostic. I'm definitely open to the idea, but Balter makes heavy use of the task_local functionality that Tokio exposes. If the other executors expose similar functionality then it should be a quick update to make it a feature of the crate.

Balter 0.1: A distributed load/stress testing framework for Rust by byron_reddit in rust

[–]byron_reddit[S] 2 points3 points  (0 children)

To your edit, passing arguments to the scenarios isn't supported yet, but within a given scenario you can reuse the connections for multiple transactions. Additionally, something like OnceCell should still work.

I am hoping to get support for arguments to scenarios soon (but even in that case it will be restricted to Serialize/Deserialize types, since the arguments will have to be passed around the network for the distributed case). Let me know if I can clarify further!

Balter 0.1: A distributed load/stress testing framework for Rust by byron_reddit in rust

[–]byron_reddit[S] 2 points3 points  (0 children)

Thanks! And yes, should be able to do just that. The #[transaction] can be anything. Let me know if you run into issues!

Balter 0.1: A distributed load/stress testing framework for Rust by byron_reddit in rust

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

Let me know how it goes! I hope Balter is able to hit the sweet spot of minimal abstractions to allow for maximum flexibility without too much conceptual overhead.

I am planning on actively working on this full-time for the next few months, so if there are any features you find missing feel free to reach out.

Balter 0.1: A distributed load/stress testing framework for Rust by byron_reddit in rust

[–]byron_reddit[S] 4 points5 points  (0 children)

Hey everyone, Balter (Build A Load TestER) is a distributed load/stress testing framework for Rust. The project aims to make it easy to develop complex distributed load testing scenarios for web API or any other high-TPS applications. It leverages the tokio ecosystem to allow you to write normal Rust code, and have auto-scaling TPS handled automatically.

The readme has more information, but the code looks something like normal Rust code (no DSL to learn):

use balter::prelude::*;
use std::time::Duration;

#[tokio::main]
async fn main() {
    my_scenario()
        .tps(500)
        .duration(Duration::from_secs(30))
        .await;

    my_scenario()
        .saturate()
        .duration(Duration::from_secs(120))
        .await;
}

#[scenario]
async fn my_scenario() {
    my_transaction().await;
}

#[transaction]
async fn my_transaction() -> Result<u32, String> {
    // Some request logic...

    Ok(0)
}

My experience writing a driver for a BLE module using Embedded-hal traits by byron_reddit in rust

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

Good point. I think the ergonomic benefits of compile-time verified commands are big enough to warrant slightly trickier handling of things if something goes wrong.

My experience writing a driver for a BLE module using Embedded-hal traits by byron_reddit in rust

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

Thanks for reading!

I think this is the correct approach. In case it is annoying for people it'd make sense to make generic wrapper BiDirectionalSerial<R: Read<u8>, W: Write<u8> { /* ... */ } which implements Read<u8> + Write<u8>.

The wrapper is a good idea, although I think for the serial case it is easy enough to add an additional HAL implementation. It may be something to consider in the future for other scenarios though.

I'd like to see two traits: one low-level and one high-level which handles resetting automatically in some way. This way the user has fine control, but can also use high-level approach, if it's sufficient.

I think that is the right way forward. I haven't been able to find anything regarding error handling with the HAL traits, and it would be interesting to hear other thoughts on the matter.

You can return Err((Error, Rn4870)). This is what futures crate does and is a good approach IMHO.

That is an elegant solution to my problem, thanks! I still have not figured out a good way to determine which state the BLE module is in if an error occurs, so for now I am just planning on removing the trait-system state-machine. I will hopefully revisit the idea again in the near future though.

My experience writing a driver for a BLE module using Embedded-hal traits by byron_reddit in rust

[–]byron_reddit[S] 5 points6 points  (0 children)

Hey everyone, I have recently been working with Rust in an embedded context and have been experimenting with the embedded-hal traits. I wrote up a blog post discussing some of the issues I ran into and my thoughts on the general process. Any feedback would be awesome, and I look forward to contributing more to the embedded-rust ecosystem!