Xamarin.iOS package size increase a lot after using ServiceStack.Client

After migrating my mobile code to using ServiceStack.Client. My package size grow from 50+m to 70+m. This really make me crazy.

I do not know why Xamarin.iOS package size is so huge. I have asked question in the Xamarin forums. If anybody has some ideas to reduce package size, you will save my life.

Thank you very much.

@mythz
I find if i call IosPclExportClient.Configure(); the app size increase from 50+m to 70+m, what’s the magic service client did?

Could you tell me how to reduce the size. If service stack client is so huge, i will use other client instead. But i think Service Stack Client work perfect with Service Stack Server, i do not want to change. could you have a look at it.

Please check my snapshots. I already spend more than 20 hours to find which parts make my project size growing. please help me.

commet IosPclExportClient.Configure();


if has IosPclExportClient.Configure();

Please don’t address questions to me about 3rd party products. This is clearly a result of how Xamarin works, not ServiceStack.

There is no “magic” in ServiceStack Client libraries, they’re normal managed .NET dlls. You can take a look at ServiceStack.Client and ServiceStack.HttpClient yourself to see exactly what they’re made of.

From a high-level you can see what dependencies each have by looking at the NuGet dependencies for ServiceStack.Client and ServiceStack.HttpClient. Here you can can tell JsonHttpClient in ServiceStack.HttpClient requires more dependencies than JsonServiceClient in ServiceStack.Client.

The “magic” is in Xamarin’s linker which pulls in everything it needs to for it to work. If you’re not happy with the size, look for a different library with a smaller footprint.

Thank you, I will try JsonServiceClient and ask Xamarin.

JsonServiceClient is still not good. But smaller than JsonHttpClient.

Can you also try the ServiceStack.Client on MyGet, I’ve removed the XmlServiceClient and references System.Xml in PCL builds to see if it makes a difference to the compiled binary?

Thank you, I tried it. the size is not change. I find RestSharp is very small. ServiceStack.Client reference ServiceStack.Pcl.iOS. I guest this dll refer some useless feature. I just guess.

I use these dlls from myget.

<package id="ServiceStack.Client" version="4.0.43" targetFramework="xamarinios10" />
<package id="ServiceStack.Interfaces" version="4.0.43" targetFramework="xamarinios10" />
<package id="ServiceStack.Text" version="4.0.43" targetFramework="xamarinios10" />

It’s not a useless feature, it’s the PCL implementation for the iOS platform, required for running on iOS.
The source code is in ServiceStack.Pcl.iOS10.

How much smaller is RestSharp?

I have not used RestSharp to implement my client, i just refer RestSharp and archive my app. I find the package size just increase 2~3m. This may not be accurate. I will test RestSharp tomorrow. I hope Xamarin reply my email ASAP and tell me how the link work.

This is RestSharp Reference.

<ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="Xamarin.iOS" />
  </ItemGroup>

This is ServiceStack.Client reference

<Reference Include="ServiceStack.Text">
      <HintPath>..\..\lib\ServiceStack.Text.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Net" />
    <Reference Include="System.Runtime.Serialization" />
    <Reference Include="System.ServiceModel" />
    <Reference Include="System.Web" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>

This is ServiceStack.Pcl.iOS10.csproj reference

<ItemGroup>
    <Reference Include="ServiceStack.Text">
      <HintPath>..\..\lib\pcl\ServiceStack.Text.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Xml" />
    <Reference Include="System.Core" />
    <Reference Include="Xamarin.iOS" />
    <Reference Include="ServiceStack.Interfaces">
      <HintPath>..\..\lib\ServiceStack.Interfaces.dll</HintPath>
    </Reference>
    <Reference Include="System.Runtime.Serialization" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\ServiceStack.Client\ServiceStack.Client.PCL.csproj">
      <Project>{135808A7-CE69-4C32-BE30-25A8FFBF4A58}</Project>
      <Name>ServiceStack.Client.PCL</Name>
    </ProjectReference>
  </ItemGroup>

I do not know which reference is the key.

Xamarin Support has replied, but seems useless.


Nicholas Spagnola
AUG 26, 2015 | 11:44AM EDT
Hi Yin,

Unfortunately this is not a Xamarin issue. We can’t do a full code review to determine the issue, if there is any. I’d continue to check StackOverflow and the Xamarin Forums for further advice.

Warm regards,
Nick

Please, rate my reply: http://nicereply.com/xamarin/22751388/203565

I test Hello.Xamarin project. This example is download from ServiceStack website. If comment ServiceStack.IosPclExportClient.Configure(); in the Main.cs. The package size is 10M+, otherwise, the size is 44M+. ServiceStack Client should consider the size.

https://github.com/ServiceStackApps/HelloMobile


I have tried RestSharp. RestSharp api is not as good as SS client. But it’s very small. Just increase 2m+ in my iOS package. I hope SS Client have a fix about this and I still want to use SS Client.

Use RestSharp instead SS client I must save cookies by myself, I input code below if anyone has the same condition. You can store _cookieJar in the file or database by yourself.

         var _iServiceClient = new RestClient("http://xxx/api");
//            _iServiceClient.Authenticator = new HttpBasicAuthenticator("")
            var request = new RestRequest("/auth/credentials", Method.GET);
            request.RequestFormat = DataFormat.Json;
            request.AddQueryParameter("Username", "ghgjgh");
            request.AddQueryParameter("Password", "123456");
            request.AddQueryParameter("Remeberme", "true");
            request.AddQueryParameter("meta", "{RoleType:\"Parent\"}");

            var authResponse = _iServiceClient.Get<AuthenticateResponse>(request);
            CookieContainer _cookieJar = new CookieContainer();
            foreach (var sessionCookie in authResponse.Cookies)
            {
                _cookieJar.Add(new Cookie(sessionCookie.Name, sessionCookie.Value, sessionCookie.Path, sessionCookie.Domain));
            }
/*if you reload app again, you should recreate _cookieJar first and then you can reuse the session.   HttpBasicAuthenticator is also a good choice, but i think send username and password every time is not safe. i not very sure about that.*/

            var _iServiceClient1 = new RestClient("http://xxx/api");
            _iServiceClient1.CookieContainer = _cookieJar;
            var request1 = new RestRequest("/cities", Method.GET);
            var ret = _iServiceClient1.Get<CityModel>(request1);

Understand this is nothing to do with the size of ServiceStack Client dlls. You can read about Xamarin Application Sizes in their Docs which will show you the different sizes for the Xamarin software that make up your packaged Application.

If you check the output folder of the iOS project you’ll see the actual bytes sizes for each of the ServiceStack Client dlls, i.e:

  • 271kb for ServiceStack.Text
  • 136kb for ServiceStack.Client

and the platform-specific dll that contains IosPclExportClient is only:

  • 28kb for ServiceStack.Pcl.iOS.dll

I hope this makes it clear the 26kb footprint or actual sizes of ServiceStack Client .dlls is insignificant, it’s the mono dependencies that Xamarin links together that makes up the bulk of the App size. Not configuring the 28kb IosPclExportClient iOS platform specific implementation is not an option, it’s what binds iOS implementation to the Exported PCL API’s.

The HelloMobile iOS project was using the old ServiceStack.Client.Pcl packages which were deprecated at the end of last year before Apple forced Xamarin to move everyone to their new Unified API.

To see if it made a difference I’ve since removed System.Xml support as well as Microsoft.CSharp dependencies in ServiceStack PCL Client removes support for XmlServiceClient and dynamic from the latest v4.0.43 packages on MyGet which are both heavy technologies that shouldn’t really be used in mobile apps.

But I don’t think it helps as after creating a new iOS Phone project with the client packages I can see the size jumps from the default empty iPhone app template size of 8MB:

to 9.64MB after adding the v4.0.43 ServiceStack.Client NuGet packages:

Configuring the 28kb IosPclExportClient makes it jump to 41.36MB:

But as mentioned earlier the Client library is useless without it, I expect all this is doing is forcing Xamarin to bundle the ServiceStack Client libraries dependencies where previously it didn’t.

This is what it looks like after enabling some optimizations, after changing the iOS Build Linker behavior to link all the assemblies the size drops to 31.9MB:

Note: this isn’t recommended for reflection-heavy libraries like serializers

Then if you only wanted to support iPhone 5s+ you can enable just the ARM64 CPU Architecture which since you’re only supporting 1 CPU effectively halves the amount of space to 16.47MB:

Using ARM Thumb support at the cost of a little CPU makes the binary a little smaller at 15.45MB:

Which is the smallest it goes down to with the primary UI optimizations. But not recommended since you could run into serialization issues with Link All Assemblies. Without that optimization compiling for just ARM64 the size is 20MB.

If we look at the build output you can see all the different assemblies being included:

