microsoftgraph / msgraph-sdk-dotnet

Microsoft Graph Client Library for .NET!
https://graph.microsoft.com
Other
704 stars 252 forks source link

Microsoft.Graph.dll file size #1702

Closed teh173 closed 8 months ago

teh173 commented 1 year ago

Describe the bug File size of Microsoft.Graph.dll seems bigger than it needs to be if I'm just using a few APIs from Graph. Can the Graph DLL be split up? Is there a simple way to leave things I don't need compiled out?

It's jumped massively with 5.0.

4.x: image

5.x: image

See also: https://github.com/microsoftgraph/msgraph-beta-sdk-dotnet/issues/500

Expected behavior Distributable size proportionate to need.

silentdevnull commented 1 year ago

The file size is a big issue for me at the moment. I had to go back to 4.x. I can't upload any signal file over 25mb to the server, right now this dll is 36mb.

I hope this is a fast fix so I can go to 5.x

MartinM85 commented 1 year ago

Same for Microsoft.Graph.xml

v4.6 - 29.7 MB (31,194,770 bytes)

v5.1 - 61.9 MB (64,972,960 bytes)

I suspect that very long namespaces have effect on the size of dll and xml.

Example: v5 - Microsoft.Graph.Drives.Item.Items.Item.Analytics.ItemActivityStats.Item.Activities.Item.ItemActivityItemRequestBuilder 8x times word Item in one namespace is really weird.

v4 - Microsoft.Graph.IItemActivityRequestBuilder.Request

rubeesh commented 1 year ago

The issue still not resolved even after upgrading to version 5.2

silentdevnull commented 1 year ago

Good Morning,

Is there an update on this? I'm unable to switch to this until the dll size issue is fixed.

silentdevnull commented 1 year ago

I just tried upgrading to 5.3.0 and it still 36mb. There is no way for me to around the 25mb file limit. Can we please address this issue.

rubeesh commented 1 year ago

I just tried upgrading to 5.3.0 and it still 36mb. There is no way for me to around the 25mb file limit. Can we please address this issue.

The issue still not resolved even after upgrading to version 5.2

Tested version 5.4 Not yet fixed.

silentdevnull commented 1 year ago

Do we have a status update on this? It would be really nice to go to graph 5.0.

Thank you

silentdevnull commented 1 year ago

Is there any update on the size issue?

silentdevnull commented 1 year ago

Do we have any update on why the file size is so large and a ETA of it being fixed?

MartinM85 commented 1 year ago

@silentdevnull https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/1874 Looks like the target version with a fix is v6.

MartinM85 commented 1 year ago

From my investigation, there is a lot of duplicated classes with the same name but under different namespaces. I've comparing v4.54 and v5.9

version 4.54 In version 4.54 there is around 8199 classes and the size of MicrosoftGraph.dll is around 11 MB

version 5.9.0 In version 5.9.0 there is around 28799 classes and the size of MicrosoftGraph.dll is around 34 MB. If classes are grouped by a name (not a full name) then the number of classes is around 8196.

The table bellow shows classes which are in more than 50 different namespaces.

class name number
CountRequestBuilder 1492
CountRequestBuilderGetRequestConfiguration 1491
CountRequestBuilderGetQueryParameters 1482
DeltaRequestBuilder 120
DeltaResponse 119
DeltaRequestBuilderGetQueryParameters 119
DeltaRequestBuilderGetRequestConfiguration 119
ContentRequestBuilder 111
ContentRequestBuilderGetRequestConfiguration 111
ContentRequestBuilderPutRequestConfiguration 111
SetRequestBuilder 108
SetRequestBuilderGetQueryParameters 108
SetRequestBuilderGetRequestConfiguration 108
SingleValueExtendedPropertiesRequestBuilder 71
SingleValueLegacyExtendedPropertyItemRequestBuilder 71
MultiValueExtendedPropertiesRequestBuilder 71
MultiValueLegacyExtendedPropertyItemRequestBuilder 71
SingleValueExtendedPropertiesRequestBuilderGetQueryParameters 71
SingleValueExtendedPropertiesRequestBuilderGetRequestConfiguration 71
SingleValueExtendedPropertiesRequestBuilderPostRequestConfiguration 71
SingleValueLegacyExtendedPropertyItemRequestBuilderDeleteRequestConfiguration 71
SingleValueLegacyExtendedPropertyItemRequestBuilderGetQueryParameters 71
SingleValueLegacyExtendedPropertyItemRequestBuilderGetRequestConfiguration 71
SingleValueLegacyExtendedPropertyItemRequestBuilderPatchRequestConfiguration 71
MultiValueExtendedPropertiesRequestBuilderGetQueryParameters 71
MultiValueExtendedPropertiesRequestBuilderGetRequestConfiguration 71
MultiValueExtendedPropertiesRequestBuilderPostRequestConfiguration 71
MultiValueLegacyExtendedPropertyItemRequestBuilderDeleteRequestConfiguration 71
MultiValueLegacyExtendedPropertyItemRequestBuilderGetQueryParameters 71
MultiValueLegacyExtendedPropertyItemRequestBuilderGetRequestConfiguration 71
MultiValueLegacyExtendedPropertyItemRequestBuilderPatchRequestConfiguration 71
RefRequestBuilder 69
ExtensionsRequestBuilder 66
ExtensionItemRequestBuilder 66
ExtensionsRequestBuilderGetQueryParameters 66
ExtensionsRequestBuilderGetRequestConfiguration 66
ExtensionsRequestBuilderPostRequestConfiguration 66
ExtensionItemRequestBuilderDeleteRequestConfiguration 66
ExtensionItemRequestBuilderGetQueryParameters 66
ExtensionItemRequestBuilderGetRequestConfiguration 66
ExtensionItemRequestBuilderPatchRequestConfiguration 66
RelationsRequestBuilder 60
RelationItemRequestBuilder 60
ToTermRequestBuilder 60
FromTermRequestBuilder 60
RelationsRequestBuilderGetQueryParameters 60
RelationsRequestBuilderGetRequestConfiguration 60
RelationsRequestBuilderPostRequestConfiguration 60
RelationItemRequestBuilderDeleteRequestConfiguration 60
RelationItemRequestBuilderGetQueryParameters 60
RelationItemRequestBuilderGetRequestConfiguration 60
RelationItemRequestBuilderPatchRequestConfiguration 60
ToTermRequestBuilderGetQueryParameters 60
ToTermRequestBuilderGetRequestConfiguration 60
FromTermRequestBuilderGetQueryParameters 60
FromTermRequestBuilderGetRequestConfiguration 60
CreateUploadSessionPostRequestBody 55
CreateUploadSessionRequestBuilder 55
ParentNotebookRequestBuilder 55
CreateUploadSessionRequestBuilderPostRequestConfiguration 55
ParentNotebookRequestBuilderGetQueryParameters 55
ParentNotebookRequestBuilderGetRequestConfiguration 55
AttachmentsRequestBuilder 53
AttachmentsRequestBuilderGetQueryParameters 53
AttachmentsRequestBuilderGetRequestConfiguration 53
AttachmentsRequestBuilderPostRequestConfiguration 53
ForwardPostRequestBody 50
ForwardRequestBuilder 50
AttachmentItemRequestBuilder 50
ForwardRequestBuilderPostRequestConfiguration 50
AttachmentItemRequestBuilderDeleteRequestConfiguration 50
AttachmentItemRequestBuilderGetQueryParameters 50
AttachmentItemRequestBuilderGetRequestConfiguration 50

Why to have more than 1000 classes with the same name and the same implementation?

snippet

var graphAssembly = Assembly.Load(AssemblyName.GetAssemblyName("Microsoft.Graph.dll"));

var types = graphAssembly.GetTypes();

var classes = new List<(string name, string fullname)>();

foreach (var tc in types)
{
    if (tc.IsClass && tc.FullName.StartsWith("Microsoft.Graph"))
    {
        classes.Add((tc.Name, tc.FullName));
    }
}

var groups = classes.GroupBy(x => x.name).OrderByDescending(x => x.Count()).ToList();
silentdevnull commented 1 year ago

@silentdevnull #1874 Looks like the target version with a fix is v6.

Thank you for the information.

I can't believe the are going to not fix it in the current version as this a big issue.

I hope version 4 doesn't break because if it does, I'm screwed big time. I can't update an of my application to 5.

lukeskinner commented 1 year ago

We recently moved onto the graph API due to the deprecation/turned off the ability to use EWS with modern auth. We're just finding this Microsoft.Graph.dll file is bigger than the entirety of some of our applications (wpf based). It's extremely wasteful for client applications that run on low spec pcs.

d-a-s commented 1 year ago

This has a huge impact on first load time after building a project. I have a web server which previously would take 9s after build to load the first page. Adding this package it takes 30s...3 times longer!

Edit: I spent the last couple of days studying the source code and implementing a "thin" client alternative, based mostly on copying the models out of the SDKs source and then using the Microsoft.Graph.Core package directly.

For anyone who's interested, I put together a [github gist])https://gist.github.com/d-a-s/bea2792daa8f6e1b835696dfc487165f). It's a simplified/sanitized version of the code I ended up with.

Safirion commented 1 year ago

Please reduce the size of the Microsoft.Graph.dll. My .Net 7 app publish file size is ~10Mb without Microsoft Graph and after adding it and build in R2R, the size is now 180Mb.

image

Balkoth commented 1 year ago

Yes, this single assembly blows up applications by a ridiculous amount.

MartinM85 commented 1 year ago

Yes, the issue is that there is only one single assembly that contains builders for thousands endpoints. Real use case is that an app is calling only a small subset of endpoints, so it uses < 1% of builders and endpoints.

Since all builders are generated by Kiota, it should be possible to split up Microsoft.Graph project into small ones. Each project will generate own NuGet package and developers can reference only one small NuGet package.

Example:

src\Microsoft.Graph\Generated\RoleManagement will have NuGet Microsoft.Graph.RoleManagement with RoleManagementServiceClient similar to the current GraphServiceClient and BaseGraphServiceClient

// <auto-generated/>
using Microsoft.Graph.RoleManagement;
...
namespace Microsoft.Graph {
    /// <summary>
    /// The main entry point of the SDK, exposes the configuration and the fluent API.
    /// </summary>
    public class RoleManagementBaseGraphServiceClient : BaseRequestBuilder {
        /// <summary>Provides operations to manage the roleManagement singleton.</summary>
        public RoleManagementRequestBuilder RoleManagement { get =>
            new RoleManagementRequestBuilder(PathParameters, RequestAdapter);
        }

        /// <summary>
        /// Instantiates a new RoleManagementBaseGraphServiceClient and sets the default values.
        /// </summary>
        /// <param name="backingStore">The backing store to use for the models.</param>
        /// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
        public RoleManagementBaseGraphServiceClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary<string, object>()) {
            ApiClientBuilder.RegisterDefaultSerializer<JsonSerializationWriterFactory>();
            ApiClientBuilder.RegisterDefaultSerializer<TextSerializationWriterFactory>();
            ApiClientBuilder.RegisterDefaultSerializer<FormSerializationWriterFactory>();
            ApiClientBuilder.RegisterDefaultSerializer<MultipartSerializationWriterFactory>();
            ApiClientBuilder.RegisterDefaultDeserializer<JsonParseNodeFactory>();
            ApiClientBuilder.RegisterDefaultDeserializer<TextParseNodeFactory>();
            ApiClientBuilder.RegisterDefaultDeserializer<FormParseNodeFactory>();
            if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) {
                RequestAdapter.BaseUrl = "https://graph.microsoft.com/v1.0";
            }
            PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl);
            RequestAdapter.EnableBackingStore(backingStore);
        }

}
pschaeflein commented 1 year ago

@MartinM85 - You can use Kiota to generate an SDK for Graph that includes whatever endpoints you wish.

MartinM85 commented 1 year ago

@pschaeflein Sure, I can generate a SDK for Graph API with Kiota by myself, but the whole process is quite complicated. Metadata for OpenAPI spec are preprocessed several times, but it's a good idea. I can imagine some tool where devs check which endpoints should be included into Graph API SDK, select language(s), etc.

baywet commented 8 months ago

Hi everyone, This thread was brought to my attention during the Microsoft MVP summit this week. Apologies for the delays in getting a proper reply.

I'll write down a lengthy explanations of the situation here and hopefully it answers most questions.

Size is a concern

Microsoft Graph is an extremely large API and packaging any client for it has always, and will remain a challenge. It's a trade-off between getting access to as many capabilities as possible and keeping size under control. We acknowledge that size can be a limiting factor and/or degrade the developer/end user experience.

Self-served clients

No application needs all Graph operations and endpoints, while a pre-packaged SDK makes things straightforward to discover and consume, it brings its trade-off. For scenarios that are constrained on size, we recommend that you explore generating your own client with kiota. You'll get the same exact experience (models, fluent API, etc...) but for only the operations your application needs, reducing the footprint drastically. On the self serve story, the main gap we've had to date is the lack of documentation. This is something we're starting to address https://github.com/microsoftgraph/microsoft-graph-docs/pull/23917

Improvements in the SDK we've already made

We've worked with the dotnet team to enable proper AOT support. If you haven't explored that aspect, and you don't want to switch to a self-served client, you should try AOT, which among other things tree-shakes the assemblies. In a containerized scenario the dotnet team went from ~350+MB down to ~30MB (trimming + changing base image).

We've changed the way we project the code where we could without introducing a breaking change. That already resulted in a size reduction (I don't have the numbers handy anymore, but can look them up if anyone is interested)

Improvements for the SDK to come

One thing that was missed before GA, is to NOT generate code for /me, and bind the path to the same code as /users/id. The user object ties in to a lot of the API surface, and this "duplication" results in about 30% size waste. https://github.com/microsoftgraph/msgraph-sdk-dotnet/issues/1874 We also had ambiguous naming convention issues we've had to fix, and add backward compatible obsolete symbols, this wastes another 10 % (so 37% total). We're planning to clean all this up during the next major release as all these things represent breaking changes. We don't have a timeline for that yet.

Item pattern

This is simply a naming pattern when indexing into collections. Since Graph is designed with a lot of nested collections, it can lead to duplication. Is there any additional questions on that aspect?

Request builder names duplication

This is a design choice, effectively each request builder is different from one another because the request body, response, operations, query parameters, etc... Can vary from one to another. They are used to build the fluent API experience. It just happens so Graph being based on odata conventions has a lot of naming repetition. I'm curious to why this is causing friction for you? The way this API is designed, there are only very rare cases where you should have to import them. Can you expand on why you believe this is an issue?

Splitting things over multiple packages

This is something we've talked about multiple times in the past. We've had to do it for TypeScript for example. But it adds a lot of complexity to the consumer of the packages and maintenance burden for us. We feel like dotnet is efficient enough to produce reasonably sized packages given the size of the API. And most scenarios that dotnet is used in are either not size constrained (server apps), or trimmed (AOT, etc...) for this investment to be worth the trade-off.

I hope this lengthy reply helps clarify a lot of the interrogations, please do not hesitate to follow-up on the points mentioned above.

MartinM85 commented 8 months ago

Self-served clients

No application needs all Graph operations and endpoints, while a pre-packaged SDK makes things straightforward to discover and consume, it brings its trade-off. For scenarios that are constrained on size, we recommend that you explore generating your own client with kiota. You'll get the same exact experience (models, fluent API, etc...) but for only the operations your application needs, reducing the footprint drastically. On the self serve story, the main gap we've had to date is the lack of documentation. This is something we're starting to address https://github.com/microsoftgraph/microsoft-graph-docs/pull/23917

@baywet Could you please edit the link? It's linked to the old doc repository. New repo for doc is https://github.com/microsoftgraph/microsoft-graph-docs-contrib

baywet commented 8 months ago

Sorry about that. The page has since been published here don't hesitate to provide feedback!

BieleckiLtd commented 1 week ago

Could Microsoft.Graph be modularised in the future? Currently, this dependency alone is doubling the application's footprint just to handle authorisation for me.