Skip to content

Avoid unnecessary CompilableProvier castings (#84)#274

Merged
alex-kulakov merged 3 commits intoDataObjects-NET:masterfrom
servicetitan:upstream/CompilableProvider
Jul 26, 2023
Merged

Avoid unnecessary CompilableProvier castings (#84)#274
alex-kulakov merged 3 commits intoDataObjects-NET:masterfrom
servicetitan:upstream/CompilableProvider

Conversation

@SergeiPavlov
Copy link
Copy Markdown
Contributor

No description provided.

@alex-kulakov
Copy link
Copy Markdown
Contributor

Hello, so this is similar to the case in #261, right?

@SergeiPavlov
Copy link
Copy Markdown
Contributor Author

Hello, so this is similar to the case in #261, right?

Not exaclty.
The aim of #265 was to remove common part of each Clone() method for simplification.

This PR avoids explicit type casts

@alex-kulakov
Copy link
Copy Markdown
Contributor

@SergeiPavlov,

With these changes of ProviderVisitor, it is basically the same as CompilableProviderVisitor. No references to ProviderVisitor exist, except for usage of it as base class for CompilableProviderVisitor. This means there is no way to have it as direct base class for something in user code. I'm thinking of merging ProviderVistior and CompilableProviderVisitor.

By the way, some members of CompilableProviderVisitor, for instance, VistitTag, VisitDistinct methods have specific return types instead of general CompilableProvider type. Why? To have advantage of covariant returns we need to call method and work with result directly, without any casts, but I can't see any direct usage of results, moreover, they are casted to CompilableProvider in the Visit method, so cast to base class happens anyway, right?

@SergeiPavlov
Copy link
Copy Markdown
Contributor Author

Right now returning TagProvider form VisitTag(TagProvider provider) is unnecessary, but may be useful in future.
Generally returning subtype is more safe.

Casting to base class is compile-time, so it is free.

@alex-kulakov
Copy link
Copy Markdown
Contributor

But it blocks overriding methods from being able to return something other than provider type of parameter. CompilableProviderVisitor is used in rewriters which may transform tree of providers including change of type of returning instance. If we changed return type of virtual method this opportunity would be closed. It also may be useful for future, and in case of such need of rewriting we would have to change virtual method signature back to base type - CompilableProvider. Not very good for base class. I assume that overriding methods prevented you from declaring all the virtual VisitXxx methods to have exact return types, right?

I would vote for keeping CompilableProvider as return type of virtual methods. I did some benchmarks on dummy providers tree of 200 nodes (only visiting of the tree). Fastest option changes from one to another in some runs but both options are faster than returning Provider.

Method Mean Error StdDev Rank Gen 0 Gen 1 Allocated
ReturnCompilableProviders 3.106 us 0.0110 us 0.0092 us 1 1.6899 0.0229 8 KB
RetrunExactProviders 3.139 us 0.0205 us 0.0191 us 1 1.6899 0.0229 8 KB
RerturnProviders 3.367 us 0.0062 us 0.0048 us 2 1.6899 0.0229 8 KB
Method Mean Error StdDev Rank Gen 0 Gen 1 Allocated
RetrunExactProviders 3.188 us 0.0302 us 0.0268 us 1 1.6899 0.0229 8 KB
ReturnCompilableProviders 3.272 us 0.0245 us 0.0229 us 2 1.6899 0.0229 8 KB
RerturnProviders 3.501 us 0.0216 us 0.0191 us 3 1.6899 0.0229 8 KB

I believe that tells that returning CompilableProvider and having it across the board is good idea overall.

Also, I'm getting rid of ProviderVisitor as base class of visitors and will make a PR to your branch a bit later today.

@SergeiPavlov
Copy link
Copy Markdown
Contributor Author

SergeiPavlov commented Jul 21, 2023

My guess was that every VisitFoo() method returns the same type as its argument, because it is a kind of filter.
Is this statement wrong?

Ok, I've changed return type to CompilableProvider

@alex-kulakov
Copy link
Copy Markdown
Contributor

alex-kulakov commented Jul 24, 2023

My guess was that every VisitFoo() method returns the same type as its argument, because it is a kind of filter.

This is true but mostly for sealed classes, also might be true for some in-between classes. For instance, ColumnMappingInspector does not change structure of Providers tree, but some others may change the tree, optimize it or shrink it. This is why I vote for methods returning CompilableProvider in ComplilableProviderVisitor, because it does not constraint derived types' methods to have exact return type instead of base type.

This is what I did in my changes to this PR, I agreed with you and made children types take advantage of covariant returns where it is possible.
The PR I did servicetitan#134

* Make CompilableProviderVisitor API declaration for provider vistitors

- ProviderVisitor no longer parent type for any other type and [Obsolete]
- ProviderVisitor changes reverted
- CompilableProviderVisitor gets protected Visit method from ProviderVisitor
  and all the summaries coppied; also changes signature of expressionTranslator
  to not allow having Provider as incoming parameter and cause issies.

* Apply covariant returns to CompilableProviderVisitor descendants

* CompilableProviderVisitor: convert IFs to conditionals

* Revert obsolescence of ProviderVisitor
@alex-kulakov alex-kulakov merged commit c41382f into DataObjects-NET:master Jul 26, 2023
SergeiPavlov added a commit to servicetitan/dataobjects-net that referenced this pull request Jul 27, 2023
* Use C#9 Covariant return types feature for Clone() implementation for more type safety

* Make SqlNodeCloneContext readonly struct

* Continue refactoring

* Refactor other Clone()

* Get rid of IsNullReference() in modified lines

* Small optimizations (#74)

* Optimize VisitMethodCall()

* Optimize Provider constructor

* Use Array.Empty<T>() instead of allocating Empty array

* Get rid of unused PriorityQueue<> class

* VisitNullable()

* Avoid unnecessary CompilableProvier castings (#84)

* Update Orm/Xtensive.Orm/Sql/Dml/Expressions/SqlUserFunctionCall.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* Update Orm/Xtensive.Orm/Sql/Dml/Expressions/SqlFunctionCall.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* Update Orm/Xtensive.Orm/Sql/Dml/Expressions/SqlCustomFunctionCall.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* make VisitNullable() private

* ToArray(t.tables.Length) for consistency

* SqlServer: Both US English and British English are considered english

* Improve changelog

* Fix build

* Change version to next developing

* Add changelog file

* After merge changes

- TestHelper.AddValueRow() is for all build targets
- SqlSessionHandler: shared code for async and sync Execute + renames
- TemporaryTableManager: removed unused code
- CommandFactory: removed commented code
- DomainConfuguration: fixed bug of MaxNumberOfConditions value not being
  validated (added tests to make sure that validation happens)
- Test for temp table popupation
- Updated MaxQueryParameterCount for Oracle and PostgreSQL 9.0+

* Add new storage configurations + enrich supported databases list

* Fixed bad merge results

* Remove usage of obsolete SqlInsert.Values from object cloning

* Changelog improved

* Update Orm/Xtensive.Orm/Sql/Internals/SqlNodeCloneContext.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* Fix SqlTruncateTable.Clone()

* Fix build

* Refactor SqlInsert.Clone()

* Changelog improved

* Return CompilableProvider from Visitors

* Proposes changes on top of DataObjects-NET#274 (#134)

* Make CompilableProviderVisitor API declaration for provider vistitors

- ProviderVisitor no longer parent type for any other type and [Obsolete]
- ProviderVisitor changes reverted
- CompilableProviderVisitor gets protected Visit method from ProviderVisitor
  and all the summaries coppied; also changes signature of expressionTranslator
  to not allow having Provider as incoming parameter and cause issies.

* Apply covariant returns to CompilableProviderVisitor descendants

* CompilableProviderVisitor: convert IFs to conditionals

* Revert obsolescence of ProviderVisitor

---------

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>
SergeiPavlov added a commit to servicetitan/dataobjects-net that referenced this pull request Jul 27, 2023
* Use C#9 Covariant return types feature for Clone() implementation for more type safety

* Make SqlNodeCloneContext readonly struct

* Continue refactoring

* Refactor other Clone()

* Get rid of IsNullReference() in modified lines

* Small optimizations (#74)

* Optimize VisitMethodCall()

* Optimize Provider constructor

* Use Array.Empty<T>() instead of allocating Empty array

* Get rid of unused PriorityQueue<> class

* VisitNullable()

* Avoid unnecessary CompilableProvier castings (#84)

* Fix hinding exception & StackTrace in OpenSessionInternalAsync()

* Flatten AggregateException with single inner exception

* Update Orm/Xtensive.Orm/Sql/Dml/Expressions/SqlUserFunctionCall.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* Update Orm/Xtensive.Orm/Sql/Dml/Expressions/SqlFunctionCall.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* Update Orm/Xtensive.Orm/Sql/Dml/Expressions/SqlCustomFunctionCall.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* make VisitNullable() private

* ToArray(t.tables.Length) for consistency

* SqlServer: Both US English and British English are considered english

* Improve changelog

* Fix build

* Change version to next developing

* Add changelog file

* After merge changes

- TestHelper.AddValueRow() is for all build targets
- SqlSessionHandler: shared code for async and sync Execute + renames
- TemporaryTableManager: removed unused code
- CommandFactory: removed commented code
- DomainConfuguration: fixed bug of MaxNumberOfConditions value not being
  validated (added tests to make sure that validation happens)
- Test for temp table popupation
- Updated MaxQueryParameterCount for Oracle and PostgreSQL 9.0+

* Add new storage configurations + enrich supported databases list

* Fixed bad merge results

* Remove usage of obsolete SqlInsert.Values from object cloning

* Changelog improved

* Update Orm/Xtensive.Orm/Sql/Internals/SqlNodeCloneContext.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* Fix SqlTruncateTable.Clone()

* Fix build

* Refactor SqlInsert.Clone()

* Changelog improved

* Return CompilableProvider from Visitors

* Proposes changes on top of DataObjects-NET#274 (#134)

* Make CompilableProviderVisitor API declaration for provider vistitors

- ProviderVisitor no longer parent type for any other type and [Obsolete]
- ProviderVisitor changes reverted
- CompilableProviderVisitor gets protected Visit method from ProviderVisitor
  and all the summaries coppied; also changes signature of expressionTranslator
  to not allow having Provider as incoming parameter and cause issies.

* Apply covariant returns to CompilableProviderVisitor descendants

* CompilableProviderVisitor: convert IFs to conditionals

* Revert obsolescence of ProviderVisitor

* Improve changelog

---------

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>
SergeiPavlov added a commit to servicetitan/dataobjects-net that referenced this pull request Jul 28, 2023
* Use C#9 Covariant return types feature for Clone() implementation for more type safety

* Make SqlNodeCloneContext readonly struct

* Continue refactoring

* Refactor other Clone()

* Get rid of IsNullReference() in modified lines

* Small optimizations (#74)

* Optimize VisitMethodCall()

* Optimize Provider constructor

* Use Array.Empty<T>() instead of allocating Empty array

* Get rid of unused PriorityQueue<> class

* VisitNullable()

* Avoid unnecessary CompilableProvier castings (#84)

* Avoid unnecessary CompilableProvier castings (#84)

* Refactor ProviderVisitor to avoid code duplication (#86)

* Fix hinding exception & StackTrace in OpenSessionInternalAsync()

* Flatten AggregateException with single inner exception

* Update Orm/Xtensive.Orm/Sql/Dml/Expressions/SqlUserFunctionCall.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* Update Orm/Xtensive.Orm/Sql/Dml/Expressions/SqlFunctionCall.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* Update Orm/Xtensive.Orm/Sql/Dml/Expressions/SqlCustomFunctionCall.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* make VisitNullable() private

* ToArray(t.tables.Length) for consistency

* SqlServer: Both US English and British English are considered english

* Improve changelog

* Fix build

* Change version to next developing

* Add changelog file

* After merge changes

- TestHelper.AddValueRow() is for all build targets
- SqlSessionHandler: shared code for async and sync Execute + renames
- TemporaryTableManager: removed unused code
- CommandFactory: removed commented code
- DomainConfuguration: fixed bug of MaxNumberOfConditions value not being
  validated (added tests to make sure that validation happens)
- Test for temp table popupation
- Updated MaxQueryParameterCount for Oracle and PostgreSQL 9.0+

* Add new storage configurations + enrich supported databases list

* Fixed bad merge results

* Remove usage of obsolete SqlInsert.Values from object cloning

* Changelog improved

* Update Orm/Xtensive.Orm/Sql/Internals/SqlNodeCloneContext.cs

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>

* Fix SqlTruncateTable.Clone()

* Fix build

* Refactor SqlInsert.Clone()

* Changelog improved

* Return CompilableProvider from Visitors

* Proposes changes on top of DataObjects-NET#274 (#134)

* Make CompilableProviderVisitor API declaration for provider vistitors

- ProviderVisitor no longer parent type for any other type and [Obsolete]
- ProviderVisitor changes reverted
- CompilableProviderVisitor gets protected Visit method from ProviderVisitor
  and all the summaries coppied; also changes signature of expressionTranslator
  to not allow having Provider as incoming parameter and cause issies.

* Apply covariant returns to CompilableProviderVisitor descendants

* CompilableProviderVisitor: convert IFs to conditionals

* Revert obsolescence of ProviderVisitor

* Improve changelog

* After-merge fix

* Prevent continuation happening if parent task was canceled

otherwise OperationCanceledException will be swallowed

---------

Co-authored-by: Alexey Kulakov <alexey.kulakov@dataobjects.net>
@SergeiPavlov SergeiPavlov deleted the upstream/CompilableProvider branch August 18, 2023 21:26
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