Why are interface projections much slower than constructor projections and entity projections in Spring Data...
I've been wondering which kind of projections should I use, so I did a little test, which covered 5 types of projections (based on docs: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections):
1. Entity projection
This is just a standard findAll()
provided by Spring Data repository. Nothing fancy here.
Service:
List<SampleEntity> projections = sampleRepository.findAll();
Entity:
@Entity
@Table(name = "SAMPLE_ENTITIES")
public class SampleEntity {
@Id
private Long id;
private String name;
private String city;
private Integer age;
}
2. Constructor projection
Service:
List<NameOnlyDTO> projections = sampleRepository.findAllNameOnlyConstructorProjection();
Repository:
@Query("select new path.to.dto.NameOnlyDTO(e.name) from SampleEntity e")
List<NameOnlyDTO> findAllNameOnlyConstructorProjection();
Data transfer object:
@NoArgsConstructor
@AllArgsConstructor
public class NameOnlyDTO {
private String name;
}
3. Interface projection
Service:
List<NameOnly> projections = sampleRepository.findAllNameOnlyBy();
Repository:
List<NameOnly> findAllNameOnlyBy();
Interface:
public interface NameOnly {
String getName();
}
4. Tuple projection
Service:
List<Tuple> projections = sampleRepository.findAllNameOnlyTupleProjection();
Repository:
@Query("select e.name as name from SampleEntity e")
List<Tuple> findAllNameOnlyTupleProjection();
5. Dynamic projection
Service:
List<DynamicProjectionDTO> projections = sampleRepository.findAllBy(DynamicProjectionDTO.class);
Repository:
<T> List<T> findAllBy(Class<T> type);
Data transfer object:
public class DynamicProjectionDTO {
private String name;
public DynamicProjectionDTO(String name) {
this.name = name;
}
}
Some additional info:
The project was built using gradle spring boot plugin (version 2.0.4), which uses Spring 5.0.8 under the hood. Database: H2 in memory.
Results:
Entity projections took 161.61 ms on average out of 100 iterations.
Constructor projections took 24.84 ms on average out of 100 iterations.
Interface projections took 252.26 ms on average out of 100 iterations.
Tuple projections took 21.41 ms on average out of 100 iterations.
Dynamic projections took 23.62 ms on average out of 100 iterations.
-----------------------------------------------------------------------
One iteration retrieved (from DB) and projected 100 000 objects.
-----------------------------------------------------------------------
Notes:
It is understandable that retrieving entities takes some time. Hibernate tracks these objects for changes, lazy loading and so on.
Constructor projections are really fast and have no limitations on the DTO side, but require manual object creation in @Query
annotation.
Interface projections turned out to be really slow. See question.
Tuple projections were the fastest, but are not the most convinient to play with. They need an alias in JPQL and the data has to be retrieved by calling .get("name")
instead of .getName()
.
Dynamic projections look pretty cool and fast, but must have exactly one constructor. No more, no less. Otherwise Spring Data throws an exception, because it doesn't know which one to use (it takes constructor parameters to determine which data to retrieve from DB).
Question:
Why interface projections take longer than retrieving entities? Each interface projection returned is actually a proxy. Is it so expensive to create that proxy? If so, doesn't it defeat the main purpose of projections (since they are meant to be faster than entities)? Other projections look awesome tho. I would really love some insight on this. Thank you.
EDIT :
Here is the test repository: https://github.com/aurora-software-ks/spring-boot-projections-test in case you want to run it yourself. It is very easy to set up. Readme contains everything you need to know.
spring performance hibernate spring-data-jpa projection
|
show 6 more comments
I've been wondering which kind of projections should I use, so I did a little test, which covered 5 types of projections (based on docs: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections):
1. Entity projection
This is just a standard findAll()
provided by Spring Data repository. Nothing fancy here.
Service:
List<SampleEntity> projections = sampleRepository.findAll();
Entity:
@Entity
@Table(name = "SAMPLE_ENTITIES")
public class SampleEntity {
@Id
private Long id;
private String name;
private String city;
private Integer age;
}
2. Constructor projection
Service:
List<NameOnlyDTO> projections = sampleRepository.findAllNameOnlyConstructorProjection();
Repository:
@Query("select new path.to.dto.NameOnlyDTO(e.name) from SampleEntity e")
List<NameOnlyDTO> findAllNameOnlyConstructorProjection();
Data transfer object:
@NoArgsConstructor
@AllArgsConstructor
public class NameOnlyDTO {
private String name;
}
3. Interface projection
Service:
List<NameOnly> projections = sampleRepository.findAllNameOnlyBy();
Repository:
List<NameOnly> findAllNameOnlyBy();
Interface:
public interface NameOnly {
String getName();
}
4. Tuple projection
Service:
List<Tuple> projections = sampleRepository.findAllNameOnlyTupleProjection();
Repository:
@Query("select e.name as name from SampleEntity e")
List<Tuple> findAllNameOnlyTupleProjection();
5. Dynamic projection
Service:
List<DynamicProjectionDTO> projections = sampleRepository.findAllBy(DynamicProjectionDTO.class);
Repository:
<T> List<T> findAllBy(Class<T> type);
Data transfer object:
public class DynamicProjectionDTO {
private String name;
public DynamicProjectionDTO(String name) {
this.name = name;
}
}
Some additional info:
The project was built using gradle spring boot plugin (version 2.0.4), which uses Spring 5.0.8 under the hood. Database: H2 in memory.
Results:
Entity projections took 161.61 ms on average out of 100 iterations.
Constructor projections took 24.84 ms on average out of 100 iterations.
Interface projections took 252.26 ms on average out of 100 iterations.
Tuple projections took 21.41 ms on average out of 100 iterations.
Dynamic projections took 23.62 ms on average out of 100 iterations.
-----------------------------------------------------------------------
One iteration retrieved (from DB) and projected 100 000 objects.
-----------------------------------------------------------------------
Notes:
It is understandable that retrieving entities takes some time. Hibernate tracks these objects for changes, lazy loading and so on.
Constructor projections are really fast and have no limitations on the DTO side, but require manual object creation in @Query
annotation.
Interface projections turned out to be really slow. See question.
Tuple projections were the fastest, but are not the most convinient to play with. They need an alias in JPQL and the data has to be retrieved by calling .get("name")
instead of .getName()
.
Dynamic projections look pretty cool and fast, but must have exactly one constructor. No more, no less. Otherwise Spring Data throws an exception, because it doesn't know which one to use (it takes constructor parameters to determine which data to retrieve from DB).
Question:
Why interface projections take longer than retrieving entities? Each interface projection returned is actually a proxy. Is it so expensive to create that proxy? If so, doesn't it defeat the main purpose of projections (since they are meant to be faster than entities)? Other projections look awesome tho. I would really love some insight on this. Thank you.
EDIT :
Here is the test repository: https://github.com/aurora-software-ks/spring-boot-projections-test in case you want to run it yourself. It is very easy to set up. Readme contains everything you need to know.
spring performance hibernate spring-data-jpa projection
So you are worrying about 2.5ms for retrieving 100000 objects in a method call which takes probably about 300ms. Also make sure you are running a proper test (with warm-up iterations etc. etc.). And run each test individually (not 1 test with multiple testcases but a sperate test, including loading of JVM etc. etc.). But as they are proxies and are wrapped around the entity I would suspect that they are indeed slower then the entity. However all in all feels like pre-mature optimization.
– M. Deinum
Nov 17 '18 at 15:45
Hey, thanks for the comment. This test has been done after the warm-up iterations. It is not a unit test, it was conducted after fully starting up the project, warming it up by performing this call a couple of times and then calling it once again to test the projections. The results were all almost identical tho. Also it is not about 2.5 ms. One iteration (projecting 100 000 objects) takes 252 ms on average out of 100 tries. Using a real business logic with relations, multiple calls and other stuff would probably make it even slower. This test is merely to figure out which ones are better.
– Sikor
Nov 17 '18 at 16:01
Any chance of making those tests available? Maybe even as a pull request?
– Jens Schauder
Nov 18 '18 at 4:52
@JensSchauder Sure. I will do it in a few hours because I am not at home right now. I will create a public repo and let you know about it in the next comment. Thanks for taking interest in this.
– Sikor
Nov 18 '18 at 11:51
No hurry, it will take some time until I'll be able to look into this.
– Jens Schauder
Nov 18 '18 at 12:44
|
show 6 more comments
I've been wondering which kind of projections should I use, so I did a little test, which covered 5 types of projections (based on docs: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections):
1. Entity projection
This is just a standard findAll()
provided by Spring Data repository. Nothing fancy here.
Service:
List<SampleEntity> projections = sampleRepository.findAll();
Entity:
@Entity
@Table(name = "SAMPLE_ENTITIES")
public class SampleEntity {
@Id
private Long id;
private String name;
private String city;
private Integer age;
}
2. Constructor projection
Service:
List<NameOnlyDTO> projections = sampleRepository.findAllNameOnlyConstructorProjection();
Repository:
@Query("select new path.to.dto.NameOnlyDTO(e.name) from SampleEntity e")
List<NameOnlyDTO> findAllNameOnlyConstructorProjection();
Data transfer object:
@NoArgsConstructor
@AllArgsConstructor
public class NameOnlyDTO {
private String name;
}
3. Interface projection
Service:
List<NameOnly> projections = sampleRepository.findAllNameOnlyBy();
Repository:
List<NameOnly> findAllNameOnlyBy();
Interface:
public interface NameOnly {
String getName();
}
4. Tuple projection
Service:
List<Tuple> projections = sampleRepository.findAllNameOnlyTupleProjection();
Repository:
@Query("select e.name as name from SampleEntity e")
List<Tuple> findAllNameOnlyTupleProjection();
5. Dynamic projection
Service:
List<DynamicProjectionDTO> projections = sampleRepository.findAllBy(DynamicProjectionDTO.class);
Repository:
<T> List<T> findAllBy(Class<T> type);
Data transfer object:
public class DynamicProjectionDTO {
private String name;
public DynamicProjectionDTO(String name) {
this.name = name;
}
}
Some additional info:
The project was built using gradle spring boot plugin (version 2.0.4), which uses Spring 5.0.8 under the hood. Database: H2 in memory.
Results:
Entity projections took 161.61 ms on average out of 100 iterations.
Constructor projections took 24.84 ms on average out of 100 iterations.
Interface projections took 252.26 ms on average out of 100 iterations.
Tuple projections took 21.41 ms on average out of 100 iterations.
Dynamic projections took 23.62 ms on average out of 100 iterations.
-----------------------------------------------------------------------
One iteration retrieved (from DB) and projected 100 000 objects.
-----------------------------------------------------------------------
Notes:
It is understandable that retrieving entities takes some time. Hibernate tracks these objects for changes, lazy loading and so on.
Constructor projections are really fast and have no limitations on the DTO side, but require manual object creation in @Query
annotation.
Interface projections turned out to be really slow. See question.
Tuple projections were the fastest, but are not the most convinient to play with. They need an alias in JPQL and the data has to be retrieved by calling .get("name")
instead of .getName()
.
Dynamic projections look pretty cool and fast, but must have exactly one constructor. No more, no less. Otherwise Spring Data throws an exception, because it doesn't know which one to use (it takes constructor parameters to determine which data to retrieve from DB).
Question:
Why interface projections take longer than retrieving entities? Each interface projection returned is actually a proxy. Is it so expensive to create that proxy? If so, doesn't it defeat the main purpose of projections (since they are meant to be faster than entities)? Other projections look awesome tho. I would really love some insight on this. Thank you.
EDIT :
Here is the test repository: https://github.com/aurora-software-ks/spring-boot-projections-test in case you want to run it yourself. It is very easy to set up. Readme contains everything you need to know.
spring performance hibernate spring-data-jpa projection
I've been wondering which kind of projections should I use, so I did a little test, which covered 5 types of projections (based on docs: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections):
1. Entity projection
This is just a standard findAll()
provided by Spring Data repository. Nothing fancy here.
Service:
List<SampleEntity> projections = sampleRepository.findAll();
Entity:
@Entity
@Table(name = "SAMPLE_ENTITIES")
public class SampleEntity {
@Id
private Long id;
private String name;
private String city;
private Integer age;
}
2. Constructor projection
Service:
List<NameOnlyDTO> projections = sampleRepository.findAllNameOnlyConstructorProjection();
Repository:
@Query("select new path.to.dto.NameOnlyDTO(e.name) from SampleEntity e")
List<NameOnlyDTO> findAllNameOnlyConstructorProjection();
Data transfer object:
@NoArgsConstructor
@AllArgsConstructor
public class NameOnlyDTO {
private String name;
}
3. Interface projection
Service:
List<NameOnly> projections = sampleRepository.findAllNameOnlyBy();
Repository:
List<NameOnly> findAllNameOnlyBy();
Interface:
public interface NameOnly {
String getName();
}
4. Tuple projection
Service:
List<Tuple> projections = sampleRepository.findAllNameOnlyTupleProjection();
Repository:
@Query("select e.name as name from SampleEntity e")
List<Tuple> findAllNameOnlyTupleProjection();
5. Dynamic projection
Service:
List<DynamicProjectionDTO> projections = sampleRepository.findAllBy(DynamicProjectionDTO.class);
Repository:
<T> List<T> findAllBy(Class<T> type);
Data transfer object:
public class DynamicProjectionDTO {
private String name;
public DynamicProjectionDTO(String name) {
this.name = name;
}
}
Some additional info:
The project was built using gradle spring boot plugin (version 2.0.4), which uses Spring 5.0.8 under the hood. Database: H2 in memory.
Results:
Entity projections took 161.61 ms on average out of 100 iterations.
Constructor projections took 24.84 ms on average out of 100 iterations.
Interface projections took 252.26 ms on average out of 100 iterations.
Tuple projections took 21.41 ms on average out of 100 iterations.
Dynamic projections took 23.62 ms on average out of 100 iterations.
-----------------------------------------------------------------------
One iteration retrieved (from DB) and projected 100 000 objects.
-----------------------------------------------------------------------
Notes:
It is understandable that retrieving entities takes some time. Hibernate tracks these objects for changes, lazy loading and so on.
Constructor projections are really fast and have no limitations on the DTO side, but require manual object creation in @Query
annotation.
Interface projections turned out to be really slow. See question.
Tuple projections were the fastest, but are not the most convinient to play with. They need an alias in JPQL and the data has to be retrieved by calling .get("name")
instead of .getName()
.
Dynamic projections look pretty cool and fast, but must have exactly one constructor. No more, no less. Otherwise Spring Data throws an exception, because it doesn't know which one to use (it takes constructor parameters to determine which data to retrieve from DB).
Question:
Why interface projections take longer than retrieving entities? Each interface projection returned is actually a proxy. Is it so expensive to create that proxy? If so, doesn't it defeat the main purpose of projections (since they are meant to be faster than entities)? Other projections look awesome tho. I would really love some insight on this. Thank you.
EDIT :
Here is the test repository: https://github.com/aurora-software-ks/spring-boot-projections-test in case you want to run it yourself. It is very easy to set up. Readme contains everything you need to know.
spring performance hibernate spring-data-jpa projection
spring performance hibernate spring-data-jpa projection
edited Nov 25 '18 at 19:17
Sikor
asked Nov 17 '18 at 0:29
SikorSikor
5,25331632
5,25331632
So you are worrying about 2.5ms for retrieving 100000 objects in a method call which takes probably about 300ms. Also make sure you are running a proper test (with warm-up iterations etc. etc.). And run each test individually (not 1 test with multiple testcases but a sperate test, including loading of JVM etc. etc.). But as they are proxies and are wrapped around the entity I would suspect that they are indeed slower then the entity. However all in all feels like pre-mature optimization.
– M. Deinum
Nov 17 '18 at 15:45
Hey, thanks for the comment. This test has been done after the warm-up iterations. It is not a unit test, it was conducted after fully starting up the project, warming it up by performing this call a couple of times and then calling it once again to test the projections. The results were all almost identical tho. Also it is not about 2.5 ms. One iteration (projecting 100 000 objects) takes 252 ms on average out of 100 tries. Using a real business logic with relations, multiple calls and other stuff would probably make it even slower. This test is merely to figure out which ones are better.
– Sikor
Nov 17 '18 at 16:01
Any chance of making those tests available? Maybe even as a pull request?
– Jens Schauder
Nov 18 '18 at 4:52
@JensSchauder Sure. I will do it in a few hours because I am not at home right now. I will create a public repo and let you know about it in the next comment. Thanks for taking interest in this.
– Sikor
Nov 18 '18 at 11:51
No hurry, it will take some time until I'll be able to look into this.
– Jens Schauder
Nov 18 '18 at 12:44
|
show 6 more comments
So you are worrying about 2.5ms for retrieving 100000 objects in a method call which takes probably about 300ms. Also make sure you are running a proper test (with warm-up iterations etc. etc.). And run each test individually (not 1 test with multiple testcases but a sperate test, including loading of JVM etc. etc.). But as they are proxies and are wrapped around the entity I would suspect that they are indeed slower then the entity. However all in all feels like pre-mature optimization.
– M. Deinum
Nov 17 '18 at 15:45
Hey, thanks for the comment. This test has been done after the warm-up iterations. It is not a unit test, it was conducted after fully starting up the project, warming it up by performing this call a couple of times and then calling it once again to test the projections. The results were all almost identical tho. Also it is not about 2.5 ms. One iteration (projecting 100 000 objects) takes 252 ms on average out of 100 tries. Using a real business logic with relations, multiple calls and other stuff would probably make it even slower. This test is merely to figure out which ones are better.
– Sikor
Nov 17 '18 at 16:01
Any chance of making those tests available? Maybe even as a pull request?
– Jens Schauder
Nov 18 '18 at 4:52
@JensSchauder Sure. I will do it in a few hours because I am not at home right now. I will create a public repo and let you know about it in the next comment. Thanks for taking interest in this.
– Sikor
Nov 18 '18 at 11:51
No hurry, it will take some time until I'll be able to look into this.
– Jens Schauder
Nov 18 '18 at 12:44
So you are worrying about 2.5ms for retrieving 100000 objects in a method call which takes probably about 300ms. Also make sure you are running a proper test (with warm-up iterations etc. etc.). And run each test individually (not 1 test with multiple testcases but a sperate test, including loading of JVM etc. etc.). But as they are proxies and are wrapped around the entity I would suspect that they are indeed slower then the entity. However all in all feels like pre-mature optimization.
– M. Deinum
Nov 17 '18 at 15:45
So you are worrying about 2.5ms for retrieving 100000 objects in a method call which takes probably about 300ms. Also make sure you are running a proper test (with warm-up iterations etc. etc.). And run each test individually (not 1 test with multiple testcases but a sperate test, including loading of JVM etc. etc.). But as they are proxies and are wrapped around the entity I would suspect that they are indeed slower then the entity. However all in all feels like pre-mature optimization.
– M. Deinum
Nov 17 '18 at 15:45
Hey, thanks for the comment. This test has been done after the warm-up iterations. It is not a unit test, it was conducted after fully starting up the project, warming it up by performing this call a couple of times and then calling it once again to test the projections. The results were all almost identical tho. Also it is not about 2.5 ms. One iteration (projecting 100 000 objects) takes 252 ms on average out of 100 tries. Using a real business logic with relations, multiple calls and other stuff would probably make it even slower. This test is merely to figure out which ones are better.
– Sikor
Nov 17 '18 at 16:01
Hey, thanks for the comment. This test has been done after the warm-up iterations. It is not a unit test, it was conducted after fully starting up the project, warming it up by performing this call a couple of times and then calling it once again to test the projections. The results were all almost identical tho. Also it is not about 2.5 ms. One iteration (projecting 100 000 objects) takes 252 ms on average out of 100 tries. Using a real business logic with relations, multiple calls and other stuff would probably make it even slower. This test is merely to figure out which ones are better.
– Sikor
Nov 17 '18 at 16:01
Any chance of making those tests available? Maybe even as a pull request?
– Jens Schauder
Nov 18 '18 at 4:52
Any chance of making those tests available? Maybe even as a pull request?
– Jens Schauder
Nov 18 '18 at 4:52
@JensSchauder Sure. I will do it in a few hours because I am not at home right now. I will create a public repo and let you know about it in the next comment. Thanks for taking interest in this.
– Sikor
Nov 18 '18 at 11:51
@JensSchauder Sure. I will do it in a few hours because I am not at home right now. I will create a public repo and let you know about it in the next comment. Thanks for taking interest in this.
– Sikor
Nov 18 '18 at 11:51
No hurry, it will take some time until I'll be able to look into this.
– Jens Schauder
Nov 18 '18 at 12:44
No hurry, it will take some time until I'll be able to look into this.
– Jens Schauder
Nov 18 '18 at 12:44
|
show 6 more comments
1 Answer
1
active
oldest
votes
I experienced similar behavior with an older version of Spring Data and this was my take on it: https://blog.arnoldgalovics.com/how-much-projections-can-help/
I had a talk with Oliver Gierke (Spring Data lead) and he made some improvements (that's why you get so "good" results :-) ) but basically there will be always a cost on having abstractions vs coding it manually.
This is a trade-off as everything else is. On one hand you got flexibility, easier development, less maintenance (hopefully), on the other hand you get full control, a bit uglier query model.
Hey, thanks for answering. I've read your article and yeah, it looks like the same "issue". Anyway, I'd rather prefer full control or just use dynamic projections with 1 constructor than having such times. So this behaviour is more or less intended right? If so, I believe there should be a mention in the documentation that these kind of projections are the slowest and even slower than retrieving entities, because people mainly use it to improve performance.
– Sikor
Dec 2 '18 at 10:48
I mean yeah, using more level of abstraction don't come without cost so it is completely expected. Personally I wouldn't put it into the docs for one reason, the main purpose of using Spring Data is to get started quickly and cover general use-cases. As soon as you want to have the best possible performance, you have to get rid of the abstractions anyway.
– galovics
Dec 2 '18 at 14:09
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53347063%2fwhy-are-interface-projections-much-slower-than-constructor-projections-and-entit%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I experienced similar behavior with an older version of Spring Data and this was my take on it: https://blog.arnoldgalovics.com/how-much-projections-can-help/
I had a talk with Oliver Gierke (Spring Data lead) and he made some improvements (that's why you get so "good" results :-) ) but basically there will be always a cost on having abstractions vs coding it manually.
This is a trade-off as everything else is. On one hand you got flexibility, easier development, less maintenance (hopefully), on the other hand you get full control, a bit uglier query model.
Hey, thanks for answering. I've read your article and yeah, it looks like the same "issue". Anyway, I'd rather prefer full control or just use dynamic projections with 1 constructor than having such times. So this behaviour is more or less intended right? If so, I believe there should be a mention in the documentation that these kind of projections are the slowest and even slower than retrieving entities, because people mainly use it to improve performance.
– Sikor
Dec 2 '18 at 10:48
I mean yeah, using more level of abstraction don't come without cost so it is completely expected. Personally I wouldn't put it into the docs for one reason, the main purpose of using Spring Data is to get started quickly and cover general use-cases. As soon as you want to have the best possible performance, you have to get rid of the abstractions anyway.
– galovics
Dec 2 '18 at 14:09
add a comment |
I experienced similar behavior with an older version of Spring Data and this was my take on it: https://blog.arnoldgalovics.com/how-much-projections-can-help/
I had a talk with Oliver Gierke (Spring Data lead) and he made some improvements (that's why you get so "good" results :-) ) but basically there will be always a cost on having abstractions vs coding it manually.
This is a trade-off as everything else is. On one hand you got flexibility, easier development, less maintenance (hopefully), on the other hand you get full control, a bit uglier query model.
Hey, thanks for answering. I've read your article and yeah, it looks like the same "issue". Anyway, I'd rather prefer full control or just use dynamic projections with 1 constructor than having such times. So this behaviour is more or less intended right? If so, I believe there should be a mention in the documentation that these kind of projections are the slowest and even slower than retrieving entities, because people mainly use it to improve performance.
– Sikor
Dec 2 '18 at 10:48
I mean yeah, using more level of abstraction don't come without cost so it is completely expected. Personally I wouldn't put it into the docs for one reason, the main purpose of using Spring Data is to get started quickly and cover general use-cases. As soon as you want to have the best possible performance, you have to get rid of the abstractions anyway.
– galovics
Dec 2 '18 at 14:09
add a comment |
I experienced similar behavior with an older version of Spring Data and this was my take on it: https://blog.arnoldgalovics.com/how-much-projections-can-help/
I had a talk with Oliver Gierke (Spring Data lead) and he made some improvements (that's why you get so "good" results :-) ) but basically there will be always a cost on having abstractions vs coding it manually.
This is a trade-off as everything else is. On one hand you got flexibility, easier development, less maintenance (hopefully), on the other hand you get full control, a bit uglier query model.
I experienced similar behavior with an older version of Spring Data and this was my take on it: https://blog.arnoldgalovics.com/how-much-projections-can-help/
I had a talk with Oliver Gierke (Spring Data lead) and he made some improvements (that's why you get so "good" results :-) ) but basically there will be always a cost on having abstractions vs coding it manually.
This is a trade-off as everything else is. On one hand you got flexibility, easier development, less maintenance (hopefully), on the other hand you get full control, a bit uglier query model.
answered Dec 1 '18 at 12:01
galovicsgalovics
2,29931121
2,29931121
Hey, thanks for answering. I've read your article and yeah, it looks like the same "issue". Anyway, I'd rather prefer full control or just use dynamic projections with 1 constructor than having such times. So this behaviour is more or less intended right? If so, I believe there should be a mention in the documentation that these kind of projections are the slowest and even slower than retrieving entities, because people mainly use it to improve performance.
– Sikor
Dec 2 '18 at 10:48
I mean yeah, using more level of abstraction don't come without cost so it is completely expected. Personally I wouldn't put it into the docs for one reason, the main purpose of using Spring Data is to get started quickly and cover general use-cases. As soon as you want to have the best possible performance, you have to get rid of the abstractions anyway.
– galovics
Dec 2 '18 at 14:09
add a comment |
Hey, thanks for answering. I've read your article and yeah, it looks like the same "issue". Anyway, I'd rather prefer full control or just use dynamic projections with 1 constructor than having such times. So this behaviour is more or less intended right? If so, I believe there should be a mention in the documentation that these kind of projections are the slowest and even slower than retrieving entities, because people mainly use it to improve performance.
– Sikor
Dec 2 '18 at 10:48
I mean yeah, using more level of abstraction don't come without cost so it is completely expected. Personally I wouldn't put it into the docs for one reason, the main purpose of using Spring Data is to get started quickly and cover general use-cases. As soon as you want to have the best possible performance, you have to get rid of the abstractions anyway.
– galovics
Dec 2 '18 at 14:09
Hey, thanks for answering. I've read your article and yeah, it looks like the same "issue". Anyway, I'd rather prefer full control or just use dynamic projections with 1 constructor than having such times. So this behaviour is more or less intended right? If so, I believe there should be a mention in the documentation that these kind of projections are the slowest and even slower than retrieving entities, because people mainly use it to improve performance.
– Sikor
Dec 2 '18 at 10:48
Hey, thanks for answering. I've read your article and yeah, it looks like the same "issue". Anyway, I'd rather prefer full control or just use dynamic projections with 1 constructor than having such times. So this behaviour is more or less intended right? If so, I believe there should be a mention in the documentation that these kind of projections are the slowest and even slower than retrieving entities, because people mainly use it to improve performance.
– Sikor
Dec 2 '18 at 10:48
I mean yeah, using more level of abstraction don't come without cost so it is completely expected. Personally I wouldn't put it into the docs for one reason, the main purpose of using Spring Data is to get started quickly and cover general use-cases. As soon as you want to have the best possible performance, you have to get rid of the abstractions anyway.
– galovics
Dec 2 '18 at 14:09
I mean yeah, using more level of abstraction don't come without cost so it is completely expected. Personally I wouldn't put it into the docs for one reason, the main purpose of using Spring Data is to get started quickly and cover general use-cases. As soon as you want to have the best possible performance, you have to get rid of the abstractions anyway.
– galovics
Dec 2 '18 at 14:09
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53347063%2fwhy-are-interface-projections-much-slower-than-constructor-projections-and-entit%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
So you are worrying about 2.5ms for retrieving 100000 objects in a method call which takes probably about 300ms. Also make sure you are running a proper test (with warm-up iterations etc. etc.). And run each test individually (not 1 test with multiple testcases but a sperate test, including loading of JVM etc. etc.). But as they are proxies and are wrapped around the entity I would suspect that they are indeed slower then the entity. However all in all feels like pre-mature optimization.
– M. Deinum
Nov 17 '18 at 15:45
Hey, thanks for the comment. This test has been done after the warm-up iterations. It is not a unit test, it was conducted after fully starting up the project, warming it up by performing this call a couple of times and then calling it once again to test the projections. The results were all almost identical tho. Also it is not about 2.5 ms. One iteration (projecting 100 000 objects) takes 252 ms on average out of 100 tries. Using a real business logic with relations, multiple calls and other stuff would probably make it even slower. This test is merely to figure out which ones are better.
– Sikor
Nov 17 '18 at 16:01
Any chance of making those tests available? Maybe even as a pull request?
– Jens Schauder
Nov 18 '18 at 4:52
@JensSchauder Sure. I will do it in a few hours because I am not at home right now. I will create a public repo and let you know about it in the next comment. Thanks for taking interest in this.
– Sikor
Nov 18 '18 at 11:51
No hurry, it will take some time until I'll be able to look into this.
– Jens Schauder
Nov 18 '18 at 12:44