Skip to content
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

Add map preview cache #630

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from

Conversation

SadPencil
Copy link
Member

No description provided.

Copy link

github-actions bot commented Jan 8, 2025

Nightly build for this pull request:

@SadPencil SadPencil requested a review from Metadorius January 8, 2025 04:16
@SadPencil SadPencil linked an issue Jan 13, 2025 that may be closed by this pull request
@SadPencil SadPencil added this to the 2.11.7.0 milestone Jan 25, 2025
return null;
}

private async Task MapTextureLoadingService(CancellationToken cancellationToken)
Copy link
Member

Choose a reason for hiding this comment

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

don't think the functions should be called like so, the functions is "do something", not "a thing"

Copy link
Member Author

Choose a reason for hiding this comment

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

will fix it


private readonly ConcurrentDictionary<Map, Image> mapTextures = [];

private readonly ConcurrentDictionary<Map, byte> missedMaps = [];
Copy link
Member

Choose a reason for hiding this comment

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

  1. Why is this a dictionary when this should be a set? If the reason is that there's no concurrent set it's better to use some empty type like System.Reactive.Unit, for instance, as it better conveys the purpose.
  2. IMO this should be brought higher and renamed to pendingMaps, it's not missing, the maps are just waiting to be processed.

Copy link
Member Author

Choose a reason for hiding this comment

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

So what do you suggest? I think we can't introduce RX here right now just because of introducing the unit type

Copy link
Member

Choose a reason for hiding this comment

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

Well, I don't see a big problem with introducing Rx, but I guess you could make an empty type or just copy the unit type from System.Reactive, and later we could just replace it when we introduce Rx.

if (mapTextures.TryGetValue(map, out Image image))
return image;

if (missedMaps.Count < MaxCacheSize)
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this check redundant? There seems to be no point in regulating the input size.

Copy link
Member Author

Choose a reason for hiding this comment

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

Limiting RAM usage?

Copy link
Member

Choose a reason for hiding this comment

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

You missed the point. The RAM usage regulation is going to happen in the main dictionary which actually holds the map previews. AFAIK the map list is already in memory, so there wouldn't be a point to also regulate this as the most it will save is a few bytes. Also I don't think hitting 100 maps limit in 100ms is possible at all, and the "incoming" dictionary is drained regularly.

Copy link
Member Author

Choose a reason for hiding this comment

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

Then do you suggest also removing MaxCacheSize limits for the dictionary that holds bitmaps or not?

Copy link
Member

Choose a reason for hiding this comment

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

No, only from the pending/missing maps.

public void Dispose() =>
cancellationTokenSource?.Cancel();

public Image GetMapTextureIfAvailable(Map map)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
public Image GetMapTextureIfAvailable(Map map)
public Image? GetMapTextureIfAvailable(Map map)

Copy link
Member Author

Choose a reason for hiding this comment

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

I will write #nullable enable on file MapTextureCacheManager.cs, if we decide to use nullable pattern for new files

Copy link
Member

Choose a reason for hiding this comment

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

IMO nullables should be enabled across all projects.

Copy link
Member Author

@SadPencil SadPencil Feb 2, 2025

Choose a reason for hiding this comment

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

IMO nullables should be enabled across all projects.

Rans4cker once did that. And the majority objected because it introduces too many warning messages on existing codes. So to smoothly migrate (no one expects another .NET 6 migration PR) I suggest we enable that on new files as well as files being major revised

Copy link
Member

Choose a reason for hiding this comment

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

IIRC the main complaint was too strict StyleCop warnings, but alright. Those warnings are actually useful in this case IMO.

Copy link
Member Author

Choose a reason for hiding this comment

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

I know it's helpful. The point is there are too many warnings that would draw our attention from new warnings introduced

Comment on lines +66 to +67
}

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
}
}

Copy link
Member Author

Choose a reason for hiding this comment

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

huh? No changes were made

Copy link
Member

Choose a reason for hiding this comment

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

Ugh, I tried to remove the extra newline. Seems GitHub ate that.

@@ -43,7 +43,7 @@ public GameInformationPanel(WindowManager windowManager, MapLoader mapLoader)

private GenericHostedGame game = null;

private bool disposeTextures = false;
private bool disposeTextures = true;
Copy link
Member

Choose a reason for hiding this comment

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

This just caught my attention, I don't think there should be such a flag, just the no map preview texture should be set as a singleton, and then when disposing the texture should be compared to the no map preview one.

Copy link
Member Author

Choose a reason for hiding this comment

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

The disposeTextures pattern is directly copied from MapPreviewBox class. In that class, PreloadMapPreviews is such a texture that should not be disposed.

I think we can leave this design as a future work since the client already has such a pattern for a long time?

Copy link
Member

Choose a reason for hiding this comment

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

I thought that's a trivial change to do so though, isn't that right?

Copy link
Member Author

@SadPencil SadPencil Feb 2, 2025

Choose a reason for hiding this comment

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

Should be but it might require additional tests. Will try migrating it after I am available again

}
else
{
mapTexture = AssetLoader.TextureFromImage(mapLoader.MapTextureCacheManager.GetMapTextureIfAvailable(map));
Copy link
Member

Choose a reason for hiding this comment

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

Does this mean the first show of the preview will always show null texture? When will it be updated? IMO there should be a callback that will update the info upon loading the map.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. Currently it will be updated the second time it is visited.

Will trying implementing a callback after I am available again (~weeks perhaps)

private readonly CancellationTokenSource cancellationTokenSource = new();

public MapTextureCacheManager() =>
Task.Run(() => MapTextureLoadingService(cancellationTokenSource.Token));
Copy link
Member

Choose a reason for hiding this comment

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

There's no error handling and no task tracking. If your task errors out - there won't be any map previews anymore provided and the exception will not be caught.

Copy link
Member Author

Choose a reason for hiding this comment

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

Will fix it by catching and recording exceptions in the while loop

Copy link
Member

@Metadorius Metadorius left a comment

Choose a reason for hiding this comment

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

Actually hold on, maybe it would be better to use something like a weak reference for the cache instead of manually doing it?

Also I am not sure if clearing all of the maps when the limit is reached is a good idea, I would shave off the not used ones. Some maps are going to appear more frequently so they won't be deleted.

@SadPencil
Copy link
Member Author

Actually hold on, maybe it would be better to use something like a weak reference for the cache instead of manually doing it?

Also I am not sure if clearing all of the maps when the limit is reached is a good idea, I would shave off the not used ones. Some maps are going to appear more frequently so they won't be deleted.

Thanks for letting me know WeakReference. Will investigate

@SadPencil SadPencil modified the milestones: 2.11.7.0, long term Feb 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

Map preview lagging/ crashing for some users
2 participants