Skip to content

Update the existing structures to support accelerator array in variation and current sections#1921

Open
bharathappali wants to merge 1 commit into
kruize:mvp_demofrom
bharathappali:gpu-cur-var-1
Open

Update the existing structures to support accelerator array in variation and current sections#1921
bharathappali wants to merge 1 commit into
kruize:mvp_demofrom
bharathappali:gpu-cur-var-1

Conversation

@bharathappali
Copy link
Copy Markdown
Member

@bharathappali bharathappali commented May 20, 2026

Description

This PR adds the structural changes needed to export the accelerator info in current and variation sections of the recommendation JSON.

Finalized JSON designs:

Current Section:

{
  "current": {
    "requests": {
      "memory": {
        "amount": 490.93,
        "format": "MiB"
      },
      "cpu": {
        "amount": 1.46,
        "format": "cores"
      }
    },
    "limits": {
      "memory": {
        "amount": 712.21,
        "format": "MiB"
      },
      "cpu": {
        "amount": 1.54,
        "format": "cores"
      },
      "accelerators": [
        {
          "model": "nvidia-a100-80gb",
          "partition": "full-gpu",
          "compute": {
            "amount": 7,
            "format": "slices"
          },
          "memory": {
            "amount": 80,
            "format": "GiB"
          }
        }
      ]
    }
  }
}

Variation Section:

{
  "variation": {
    "requests": {
      "memory": {
        "amount": 707.05,
        "format": "MiB"
      },
      "cpu": {
        "amount": 6.22,
        "format": "cores"
      }
    },
    "limits": {
      "memory": {
        "amount": 485.77,
        "format": "MiB"
      },
      "cpu": {
        "amount": 6.14,
        "format": "cores"
      },
      "accelerators": [
        {
          "model": "nvidia-a100-80gb",
          "compute": {
            "amount": -57.14,
            "format": "percentage"
          },
          "memory": {
            "amount": -50.0,
            "format": "percentage"
          }
        }
      ]
    }
  }
}

From a code stand point you can see that the same structure should support a map for cpu, memory and an array for the accelerator.

Maintaining the map with generic Object will cause type check issues and also the de-serialization efforts will be huge, So we went ahead to have a interface which is implemented by two types, also this helps to keep the structure extendable and also we can maintain common functions at interface level in future.

As we need to have a wrapper class around the list, direct conversion makes it a nested structure of items as key in the JSON, so we need to have an adapter which skips that structure and adds the list values directly to the parent

Fixes #1920

Type of change

  • Bug fix
  • New feature
  • Docs update
  • Breaking change (What changes might users need to make in their application due to this PR?)
  • Requires DB changes

How has this been tested?

Please describe the tests that were run to verify your changes and steps to reproduce. Please specify any test configuration required.

  • New Test X
  • Functional testsuite

Test Configuration

  • Kubernetes clusters tested on:

Checklist 🎯

  • Followed coding guidelines
  • Comments added
  • Dependent changes merged
  • Documentation updated
  • Tests added or updated

Additional information

Include any additional information such as links, test results, screenshots here

Summary by Sourcery

Introduce a polymorphic resource recommendation model to support both scalar resources and accelerator arrays in recommendation outputs.

New Features:

  • Add support for accelerator recommendations via a new AcceleratorRecommendationItem and MultiResourceRecommendation wrapper that serialize as an array in the recommendation JSON.
  • Generalize request and limit configurations to accept a common ResourceRecommendation type so CPU, memory, and accelerators share a unified representation.

Enhancements:

  • Update existing recommendation configuration and engine code to use the new ResourceRecommendation abstraction while preserving current CPU and memory behavior.
  • Introduce a custom Gson adapter to flatten MultiResourceRecommendation into a plain JSON array for accelerators during (de)serialization.

…ion and current

Signed-off-by: bharathappali <abharath@redhat.com>
@bharathappali bharathappali requested a review from mbvreddy May 20, 2026 08:31
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented May 20, 2026

Reviewer's Guide

Refactors recommendation resource typing so CPU/memory maps and accelerator arrays share a common ResourceRecommendation interface, introduces accelerator-specific recommendation structures, and adds a custom Gson adapter to serialize a wrapped list of accelerators directly as a JSON array in current and variation sections.

