Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return a iterator from Connection::load #2799

Merged
merged 32 commits into from
Sep 29, 2021

Conversation

weiznich
Copy link
Member

@weiznich weiznich commented Jun 1, 2021

This PR provides a prototypical implementation of Connection::load so
that a iterator of Row's is returned. This is currently only
implemented for the postgres backend to checkout the performance impact
of this change.

@diesel-rs/reviewers Feel free to have a first look at this and comment on the general approach. I'm well aware that there are many missing pieces like documentation, implementation for sqlite and mysql, cleaning up some artifacts from refactoring, …

@weiznich weiznich added the run-benchmarks Used to indicate that github actions should run our benchmark suite label Jun 1, 2021
@weiznich weiznich force-pushed the feature/load_returns_a_iterator branch from 3ce47f3 to 12fd769 Compare June 1, 2021 14:02
@weiznich weiznich added run-benchmarks Used to indicate that github actions should run our benchmark suite and removed run-benchmarks Used to indicate that github actions should run our benchmark suite labels Jun 1, 2021
Copy link
Member

@Ten0 Ten0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, the PG backend is currently using the entire-result mode of libpq, while for this to resolve the original issue, we'd have to use row-by-row mode and this is not yet implemented as part of this draft.

@@ -1404,7 +1404,7 @@ pub trait RunQueryDsl<Conn>: Sized {
where
Self: LoadQuery<Conn, U>,
{
self.internal_load(conn)
self.internal_load(conn)?.collect()
Copy link
Member

@Ten0 Ten0 Jun 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering this changes the overall interaction with libpq in row-by-row mode, using load_iter().collect() may be (esp. depending on the backend) less performant than the current version (while it improves data locality, it may increase the number of allocations/deallocations).

Given this, I feel like we should leave it to each specific backend to choose whether to implement .load() as .load_iter().collect(), which unless I'm mistaken is not what is done here.

Once we have benchmarked the row-by-row implementation for PG we can decide what to do for its specific case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is even for implementations which fetch everything at once we must iterate over all elements as we would like to map every row to a tuple of rust values. Returning an iterator internally may allow future users to decide to collect into some different container than a vector. At least in my own personal projects I build sometimes a HashMap for random lookup out of the database result. That would be easier if I could just take a Iterator<Item = (Key, Value)> and collect that into the HashMap directly.

Comment on lines 35 to 36
where
Self: for<'a> IterableConnection<'a, <Self as Connection>::Backend>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if there's much point in providing a load_iter version when the backend does not support partially loading the results: this may reduce the memory usage by no more than ~2.
I'd have imagined:

trait Connection: SimpleConnection + Sized + Send {}
trait IterableConnection: Connection {}

with IterableConnection only implemented when row-by-row is supported.

That being said, having an additional load_deserialize_iter with an implementation similar to this one doing just the deserialization on the fly may be nice to have as well eventually.

Copy link
Member Author

@weiznich weiznich Jun 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written above, at least for me that's not only about reducing memory usage, but also about optimizing how often I need to iterate over a result set. See the following example:

Diesel 1.4.x:

users::table.select((users::name, users::id)).load::<(String, i32)>(&conn)?.into_iter().collect::<HashMap<_, _>>();

Diesel with this change:

users::table.select((users::name, users::id)).internal_load::<(String, i32)>(&conn)?.collect::<Result<HashMap<_, _>, _>>();

which is not perfect API wise yet, but removes at least one iteration over the result set. We may want to introduce a more formal API here that is not named internal_load 😉

@@ -24,13 +28,13 @@ impl<'a> ExactSizeIterator for Cursor<'a> {
}

impl<'a> Iterator for Cursor<'a> {
type Item = PgRow<'a>;
type Item = crate::QueryResult<PgRow<'a>>;
Copy link
Member

@Ten0 Ten0 Jun 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we don't really need Iterator that returns Rows: all we ever do with it is call .map(FromSqlRow::build_from_row). If we instead make an iterator that both creates the Row<'a> and calls FromSqlRow on it as part of a single iterator we don't need to add Rcs everywhere. (#2707 (reply in thread))

That being said in row-by-row mode there's no need to keep a reference to a global result object, the PGresult returned by each call to PQgetResult is enough so we could just store it in Row. (doc)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we don't really need Iterator that returns Rows: all we ever do with it is call .map(FromSqlRow::build_from_row). If we instead make an iterator that both creates the Row<'a> and calls FromSqlRow on it as part of a single iterator we don't need to add Rcs everywhere.

For diesel itself it's true that we never do anything else than calling FromSqlRow::build_from_row onto the returned row. The idea behind this change is that it's now possible to just skip diesels deserialization layer, in such a way that it is possible to interact with the raw result set. This is useful for cases where you don't know the schema at compile time and want to build for example select clauses at runtime. In the end this just tries to separate different diesel layers more strictly, so that in the future someone can decide to use diesels Connection but to skip the query builder entirely.

That all written, I'm not sure if that's even worth it and if it will work with all backends.

internal_result: RawResult,
column_count: usize,
row_count: usize,
column_name_map: OnceCell<Vec<Option<String>>>,
_marker: PhantomData<&'a super::PgConnection>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This marker seems to indicate that the connection should not be dropped or reused before the PgResult is dropped, but I haven't seen a reference of this in the Postgres doc. Did I miss it and the previous impl was not super safe because that was missing? Otherwise, why is this here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just there to be really safe that nothing goes wrong 🙈

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems to prevent from e.g. zipping two results and deserializing on the fly no?
Wouldn't adding a few tests to be sure it doesn't break cover for being really sure they don't depend on the connection being dropped/no other query being made be enough?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually documented that it's not needed: https://www.postgresql.org/docs/13/libpq-exec.html#LIBPQ-PQCLEAR

@weiznich
Copy link
Member Author

If I understand correctly, the PG backend is currently using the entire-result mode of libpq, while for this to resolve the original issue, we'd have to use row-by-row mode and this is not yet implemented as part of this draft.

After having looked at the row-by-row mode I'm not sure if I really want to use that as part of the libpq based connection. In general it seems to be a shortcoming of libpq that there is no way to fetch single rows/blocks of rows while reusing existing buffers like this is possible in other client implementations. We may want to keep the fetch all solution for PgConnection and maybe provide a pure rust Connection implementation someday that solves this better.

@weiznich weiznich force-pushed the feature/load_returns_a_iterator branch from 0d39aa3 to 51a677a Compare June 11, 2021 10:33
@weiznich weiznich added run-benchmarks Used to indicate that github actions should run our benchmark suite and removed run-benchmarks Used to indicate that github actions should run our benchmark suite labels Jun 11, 2021
@weiznich weiznich added run-benchmarks Used to indicate that github actions should run our benchmark suite and removed run-benchmarks Used to indicate that github actions should run our benchmark suite labels Jun 18, 2021
@weiznich weiznich marked this pull request as ready for review June 18, 2021 15:07
@weiznich
Copy link
Member Author

weiznich commented Jun 18, 2021

I've updated all implementation now. Let's see how the benchmarks look. A more in depth review would be welcome.
Things I will address maybe next week:

  • Add comments to all new unsafe blocks whey the are sound
  • Add insightful messages to unreachable! calls prompting users to open github issues if they ever see that message.
  • Fixing the remaining CI issues (mostly dead_code )

@weiznich weiznich added run-benchmarks Used to indicate that github actions should run our benchmark suite and removed run-benchmarks Used to indicate that github actions should run our benchmark suite labels Jun 28, 2021
@weiznich weiznich force-pushed the feature/load_returns_a_iterator branch 3 times, most recently from f9100c7 to 28c1f3c Compare July 2, 2021 07:57
@weiznich weiznich added run-benchmarks Used to indicate that github actions should run our benchmark suite and removed run-benchmarks Used to indicate that github actions should run our benchmark suite labels Jul 2, 2021
@weiznich
Copy link
Member Author

weiznich commented Jul 2, 2021

@diesel-rs/reviewers This is now ready for a finial review.

Benchmark results:

The largest regression seems to be for queryable_by_name on the sqlite backend. Otherwise there are some slight regressions for large results sets for sqlite + mysql and some minor speedups for smaller results sets. I'm not sure where exactly they are coming from.

Postgres
group                                                                                     changes                                 master
-----                                                                                     -------                                 ------
bench_insert/diesel/1                                                                     1.00   347.3±40.27µs        ? ?/sec     1.03  357.0±126.75µs        ? ?/sec
bench_insert/diesel/10                                                                    1.00   404.1±29.76µs        ? ?/sec     1.04   419.2±44.81µs        ? ?/sec
bench_insert/diesel/100                                                                   1.04  1274.3±145.39µs        ? ?/sec    1.00  1229.8±67.29µs        ? ?/sec
bench_insert/diesel/25                                                                    1.00   548.7±58.93µs        ? ?/sec     1.00   550.5±45.86µs        ? ?/sec
bench_insert/diesel/50                                                                    1.00   728.4±56.76µs        ? ?/sec     1.05   764.4±48.21µs        ? ?/sec
bench_loading_associations_sequentially/diesel/bench_loading_associations_sequentially    1.00     36.4±1.58ms        ? ?/sec     1.06     38.5±1.68ms        ? ?/sec
bench_medium_complex_query/diesel/1                                                       1.05    81.1±13.91µs        ? ?/sec     1.00    77.0±13.03µs        ? ?/sec
bench_medium_complex_query/diesel/10                                                      1.01    91.4±12.66µs        ? ?/sec     1.00    90.5±12.20µs        ? ?/sec
bench_medium_complex_query/diesel/100                                                     1.01   145.5±20.79µs        ? ?/sec     1.00   143.6±22.42µs        ? ?/sec
bench_medium_complex_query/diesel/1000                                                    1.00   624.3±76.15µs        ? ?/sec     1.05   656.4±74.72µs        ? ?/sec
bench_medium_complex_query/diesel/10000                                                   1.00      5.3±0.29ms        ? ?/sec     1.01      5.4±0.31ms        ? ?/sec
bench_medium_complex_query/diesel_boxed/1                                                 1.00    82.6±11.00µs        ? ?/sec     1.01    83.4±10.76µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/10                                                1.00    92.4±14.17µs        ? ?/sec     1.00    92.8±13.10µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/100                                               1.05   144.9±26.42µs        ? ?/sec     1.00   138.3±21.43µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/1000                                              1.00   653.3±85.44µs        ? ?/sec     1.00   653.2±86.72µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/10000                                             1.02      5.4±0.30ms        ? ?/sec     1.00      5.3±0.24ms        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/1                                     1.02   227.8±16.94µs        ? ?/sec     1.00   223.5±19.59µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/10                                    1.00   238.2±17.40µs        ? ?/sec     1.01   240.1±27.49µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/100                                   1.00   348.1±29.94µs        ? ?/sec     1.07   372.1±30.73µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/1000                                  1.00  1277.6±105.32µs        ? ?/sec    1.12  1432.9±113.39µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/10000                                 1.00     10.5±0.58ms        ? ?/sec     1.17     12.2±0.67ms        ? ?/sec
bench_trivial_query/diesel/1                                                              1.00     59.3±5.39µs        ? ?/sec     1.01     59.9±4.02µs        ? ?/sec
bench_trivial_query/diesel/10                                                             1.07     68.1±3.29µs        ? ?/sec     1.00     64.0±4.24µs        ? ?/sec
bench_trivial_query/diesel/100                                                            1.03    122.2±5.30µs        ? ?/sec     1.00   118.2±10.75µs        ? ?/sec
bench_trivial_query/diesel/1000                                                           1.00   605.9±34.08µs        ? ?/sec     1.03   621.3±51.12µs        ? ?/sec
bench_trivial_query/diesel/10000                                                          1.00      5.5±0.30ms        ? ?/sec     1.01      5.6±0.23ms        ? ?/sec
bench_trivial_query/diesel_boxed/1                                                        1.05     63.0±3.45µs        ? ?/sec     1.00     60.1±3.47µs        ? ?/sec
bench_trivial_query/diesel_boxed/10                                                       1.00     66.2±3.85µs        ? ?/sec     1.03     68.5±4.01µs        ? ?/sec
bench_trivial_query/diesel_boxed/100                                                      1.00   118.6±16.26µs        ? ?/sec     1.05   124.9±11.99µs        ? ?/sec
bench_trivial_query/diesel_boxed/1000                                                     1.01   626.1±40.92µs        ? ?/sec     1.00   621.0±37.46µs        ? ?/sec
bench_trivial_query/diesel_boxed/10000                                                    1.00      5.4±0.28ms        ? ?/sec     1.06      5.8±0.38ms        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/1                                            1.00   136.6±10.98µs        ? ?/sec     1.01    137.4±5.61µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/10                                           1.00    137.9±6.76µs        ? ?/sec     1.01    138.6±8.84µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/100                                          1.00   197.4±10.68µs        ? ?/sec     1.09   214.8±13.71µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/1000                                         1.00   682.2±33.94µs        ? ?/sec     1.15   783.7±39.84µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/10000                                        1.00      5.4±0.25ms        ? ?/sec     1.19      6.4±0.36ms        ? ?/sec
Sqlite:
group                                                                                     changes                                master
-----                                                                                     -------                                ------
bench_insert/diesel/1                                                                     1.01      9.1±0.05µs        ? ?/sec    1.00      9.0±0.04µs        ? ?/sec
bench_insert/diesel/10                                                                    1.06     57.6±2.34µs        ? ?/sec    1.00     54.6±1.28µs        ? ?/sec
bench_insert/diesel/100                                                                   1.00    514.5±2.41µs        ? ?/sec    1.00    515.0±2.72µs        ? ?/sec
bench_insert/diesel/25                                                                    1.00    136.5±1.24µs        ? ?/sec    1.01    137.3±1.53µs        ? ?/sec
bench_insert/diesel/50                                                                    1.00    264.2±1.52µs        ? ?/sec    1.00    264.4±1.63µs        ? ?/sec
bench_loading_associations_sequentially/diesel/bench_loading_associations_sequentially    1.06    532.6±2.78µs        ? ?/sec    1.00    500.2±3.52µs        ? ?/sec
bench_medium_complex_query/diesel/1                                                       1.00      3.4±0.05µs        ? ?/sec    1.07      3.7±0.03µs        ? ?/sec
bench_medium_complex_query/diesel/10                                                      1.00      6.1±0.05µs        ? ?/sec    1.02      6.2±0.06µs        ? ?/sec
bench_medium_complex_query/diesel/100                                                     1.03     34.2±0.27µs        ? ?/sec    1.00     33.3±0.21µs        ? ?/sec
bench_medium_complex_query/diesel/1000                                                    1.04    312.2±1.96µs        ? ?/sec    1.00    299.9±2.10µs        ? ?/sec
bench_medium_complex_query/diesel/10000                                                   1.05      3.1±0.02ms        ? ?/sec    1.00      3.0±0.02ms        ? ?/sec
bench_medium_complex_query/diesel_boxed/1                                                 1.00      5.9±0.42µs        ? ?/sec    1.00      5.9±0.28µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/10                                                1.00      8.2±0.10µs        ? ?/sec    1.01      8.3±0.06µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/100                                               1.01     36.2±0.30µs        ? ?/sec    1.00     35.9±0.21µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/1000                                              1.02    316.3±2.21µs        ? ?/sec    1.00    309.9±2.08µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/10000                                             1.02      3.1±0.01ms        ? ?/sec    1.00      3.0±0.02ms        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/1                                     1.17     20.3±0.10µs        ? ?/sec    1.00     17.4±0.10µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/10                                    1.07     24.1±0.19µs        ? ?/sec    1.00     22.5±0.14µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/100                                   1.19     81.7±0.49µs        ? ?/sec    1.00     68.8±0.35µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/1000                                  1.24    658.2±5.11µs        ? ?/sec    1.00    531.5±3.27µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/10000                                 1.26      6.5±0.05ms        ? ?/sec    1.00      5.1±0.04ms        ? ?/sec
bench_trivial_query/diesel/1                                                              1.00   812.7±10.89ns        ? ?/sec    1.12    911.1±6.73ns        ? ?/sec
bench_trivial_query/diesel/10                                                             1.01      3.8±0.04µs        ? ?/sec    1.00      3.8±0.06µs        ? ?/sec
bench_trivial_query/diesel/100                                                            1.05     34.0±0.42µs        ? ?/sec    1.00     32.3±0.62µs        ? ?/sec
bench_trivial_query/diesel/1000                                                           1.09    342.1±4.18µs        ? ?/sec    1.00    312.9±2.47µs        ? ?/sec
bench_trivial_query/diesel/10000                                                          1.09      3.4±0.02ms        ? ?/sec    1.00      3.1±0.01ms        ? ?/sec
bench_trivial_query/diesel_boxed/1                                                        1.00   1595.4±9.29ns        ? ?/sec    1.03  1645.0±26.47ns        ? ?/sec
bench_trivial_query/diesel_boxed/10                                                       1.04      4.6±0.04µs        ? ?/sec    1.00      4.4±0.06µs        ? ?/sec
bench_trivial_query/diesel_boxed/100                                                      1.09     34.7±0.27µs        ? ?/sec    1.00     31.9±0.15µs        ? ?/sec
bench_trivial_query/diesel_boxed/1000                                                     1.11    348.8±6.12µs        ? ?/sec    1.00    314.4±1.51µs        ? ?/sec
bench_trivial_query/diesel_boxed/10000                                                    1.09      3.4±0.03ms        ? ?/sec    1.00      3.1±0.03ms        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/1                                            1.00      5.4±0.05µs        ? ?/sec    1.01      5.5±0.09µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/10                                           1.07      8.7±0.07µs        ? ?/sec    1.00      8.2±0.10µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/100                                          1.21     39.9±0.41µs        ? ?/sec    1.00     33.0±0.28µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/1000                                         1.24    359.8±1.78µs        ? ?/sec    1.00   289.9±26.22µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/10000                                        1.28      3.5±0.01ms        ? ?/sec    1.00      2.8±0.01ms        ? ?/sec
Mysql:
group                                                                                     changes                                 master
-----                                                                                     -------                                 ------
bench_insert/diesel/1                                                                     1.01   718.3±96.91µs        ? ?/sec     1.00   714.2±94.25µs        ? ?/sec
bench_insert/diesel/10                                                                    1.04   862.8±72.87µs        ? ?/sec     1.00  828.3±102.29µs        ? ?/sec
bench_insert/diesel/100                                                                   1.00      2.0±0.12ms        ? ?/sec     1.03      2.1±0.16ms        ? ?/sec
bench_insert/diesel/25                                                                    1.10  1106.8±143.39µs        ? ?/sec    1.00  1007.7±88.46µs        ? ?/sec
bench_insert/diesel/50                                                                    1.00  1423.4±165.37µs        ? ?/sec    1.01  1441.6±191.62µs        ? ?/sec
bench_loading_associations_sequentially/diesel/bench_loading_associations_sequentially    1.00     92.2±4.03ms        ? ?/sec     1.03     94.8±5.33ms        ? ?/sec
bench_medium_complex_query/diesel/1                                                       1.04   103.0±11.69µs        ? ?/sec     1.00     99.0±9.42µs        ? ?/sec
bench_medium_complex_query/diesel/10                                                      1.03   146.4±16.58µs        ? ?/sec     1.00   142.7±15.57µs        ? ?/sec
bench_medium_complex_query/diesel/100                                                     1.04   241.9±27.91µs        ? ?/sec     1.00   232.9±26.16µs        ? ?/sec
bench_medium_complex_query/diesel/1000                                                    1.12  1098.2±191.08µs        ? ?/sec    1.00   980.1±98.75µs        ? ?/sec
bench_medium_complex_query/diesel/10000                                                   1.07      9.3±0.51ms        ? ?/sec     1.00      8.7±0.51ms        ? ?/sec
bench_medium_complex_query/diesel_boxed/1                                                 1.03   103.9±12.31µs        ? ?/sec     1.00   100.8±11.65µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/10                                                1.04   151.0±19.24µs        ? ?/sec     1.00   145.7±16.69µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/100                                               1.08   243.8±38.68µs        ? ?/sec     1.00   225.5±25.55µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/1000                                              1.16  1119.0±166.28µs        ? ?/sec    1.00   963.8±79.69µs        ? ?/sec
bench_medium_complex_query/diesel_boxed/10000                                             1.08      9.3±0.55ms        ? ?/sec     1.00      8.6±0.45ms        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/1                                     1.04   147.2±15.53µs        ? ?/sec     1.00   141.5±13.87µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/10                                    1.07   207.9±20.62µs        ? ?/sec     1.00   193.6±22.22µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/100                                   1.07   330.3±34.14µs        ? ?/sec     1.00   308.5±28.77µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/1000                                  1.01  1439.0±122.89µs        ? ?/sec    1.00  1421.7±116.62µs        ? ?/sec
bench_medium_complex_query/diesel_queryable_by_name/10000                                 1.05     12.9±0.87ms        ? ?/sec     1.00     12.3±0.59ms        ? ?/sec
bench_trivial_query/diesel/1                                                              1.00     53.9±2.94µs        ? ?/sec     1.06     57.4±6.60µs        ? ?/sec
bench_trivial_query/diesel/10                                                             1.01     62.1±5.43µs        ? ?/sec     1.00     61.6±4.37µs        ? ?/sec
bench_trivial_query/diesel/100                                                            1.08    143.8±9.79µs        ? ?/sec     1.00   133.5±11.52µs        ? ?/sec
bench_trivial_query/diesel/1000                                                           1.09   899.8±56.38µs        ? ?/sec     1.00   827.5±61.76µs        ? ?/sec
bench_trivial_query/diesel/10000                                                          1.20      9.0±0.48ms        ? ?/sec     1.00      7.5±0.40ms        ? ?/sec
bench_trivial_query/diesel_boxed/1                                                        1.00     55.8±5.43µs        ? ?/sec     1.05     58.9±4.47µs        ? ?/sec
bench_trivial_query/diesel_boxed/10                                                       1.02     63.6±5.61µs        ? ?/sec     1.00     62.1±5.96µs        ? ?/sec
bench_trivial_query/diesel_boxed/100                                                      1.09    144.6±9.43µs        ? ?/sec     1.00    132.6±9.15µs        ? ?/sec
bench_trivial_query/diesel_boxed/1000                                                     1.12   913.3±70.87µs        ? ?/sec     1.00   815.3±63.91µs        ? ?/sec
bench_trivial_query/diesel_boxed/10000                                                    1.18      8.9±0.49ms        ? ?/sec     1.00      7.5±0.43ms        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/1                                            1.00    107.3±7.62µs        ? ?/sec     1.01   108.0±10.37µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/10                                           1.00    117.2±8.85µs        ? ?/sec     1.00   117.0±58.14µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/100                                          1.04   195.2±18.02µs        ? ?/sec     1.00   187.3±12.88µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/1000                                         1.10   999.1±59.64µs        ? ?/sec     1.00   905.4±46.01µs        ? ?/sec
bench_trivial_query/diesel_queryable_by_name/10000                                        1.05      8.7±0.50ms        ? ?/sec     1.00      8.2±0.52ms        ? ?/sec

* Add tests for backend specific iterator behavior
* Optimize the sqlite implementation
* Fix the mysql implementation to work correctly for cases where someone
stores the row till after the next call to Iterator::next
* Add a `RunQueryDsl::load_iter` method
* Remove unneeded life times from `PgResult` and `MysqlRow`
* Add tests to show that it is possible to have more than one iterator
for `PgConnection`, but not for `SqliteConnection` and `MysqlConnection`
* Fix various broken life time bounds for unsafe code on `PgResult` to
be bound to the result itself
* Copy `MysqlType` by value instead of using a reference
Our normal deserialization workflow does not need the type OID to work,
so we can change the code in such a way that the OID is only received
from the result if the users actually requests it. This should speedup
various benchmarks for `PgConnection` measurably.
@weiznich weiznich force-pushed the feature/load_returns_a_iterator branch from e74d742 to 2dedaa4 Compare September 13, 2021 07:11
This makes it much more understandable what's the type of the return
type, while having a minimal performance cost.
I've opted into applying this change only for this method and not for
`LoadDsl::internal_load` and `Connection::load` as both are not really
user facing. (I would count them as advanced methods most users never see
and never use directly)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
run-benchmarks Used to indicate that github actions should run our benchmark suite
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants