-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Register fields for reflection in kubernetes-client #42028
Conversation
Thanks for your pull request! Your pull request does not follow our editorial rules. Could you have a look?
This message is automatically generated by a bot. |
I can't say I understand this, can you explain a little? Thanks |
7f9b0e4
to
2795649
Compare
Sure, long story short: Jackson uses reflection to search fields #39934 (comment): private Map<String,FieldBuilder> _findFields(...) {
for (Field f : cls.getDeclaredFields()) { // <- reflection alert!
... Kubernetes Client model has been annotated with This PR registers all Kubernetes resources methods and fields for reflection potentially fixing the root issue. |
I'm not sure what the initial reasons were to restrict the model registration to only a given set and to exclude fields. This seems like a good temporary solution, but still I think that what @galderz said originally would make more sense quarkus-wise:
Related issues/PRs these changes affect: |
Yes, that would be the proper way to fix it, but the thing is that is not Quarkus who uses reflection, is Jackson from here: So, while the correct approach would be to use Jandex, that probably should be done on |
There has been a lot of discussion about the Kubernetes Client having a massive overhead when we were not careful about reflection registration so I think we need to be very careful about this (not saying it shouldn't go in but we need to measure the impact in terms of image size before we think about merging it). |
Agreed, hence my "This seems like a good temporary solution" statement :) I just wanted to keep on the record that the other task/issue should not be forgotten. |
3.13.0.CR1, final file size
This patch, final file size
There is a 1 MB overhead which is not bad at all. But please don't take my word for granted, anyone could test this to ensure there are no drawbacks. |
At some point we really really have to look at the Kubernetes binary size issue (due to Jackson) in a proper way. cc @xstefank who is now going to working on the JOSDK (which is a heavy user of the client) and @mariofusco who has done a lot of work around Jackson |
This comment has been minimized.
This comment has been minimized.
Apart from being able to identify which areas of the client are used, I don't see a lot of options. |
True as that may be, the fact that we are registering so much stuff for reflection AFAIU, is killing GraalVMs ability to do dead code elimination |
We should also explore what more can be done on the client side to improve things |
I'm making good progresses with my PoC trying to generate That said, I'm not sure if the work that I'm doing could be also applied to this specific issue, but my understanding is (please correct me if I'm wrong) that here we need to convert in json some specific pojos that are mapping the kubernetes configuration. If that's true couldn't we also develop some ad-hoc |
I'm not the SME (@manusa is), but this is my understanding as well |
To clarify the current issue: kubernetes-client model contains classes with Jackson annotations, and on previous versions of KC the fields had an additional annotation ( @JsonProperty("labels")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private Map<String, String> labels = new LinkedHashMap<String, String>();
@JsonProperty("labels")
public Map<String, String> getLabels() {
return labels;
}
@JsonProperty("labels")
public void setLabels(Map<String, String> labels) {
this.labels = labels;
} Since the fields were not registered, the If the reflection can be avoided that would be great, but for the time being, this change only registers correctly the fields of the KC model. |
There are several places in the client where deserialization (json-2-Pojo) takes place:
The However, long time ago we introduced the This means that if you application is not doing any type-specific operation, it might just work by registering One of the problems is that the Kubernetes Client Quarkus extension is too broad in scope. Plus the I still have a pending task to create a blog post showcasing how to create Quarkus Kubernetes app with a limited set of models. But the thing is that users are the ones who know in advance what types their application will be needing. One of the things I think might be hard to solve (but maybe I'm wrong and GraalVM/Quarkus can actually take care of this) is something like: KubernetesResource resource = kubernetesClient.resource($inputStream).item();
if (resource instanceof Service) {
System.out.println("service");
} else {
System.out.println("not-service");
} In this case, if the |
2795649
to
01afb82
Compare
maybe it might be worth investigating whether we could have a Jandex-based collector in Jackson? |
Wild idea (because this would change a lot of how the client work currently): could we keep the current model API but have the objects backed by a generic resource. Instead of all model objects being generated individually with appropriate fields, we would just getting the accessors, which would take care of accessing the appropriate key-value in the underlying map? Maybe that would simplify the serialization aspects? That said, this might not help size in memory or performance (since you'd have to access a map instead of a direct field access)… |
Jackson might need to allow both collectors, the Reflection-based and the Jandex-based collector, and be configurable since not everyone could use Jandex. But, can we keep focus on the current issue here? I agree is important to improve and reduce reflection in most libraries used by Quarkus, but right now the issue might be solved by just registering the fields with an overhead of just 1MB in the final size of the binary. |
For us, the current situation is pretty bad, that's why we are having the discussion about potential improvements. If it doesn't happen now, it will slip yet again... In any case, the PR itself makes sense but we need a real solution soon |
Maybe we can discuss this during a call. This might get complicated especially when trying to deal with deserialization of non-standard fields, etc. Also hard for the sundrio builder-generation integration. |
To follow up the discussion: #42110 |
This comment has been minimized.
This comment has been minimized.
01afb82
to
72396b7
Compare
I would love to also discuss this in a call, since it could even be related to the work that I'm doing for the PoC that I mentioned in one of my former comments. |
Note that there's an alternative solution here, which is that methods always have the same annotations as fields. Then you "just" have to register methods for reflection and you can ignore fields. But if there's functionality that relies on annotations that are only in fields then it would break. |
This will be definitely fixed when 6.13.2 is released (probably on 2024-08-05). However, users who generate their own types and don't annotate them uniformly might still run into the issue.
I created a discussion on the Fabric8 Kubernetes Client repo to follow up on this and avoid adding more noise to the PR: fabric8io/kubernetes-client#6199 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with what has been said so far. As far as I am concerned the PR looks OK as an immediate solution.
FWIW the size increase is indeed not huge, but still noticeable.
In kubernetes-client
IT I see an increase of ~.5MB in the image size (or 0.3% of the total size and 0.8% of the heap size) which is the result of registering 10973 more fields for reflection.
In openshift-client
IT I see a similar increase of ~.5MB in the image size (or 0.4% of the total size and 0.9% of the heap size) which is the result of registering 11635 more fields for reflection.
...loyment/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesClientProcessor.java
Outdated
Show resolved
Hide resolved
This comment has been minimized.
This comment has been minimized.
Signed-off-by: Jorge Solórzano <[email protected]>
72396b7
to
969351a
Compare
Yeah same here, given the current situation, we can pay the price for it. |
Status for workflow
|
Pod Overhead set without corresponding RuntimeClass defined Overhead.
#39934