Sequence diagram for MultiResourceRecommendation JSON serialization/deserialization

sequenceDiagram
    participant Engine as RecommendationEngine
    participant gson as Gson
    participant multi as MultiResourceRecommendation
    participant adapter as MultiResourceRecommendationAdapter

    Engine->>gson: toJson(multi)
    gson->>adapter: serialize(multi, typeOfSrc, context)
    adapter->>adapter: src.getItems()
    adapter->>gson: context.serialize(items)
    gson-->>Engine: JSON accelerators_array

    Engine->>gson: fromJson(json, MultiResourceRecommendation)
    gson->>adapter: deserialize(jsonElement, typeOfT, context)
    adapter->>gson: context.deserialize(jsonElement, listType)
    gson-->>adapter: List AcceleratorRecommendationItem
    adapter-->>gson: new MultiResourceRecommendation(items)
    gson-->>Engine: MultiResourceRecommendation instance
Loading

File-Level Changes

Change Details Files
Generalize request/limit maps to hold heterogeneous resource recommendation types via a new ResourceRecommendation interface.
  • Change Config.requests and Config.limits map value type from RecommendationConfigItem to ResourceRecommendation.
  • Update RecommendationEngine to create HashMaps keyed by RecommendationItem with ResourceRecommendation values.
  • Cast map values back to RecommendationConfigItem where numeric CPU/memory amounts are updated.
src/main/java/com/autotune/analyzer/recommendations/Config.java
src/main/java/com/autotune/analyzer/recommendations/engine/RecommendationEngine.java
Make existing scalar recommendation items implement the new resource abstraction.
  • Have RecommendationConfigItem implement the new ResourceRecommendation marker interface so it can be stored in the generalized maps.
src/main/java/com/autotune/analyzer/recommendations/RecommendationConfigItem.java
Introduce accelerator-specific recommendation modeling and a wrapper for multiple accelerator recommendations.
  • Add AcceleratorRecommendationItem representing a single accelerator with model, partition, count, compute, and memory recommendations.
  • Add MultiResourceRecommendation wrapper holding a list of AcceleratorRecommendationItem and annotated with a custom JsonAdapter.
  • Define the ResourceRecommendation interface as the common supertype for scalar and multi-resource recommendations.
src/main/java/com/autotune/analyzer/recommendations/AcceleratorRecommendationItem.java
src/main/java/com/autotune/analyzer/recommendations/MultiResourceRecommendation.java
src/main/java/com/autotune/analyzer/recommendations/ResourceRecommendation.java
Customize JSON (de)serialization for accelerator lists so the wrapper is not exposed in the schema.
  • Implement MultiResourceRecommendationAdapter to serialize MultiResourceRecommendation as a bare JSON array and deserialize it back into a list of AcceleratorRecommendationItem.
  • Wire the adapter to MultiResourceRecommendation via @JsonAdapter so current and variation sections emit 'accelerators' as arrays without an 'items' wrapper.
src/main/java/com/autotune/analyzer/adapters/MultiResourceRecommendationAdapter.java
src/main/java/com/autotune/analyzer/recommendations/MultiResourceRecommendation.java

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@bharathappali bharathappali requested a review from khansaad May 20, 2026 08:31
Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • Switching Config.requests/limits to Map<..., ResourceRecommendation> but then downcasting to RecommendationConfigItem in RecommendationEngine weakens type safety and defeats the polymorphic design; consider either separating the maps by resource type or introducing typed accessors/visitors so the engine doesn’t need explicit casts.
  • The MultiResourceRecommendationAdapter.deserialize method assumes the JSON is always an array; you may want to defensively handle null or non-array inputs (e.g., a single object or empty value) to avoid runtime JsonParseExceptions on slightly malformed or older payloads.
  • If AcceleratorRecommendationItem is intended to be deserialized by Gson in more places, consider adding a no-arg constructor and/or setters so that it plays more naturally with Gson’s default instantiation and to keep it consistent with the other recommendation model classes.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Switching `Config.requests`/`limits` to `Map<..., ResourceRecommendation>` but then downcasting to `RecommendationConfigItem` in `RecommendationEngine` weakens type safety and defeats the polymorphic design; consider either separating the maps by resource type or introducing typed accessors/visitors so the engine doesn’t need explicit casts.