/lib/mono/Xamarin.iOS/System.dll
/lib/mono/Xamarin.iOS/Xamarin.iOS.dll
../packages/Xamarin.TestCloud.Agent.0.14.1/lib/Xamarin.iOS10/Calabash.dll
../packages/ServiceStack.Interfaces.4.0.43/lib/portable-*/ServiceStack.Interfaces.dll
../packages/ServiceStack.Text.4.0.43/lib/portable-*/ServiceStack.Text.dll
../packages/ServiceStack.Client.4.0.43/lib/Xamarin.iOS10/ServiceStack.Client.dll
../packages/ServiceStack.Client.4.0.43/lib/Xamarin.iOS10/ServiceStack.Pcl.iOS.dll
/lib/mono/Xamarin.iOS/System.Core.dll
/lib/mono/Xamarin.iOS/mscorlib.dll
/lib/mono/Xamarin.iOS/Facades/System.Collections.Concurrent.dll
/lib/mono/Xamarin.iOS/Facades/System.Collections.dll
/lib/mono/Xamarin.iOS/Facades/System.ComponentModel.Annotations.dll
/lib/mono/Xamarin.iOS/Facades/System.ComponentModel.EventBasedAsync.dll
/lib/mono/Xamarin.iOS/Facades/System.ComponentModel.dll
/lib/mono/Xamarin.iOS/Facades/System.Diagnostics.Contracts.dll
/lib/mono/Xamarin.iOS/Facades/System.Diagnostics.Debug.dll
/lib/mono/Xamarin.iOS/Facades/System.Diagnostics.Tools.dll
/lib/mono/Xamarin.iOS/Facades/System.Dynamic.Runtime.dll
/lib/mono/Xamarin.iOS/Facades/System.Globalization.dll
/lib/mono/Xamarin.iOS/Facades/System.IO.dll
/lib/mono/Xamarin.iOS/Facades/System.Linq.Expressions.dll
/lib/mono/Xamarin.iOS/Facades/System.Linq.Parallel.dll
/lib/mono/Xamarin.iOS/Facades/System.Linq.Queryable.dll
/lib/mono/Xamarin.iOS/Facades/System.Linq.dll
/lib/mono/Xamarin.iOS/Facades/System.Net.NetworkInformation.dll
/lib/mono/Xamarin.iOS/Facades/System.Net.Primitives.dll
/lib/mono/Xamarin.iOS/Facades/System.Net.Requests.dll
/lib/mono/Xamarin.iOS/Facades/System.ObjectModel.dll
/lib/mono/Xamarin.iOS/Facades/System.Reflection.Extensions.dll
/lib/mono/Xamarin.iOS/Facades/System.Reflection.Primitives.dll
/lib/mono/Xamarin.iOS/Facades/System.Reflection.dll
/lib/mono/Xamarin.iOS/Facades/System.Resources.ResourceManager.dll
/lib/mono/Xamarin.iOS/Facades/System.Runtime.Extensions.dll
/lib/mono/Xamarin.iOS/Facades/System.Runtime.InteropServices.WindowsRuntime.dll
/lib/mono/Xamarin.iOS/Facades/System.Runtime.InteropServices.dll
/lib/mono/Xamarin.iOS/Facades/System.Runtime.Numerics.dll
/lib/mono/Xamarin.iOS/Facades/System.Runtime.Serialization.Json.dll
/lib/mono/Xamarin.iOS/Facades/System.Runtime.Serialization.Primitives.dll
/lib/mono/Xamarin.iOS/Facades/System.Runtime.Serialization.Xml.dll
/lib/mono/Xamarin.iOS/Facades/System.Runtime.dll
/lib/mono/Xamarin.iOS/Facades/System.Security.Principal.dll
/lib/mono/Xamarin.iOS/Facades/System.ServiceModel.Http.dll
/lib/mono/Xamarin.iOS/Facades/System.ServiceModel.Primitives.dll
/lib/mono/Xamarin.iOS/Facades/System.Text.Encoding.Extensions.dll
/lib/mono/Xamarin.iOS/Facades/System.Text.Encoding.dll
/lib/mono/Xamarin.iOS/Facades/System.Text.RegularExpressions.dll
/lib/mono/Xamarin.iOS/Facades/System.Threading.Tasks.Parallel.dll
/lib/mono/Xamarin.iOS/Facades/System.Threading.Tasks.dll
/lib/mono/Xamarin.iOS/Facades/System.Threading.dll
/lib/mono/Xamarin.iOS/Facades/System.Xml.ReaderWriter.dll
/lib/mono/Xamarin.iOS/Facades/System.Xml.XDocument.dll
/lib/mono/Xamarin.iOS/Facades/System.Xml.XmlSerializer.dll
../packages/Xamarin.TestCloud.Agent.0.14.1/lib/Xamarin.iOS10/Calabash.dll
../packages/ServiceStack.Interfaces.4.0.43/lib/portable-*/ServiceStack.Interfaces.dll
../packages/ServiceStack.Text.4.0.43/lib/portable-*/ServiceStack.Text.dll
../packages/ServiceStack.Client.4.0.43/lib/Xamarin.iOS10/ServiceStack.Client.dll
../packages/ServiceStack.Client.4.0.43/lib/Xamarin.iOS10/ServiceStack.Pcl.iOS.dll

Note: directories are truncated to prevent wrapping.

A number of those .dll’s shouldn’t be needed but are still included. e.g. There’s nothing that references System.Xml in the PCL builds explicitly but the output dlls still contains a reference to System.Xml. I’ve spent the day trying to track down what’s causing the reference to System.Xml but wasn’t able to find anything. So for the time being if you want smaller binaries than above you’ll need to adopt a 3rd party HTTP library.

Thanks for your very hard work. I think we should ask help from Xamarin. I will send the results to Xmarin Support. But I don’t have enough reputations, they might ignore my request. May be you can put all of this in the Xamarin Forums. After all, you are a big fish.

I do not want to rewrite my service by RestSharp. :sob: