The SLM retention clean up task `SnapshotRetentionTask` lists all snapshots in order to identify the snapshots to retain and the snapshots to delete. While doing so it retrieves the full snapshot information, including shard snapshot details and shard snapshot failures, to later  only use snapshot metadata and snapshot timestamp to select the snapshots to retain. When the snapshots contain thousands of shards it represents of lot of objects that are unnecessary created, putting a lot of pressure on the garbage collector.

We should improve the way SLM retrieves snapshots to reduce the huge allocations of objects. David made some [interesting](https://github.com/elastic/elasticsearch/issues/99953#issuecomment-1738534389) [suggestions](https://github.com/elastic/elasticsearch/issues/99953#issuecomment-1738626743) in comments.

- #100044
- #100053
- #100054
- #100058
- #100065
- #100070
- #100092
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/slm/SnapshotRetentionConfigurationTests.java
List<SnapshotInfo> infos = Arrays.asList(s1, s2, s3, s4);
        assertThat(conf.getSnapshotDeletionPredicate(infos).test(s1), equalTo(false));
        assertThat(conf.getSnapshotDeletionPredicate(infos).test(s2), equalTo(false));
        assertThat(conf.getSnapshotDeletionPredicate(infos).test(s3), equalTo(true));
        assertThat(conf.getSnapshotDeletionPredicate(infos).test(s4), equalTo(false));
    }
    public void testFailuresKeptIfNoExpiryAndNoMoreRecentSuccess() {
        assertUnsuccessfulKeptIfNoExpiryAndNoMoreRecentSuccess(true);
    }
    public void testPartialsKeptIfNoExpiryAndNoMoreRecentSuccess() {
        assertUnsuccessfulKeptIfNoExpiryAndNoMoreRecentSuccess(false);
    }
    private void assertUnsuccessfulKeptIfNoExpiryAndNoMoreRecentSuccess(boolean failure) {
        
        SnapshotRetentionConfiguration conf = new SnapshotRetentionConfiguration(() -> 1, null, 2, 3);
        SnapshotInfo s1 = makeInfo(1);
        SnapshotInfo s2 = makeInfo(2);
        SnapshotInfo s3 = makeInfo(3);
        SnapshotInfo s4 = makeFailureOrPartial(4, failure);
        List<SnapshotInfo> infos = Arrays.asList(s1, s2, s3, s4);
        assertThat(conf.getSnapshotDeletionPredicate(infos).test(s1), equalTo(false));
        assertThat(conf.getSnapshotDeletionPredicate(infos).test(s2), equalTo(false));
        assertThat(conf.getSnapshotDeletionPredicate(infos).test(s3), equalTo(false));
        assertThat(conf.getSnapshotDeletionPredicate(infos).test(s4), equalTo(false));
    }
    public void testFailuresNotCountedTowardsMaximum() {
        assertUnsuccessfulNotCountedTowardsMaximum(true);
    }
    public void testPartialsNotCountedTowardsMaximum() {
        assertUnsuccessfulNotCountedTowardsMaximum(false);