- The `MultiResourceRecommendationAdapter.deserialize` method assumes the JSON is always an array; you may want to defensively handle `null` or non-array inputs (e.g., a single object or empty value) to avoid runtime `JsonParseException`s on slightly malformed or older payloads.
- If `AcceleratorRecommendationItem` is intended to be deserialized by Gson in more places, consider adding a no-arg constructor and/or setters so that it plays more naturally with Gson’s default instantiation and to keep it consistent with the other recommendation model classes.

## Individual Comments

### Comment 1
<location path="src/main/java/com/autotune/analyzer/adapters/MultiResourceRecommendationAdapter.java" line_range="21" />
<code_context>
+    }
+
+    @Override
+    public MultiResourceRecommendation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+            throws JsonParseException {
+        Type listType = new com.google.gson.reflect.TypeToken<List<AcceleratorRecommendationItem>>(){}.getType();
</code_context>
<issue_to_address>
**suggestion:** Deserialization does not guard against non-array or null JSON and may produce a MultiResourceRecommendation with a null items list.

The adapter currently assumes `json` can always be deserialized into `List<AcceleratorRecommendationItem>` and passes that (possibly null) list to the constructor. Consider:
- Returning an empty `MultiResourceRecommendation` when `json` is `null` or `JsonNull`.
- Validating that `json` is a `JsonArray` and throwing a clear `JsonParseException` otherwise.
This will keep `items` non-null and make failures more explicit and predictable.

Suggested implementation:

```java
    @Override
    public MultiResourceRecommendation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        // Treat null or JsonNull as an empty recommendation rather than returning a null items list
        if (json == null || json.isJsonNull()) {
            return new MultiResourceRecommendation(Collections.emptyList());
        }

        // Ensure the JSON structure is an array; fail fast with a clear error otherwise
        if (!json.isJsonArray()) {
            throw new JsonParseException(
                    "Expected a JSON array for MultiResourceRecommendation, but found: " + json.toString());
        }

        Type listType = new com.google.gson.reflect.TypeToken<List<AcceleratorRecommendationItem>>() {}.getType();
        List<AcceleratorRecommendationItem> items = context.deserialize(json, listType);

        // Guarantee items is non-null
        if (items == null) {
            items = Collections.emptyList();
        }

        return new MultiResourceRecommendation(items);
    }

```

To compile successfully, ensure the following import is present at the top of the file (if not already there):

- `import java.util.Collections;`

If it is missing, add it alongside the other imports in this class.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

}

@Override
public MultiResourceRecommendation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
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.

suggestion: Deserialization does not guard against non-array or null JSON and may produce a MultiResourceRecommendation with a null items list.

The adapter currently assumes json can always be deserialized into List<AcceleratorRecommendationItem> and passes that (possibly null) list to the constructor. Consider:

  • Returning an empty MultiResourceRecommendation when json is null or JsonNull.
  • Validating that json is a JsonArray and throwing a clear JsonParseException otherwise.
    This will keep items non-null and make failures more explicit and predictable.

Suggested implementation:

    @Override
    public MultiResourceRecommendation deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        // Treat null or JsonNull as an empty recommendation rather than returning a null items list
        if (json == null || json.isJsonNull()) {
            return new MultiResourceRecommendation(Collections.emptyList());
        }

        // Ensure the JSON structure is an array; fail fast with a clear error otherwise
        if (!json.isJsonArray()) {
            throw new JsonParseException(
                    "Expected a JSON array for MultiResourceRecommendation, but found: " + json.toString());
        }

        Type listType = new com.google.gson.reflect.TypeToken<List<AcceleratorRecommendationItem>>() {}.getType();
        List<AcceleratorRecommendationItem> items = context.deserialize(json, listType);

        // Guarantee items is non-null
        if (items == null) {
            items = Collections.emptyList();
        }

        return new MultiResourceRecommendation(items);
    }

To compile successfully, ensure the following import is present at the top of the file (if not already there):

  • import java.util.Collections;

If it is missing, add it alongside the other imports in this class.

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.

1 participant