Skip to content

perf: do not create a new parser for each column - #383

Merged
olavloite merged 4 commits into
postgresql-dialectfrom
no-parser-construction
Oct 12, 2022
Merged

olavloite merged 4 commits into
postgresql-dialectfrom
no-parser-construction

Conversation

@olavloite

Copy link
Copy Markdown
Collaborator

Convert a Spanner value directly to the PostgreSQL equivalent without creating a Parser object. This reduces the amount of memory that is allocated and must be garbage collected for each row that is sent to the PostgreSQL client.

Convert a Spanner value directly to the PostgreSQL equivalent without
creating a Parser object. This reduces the amount of memory that is
allocated and must be garbage collected for each row that is sent to
the PostgreSQL client.
@codecov

codecov Bot commented Oct 10, 2022 •

Copy link
Copy Markdown

Codecov Report

Merging #383 (9db6457) into postgresql-dialect (1137ed1) will decrease coverage by 0.16%.
The diff coverage is 73.80%.

@@                   Coverage Diff                    @@
##             postgresql-dialect     #383      +/-   ##
========================================================
- Coverage                 86.41%   86.24%   -0.17%     
- Complexity                 1847     1885      +38     
========================================================
  Files                       122      122              
  Lines                      6064     6129      +65     
  Branches                    838      839       +1     
========================================================
+ Hits                       5240     5286      +46     
- Misses                      592      603      +11     
- Partials                    232      240       +8     
Flag Coverage Δ
all_tests 86.24% <73.80%> (-0.17%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
.../cloud/spanner/pgadapter/parsers/StringParser.java 83.33% <33.33%> (-10.00%) ⬇️
.../cloud/spanner/pgadapter/parsers/BinaryParser.java 78.57% <60.00%> (-4.04%) ⬇️
...le/cloud/spanner/pgadapter/parsers/DateParser.java 87.23% <66.66%> (-3.47%) ⬇️
.../cloud/spanner/pgadapter/parsers/DoubleParser.java 82.35% <66.66%> (-3.86%) ⬇️
...le/cloud/spanner/pgadapter/parsers/LongParser.java 83.33% <66.66%> (-3.77%) ⬇️
...e/cloud/spanner/pgadapter/parsers/JsonbParser.java 91.89% <75.00%> (-4.99%) ⬇️
...cloud/spanner/pgadapter/parsers/BooleanParser.java 90.19% <76.92%> (-4.68%) ⬇️
...oud/spanner/pgadapter/parsers/TimestampParser.java 93.22% <77.77%> (-2.94%) ⬇️
...oogle/cloud/spanner/pgadapter/utils/Converter.java 80.00% <80.00%> (+5.00%) ⬆️
...cloud/spanner/pgadapter/parsers/NumericParser.java 83.78% <81.81%> (-2.43%) ⬇️
... and 3 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more


static {
ByteConverter.bool(TRUE_VALUE_BYTES_BINARY, 0, true);
ByteConverter.bool(FALSE_VALUE_BYTES_BINARY, 0, true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why are we passing true as the third parameter here? Shouldn't it be false?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Great catch, thanks! That's absolutely right, and it was not caught by our tests for two reasons:

  1. Most drivers will never use the binary format for booleans, because it does not really save any network traffic anyways (boolean values in text format are represented by t and f, so they take up just one byte, just as the binary format of 1 and 0)
  2. Our tests mostly used true as the test value, which meant that they did not catch the fact that false was encoded as true.

I've added additional tests that use randomly generated values so we can catch this kind of errors in the future. That testing also turned out to detect a bug in the PostgreSQL JDBC driver, as that driver does not correctly decode binary boolean values. I've filed an issue and a PR for the JDBC driver in their repository for it.


public static byte[] convertToPG(ResultSet resultSet, int position, DataFormat format) {
switch (format) {
case SPANNER:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why haven't we added the conversion logic for Cloud Spanner format for some of the data types?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

In Java, case statements automatically fall through, so here the same logic is used for both when the format is SPANNER and POSTGRESQL_TEXT. This is different from some other programming languages where this would mean that there is no conversion for SPANNER.


public static byte[] convertToPG(ResultSet resultSet, int position, DataFormat format) {
switch (format) {
case SPANNER:

@gauravsnj gauravsnj Oct 11, 2022 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If the conversion to Spanner format is not possible for these data types, can we add some more specific error message rather than falling back to unknown data format?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

(See above)
The default case should not be reachable, but is required for the Java compiler, as it otherwise thinks that there are code paths possible that will not return a value for this method.

@gauravsnj gauravsnj left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM with some small queries

Fix numeric parsing for NaN values.
Fix bool binary parsing (always returned true).
Add tests to verify that we actually receive the values we expect, both
when using text format and when using binary format.
@olavloite
olavloite merged commit 5352f79 into postgresql-dialect Oct 12, 2022
@olavloite
olavloite deleted the no-parser-construction branch October 12, 2022 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants