Rust 101 – 13: Type Parameters and Associated Types

Following on from video 12, looking at how to add type information to traits, to make them flexible enough to describe generic code with different types, for example how to add a u32 to a u64 and return a u128, without defining a whole new trait for every combination of types.

Series: 1: Intro, 2: Language basics, 3: Memory and ownership, 4: Exercises A1, 5: References, 6: Structs and Enums, 7: Panic and Result, 8: Methods, 9: Vec and Box, 10: Strings, 11: Exercises A2, 12: Traits, 13: Type Params, 14: std Traits, 15: Lifetimes, 16: Exercises A3pt1, 17: Exercises A3pt2, 18: Dependencies, 19: API design, 20: Tests

Links:

The course materials for this series are developed by tweede golf. You can find more information at github.com/tweedegolf/101-rs and you can sponsor the work at github.com/sponsors/tweedegolf. They are released under the Creative Commons Attribution Share Alike 4.0 International license.

This series of videos is copyright 2024 Andy Balaam and the tweede golf contributors and is released under the Creative Commons Attribution Share Alike 4.0 International license.

Rust 101 – 12: Traits

Explaining what a trait is, and how to use it. A trait is a bit like an Interface in Java or Go, or an Abstract Base Class in C++ or Python, but it can be used to define behaviour at compile-time as well as at run-time. We go through an example of why you might want to write a “generic” function – one that works for lots of different types, and if so, how you need to be able to say what the types can do if you want to write the body of the function. Traits are a way of saying what a type can do.

Series: 1: Intro, 2: Language basics, 3: Memory and ownership, 4: Exercises A1, 5: References, 6: Structs and Enums, 7: Panic and Result, 8: Methods, 9: Vec and Box, 10: Strings, 11: Exercises A2, 12: Traits, 13: Type params, 14: std Traits, 15: Lifetimes, 16: Exercises A3pt1, 17: Exercises A3pt2, 18: Dependencies, 19: API design, 20: Tests

Links:

The course materials for this series are developed by tweede golf. You can find more information at github.com/tweedegolf/101-rs and you can sponsor the work at github.com/sponsors/tweedegolf. They are released under the Creative Commons Attribution Share Alike 4.0 International license.

This series of videos is copyright 2024 Andy Balaam and the tweede golf contributors and is released under the Creative Commons Attribution Share Alike 4.0 International license.

Rust 101 – 11: Exercises for module A2

Going through some exercises on Rust ownership, references, slices and error handling.

Series: 1: Intro, 2: Language basics, 3: Memory and ownership, 4: Exercises A1, 5: References, 6: Structs and Enums, 7: Panic and Result, 8: Methods, 9: Vec and Box, 10: Strings, 11: Exercises A2, 12: Traits, 13: Type params, 14: std Traits, 15: Lifetimes, 16: Exercises A3pt1, 17: Exercises A3pt2, 18: Dependencies, 19: API design, 20: Tests

Links:

Rust 101 is a series of videos explaining how to write programs in Rust. The course materials for this series are developed by tweede golf. You can find more information at github.com/tweedegolf/101-rs and you can sponsor the work at github.com/sponsors/tweedegolf. They are released under the Creative Commons Attribution Share Alike 4.0 International license.

This series of videos is copyright 2024 Andy Balaam and the tweede golf contributors and is released under the Creative Commons Attribution Share Alike 4.0 International license.

Deleting an Indexed DB store can be incredibly slow on Firefox

See also: Keep your Indexed DB keys and values small if you want good performance! and Don’t store arrays of numbers in Indexed DB – use base64 instead.

We had performance problem in Element Web when upgrading the Indexed DB schema, and it turned out that in Firefox, deleting an object store can be incredibly slow. It can take tens of minutes or even hours.

(In Chromium the same operation can take tens of seconds, but it’s way, way faster.)

I was expecting this to be a near-instant operation, so this was a definite surprise to me.

Note that my analysis is based on widely-available browsers in February 2024, and will probably become out-of-date.

You can see the full graphs here: artificialworlds.net/indexed-db-perf/delete.html. Source code is at codeberg.org/andybalaam/indexed-db-perf.

Here’s what I learned:

Headline 1: Firefox can take a very long time to delete an object store

Graph showing that Firefox took 1.2 million milliseconds to delete an object store containing 200K records.

Firefox took 20 minutes to delete an object store containing 200K records, with one index.

In Chromium, I found that deleting a similar object store took 21 seconds, which is still slow, but rather more acceptable.

Consider not deleting stores you don’t need any more. If you must delete them, you will need to provide feedback to your users, especially if they are using Firefox.

Headline 2: Clearing the store before deleting it really helps(!)

Graph showing that Firefox takes 1.2 million ms to delete a large object store (200K records), or 300 thousand ms if you clear it before deleting it.

Graph showing that Chromium takes 20 thousand ms to delete a large object store (200K records), or 10 thousand ms if you clear it before deleting it.

On both Firefox and Chromium, running objectStore.clear() before upgrading the db and deleting the store made a significant improvement to the total time. On Chromium it more than halved the time to delete the store, and on Firefox (where the numbers were huge) it reduced the time by about 3 times!

Thanks to michael-p on Stack Overflow for giving me the idea.

Clear your store before deleting it.

Headline 3: With no indices, this is fine

Firefox deletes object stores fairly fast if there are no indices (and so does Chromium).

Graph showing that even for 200K records, Firefox can delete an object store in under 500ms if there is no index on it.

Even for 200K records, Firefox can delete an object store in under 500ms if there is no index on it.

If you need fast deletion, don’t use indices.

Observation: It’s not done until the DB is closed

In my timing experiments, I found that objectStore.delete() completed, but the operation was not really done. When I called the close() method on my IDBDatabase I had to wait a whole lot longer. (The close time is included in the measurements above.)

Even when I refreshed the browser, I found I had a long wait to open the Indexed DB database. After the wait, it worked fine and the schema update was complete.

Expect long close times after a deletion.

Don’t store arrays of numbers in Indexed DB – use base64 instead

Following on from Keep your Indexed DB keys and values small if you want good performance!, here is another thing I’ve learned about Indexed DB performance (in January 2024):

If you have a long list of numbers to store, don’t put them in a JavaScript array – instead encode them to base64.

Here are the numbers:

Graph showing that arrays of numbers are much slower to count than the same numbers encoded as base64, in Firefox.

On Firefox, storing the same set of numbers as an array is much slower than encoding them as base64.

Graph showing that arrays of numbers are much slower to count than the same numbers encoded as base64, in Chromium.

On Chromium, storing the same set of numbers as an array is much slower than encoding them as base64.

These graphs show that in both Firefox and Chromium (at time of writing), it is much faster to count the records in an Indexed DB store if the list of numbers inside each record is encoded as a base64 string instead of being included directly as a JavaScript array.

The interactive 3D(!) graphs are here: artificialworlds.net/indexed-db-perf/arrays.html and the source code is at codeberg.org/andybalaam/indexed-db-perf.

See also: Keep your Indexed DB keys and values small if you want good performance! and Deleting an Indexed DB store can be incredibly slow on Firefox.