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

Reduce framework size #1329

Open
Banck opened this issue Dec 14, 2021 · 19 comments
Open

Reduce framework size #1329

Banck opened this issue Dec 14, 2021 · 19 comments
Labels

Comments

@Banck
Copy link

Banck commented Dec 14, 2021

Hello.
We are using grpc in project, which has App Clip,so that’s why we care about the size of the application (there is limit of 10 mb of uncompressed app).
grpc integration (via spm) increased uncompressed app size by about 6.5 mb.
Maybe there are any solutions to reduce framework size?
Thanks.

@Banck Banck added the question label Dec 14, 2021
@Lukasa
Copy link
Collaborator

Lukasa commented Dec 15, 2021

Can I recommend stripping the app binary? Much of the size is likely to be symbols, and these can easily be removed by stripping them. Otherwise, you can try enabling -Osize optimizations. Beyond that, there are no ways to reduce binary size in SwiftPM.

@Banck
Copy link
Author

Banck commented Dec 16, 2021

-0size doesn't help. It reduced app clip size from 9.4 mb to 9.3 mb)
Would't like to use a proxy for the grpc in App Clip, but grpc integration increases size a lot(

@Banck
Copy link
Author

Banck commented Dec 17, 2021

Tried switch from SPM to Cocoapods and AppClip uncompressed size increased from 9.4 mb to 11.5 mb 😨

If change use_frameworks! to use_modular_headers! uncompressed size will be 8.4 mb.

@Lukasa
Copy link
Collaborator

Lukasa commented Jan 4, 2022

Have you tried stripping the binary?

@Banck
Copy link
Author

Banck commented Jan 11, 2022

Have you tried stripping the binary?
I have bitcode, Strip linked product, Dead code Stripping enabled.
I've tried enable Strip debug symbols during copy for main target and app clip target, but app size didn't change.

App clip size with bitcode, Strip linked product, Dead code Stripping enabled:
App Thinning Size Report Supported variant descriptors: Universal

  1. Cocoapods with use_modular_headers!
    App size: 3,9 MB compressed, 8,9 MB uncompressed

  2. SPM

image

a) [-O]
App size: 4,3 MB compressed, 9,9 MB uncompressed

b) Swift compiler: [-Osize], Apple clang Optimization level: [-0s]
App size: 4,3 MB compressed, 9,8 MB uncompressed

c) Swift compiler: [-Osize], Apple clang Optimization level: [-0z]
App size: 4,3 MB compressed, 9,8 MB uncompressed

Don't know what can I do else to reduce grpc lib size

@Lukasa
Copy link
Collaborator

Lukasa commented Jan 11, 2022

Thanks @Banck. Can you run the analyze_code_size.py script from Swift against your app clip and provide the output here? The invocation is probably something like: analyze_code_size.py -categorize <path/to/your/binary>.

@Banck
Copy link
Author

Banck commented Jan 11, 2022

Thanks @Banck. Can you run the analyze_code_size.py script from Swift against your app clip and provide the output here? The invocation is probably something like: analyze_code_size.py -categorize <path/to/your/binary>.

  1. Cocoapods
    Cocoapods.txt
  2. SPM
    SPM.txt

@Lukasa
Copy link
Collaborator

Lukasa commented Jan 11, 2022

Hah, sorry, can you remove the symbol stripping before you do this? That data is not all that useful without the symbols, as all we can tell is that we're using the code size mostly with code.

I also want to point out apple/swift-protobuf#1204.

@Banck
Copy link
Author

Banck commented Jan 11, 2022

Hah, sorry, can you remove the symbol stripping before you do this? That data is not all that useful without the symbols, as all we can tell is that we're using the code size mostly with code.

I also want to point out apple/swift-protobuf#1204.

Disabled Bitcode and applied these settings:
image

  1. Cocoapods:
    App size: 6,4 MB compressed, 24,1 MB uncompressed
    Cocoapods.txt

  2. SPM

image

App size: 7 MB compressed, 26,3 MB uncompressed
SPM.txt

let me know if I did something wrong or if something needs to be done additionally. Thank you

@Banck
Copy link
Author

Banck commented Jan 11, 2022

I also want to point out apple/swift-protobuf#1204.

When I wrote the first message, I measured app size, then integrated grpc with 1 simple proto file, and measured again. The size difference was around 6.5 mb.

@Lukasa
Copy link
Collaborator

Lukasa commented Jan 11, 2022

Is it possible for you to compare with only the impact from swift-protobuf? I'd like to isolate how much is grpc-swift. Keep your .proto files the same, but don't generate the grpc sources, only the regular protobuf ones?

@Banck
Copy link
Author

Banck commented Jan 11, 2022

Is it possible for you to compare with only the impact from swift-protobuf? I'd like to isolate how much is grpc-swift. Keep your .proto files the same, but don't generate the grpc sources, only the regular protobuf ones?

I measured app size with bitcode and stripping and integrated grpc via SPM:
App size: 4,3 MB compressed, 9,9 MB uncompressed

Then removed all services, generated before and generated only models via comand:
protoc *.proto --swift_out=../Common/Models/Network/GRPC

  1. Commented all my code related with services. Commented import GRPC in files:
    App size: 4,3 MB compressed, 9,8 MB uncompressed

  2. removed GRPC from spm
    a) added NIO, NIOHTTP2, Logging and protobuf:

image

App size: 3,1 MB compressed, 7,1 MB uncompressed

b) added these libs:

image

App size: 3,3 MB compressed, 7,5 MB uncompressed

@Banck
Copy link
Author

Banck commented Jan 12, 2022

And sure, only with SwiftProtobuf:
App size: 2,1 MB compressed, 4,3 MB uncompressed

@Lukasa
Copy link
Collaborator

Lukasa commented Jan 12, 2022

Ok, so based on those numbers, the big code size contributor appears to be NIO. This is not necessarily a huge surprise to me: NIOPosix is a particularly large library. Can you clarify: is your project directly importing and depending on NIO, or on NIOCore?

@Lukasa
Copy link
Collaborator

Lukasa commented Jan 12, 2022

For my own future reference:

  • Protobuf only: 2.1 MB compressed, 4.3 MB uncompressed
  • Protobuf, NIO, NIOHTTP2, Logging: 3.1 MB compressed, 7.1 MB uncompressed
  • All extra libraries including grpc: 3.3 MB compressed, 7.5 MB uncompressed

This sure implies that NIO is the bulk of the weight. NIOCore should not be that heavy, but NIOPosix may well be.

@Banck
Copy link
Author

Banck commented Jan 12, 2022

Yes, I do import NIO and import NIOCore in my services, because grpc returns EventLoopFuture and I working with it, which is part of swiftNIO.

@Banck
Copy link
Author

Banck commented Jan 12, 2022

For my own future reference:

  • Protobuf only: 2.1 MB compressed, 4.3 MB uncompressed
  • Protobuf, NIO, NIOHTTP2, Logging: 3.1 MB compressed, 7.1 MB uncompressed
  • All extra libraries including grpc: 3.3 MB compressed, 7.5 MB uncompressed

This sure implies that NIO is the bulk of the weight. NIOCore should not be that heavy, but NIOPosix may well be.

7.5 mb - it's without grpc.
Grpc with all dependecies(nio, protobuf):
App size: 4,3 MB compressed, 9,8 MB uncompressed

@Lukasa
Copy link
Collaborator

Lukasa commented Jan 12, 2022

@Banck It's part of SwiftNIO, but we recently split the NIO module up into three modules: NIOCore, NIOEmbedded, and NIOPosix. This is because for iOS apps, NIOPosix is not really necessary, but it still costs code size.

Now, unfortunately grpc itself still requires NIOPosix. We don't really have great tools for making that functionality conditional at the moment, so it's extremely hard to remove.

@Banck
Copy link
Author

Banck commented Jun 16, 2022

I've noticed, that through SPM I can install grpc without swift-nio-ssl, cause Package.swift contains:

let includeNIOSSL = ProcessInfo.processInfo.environment["GRPC_NO_NIO_SSL"] == nil
.package(
    url: "https://github.com/apple/swift-nio-ssl.git",
    from: "2.14.0"
  ),
  if: includeNIOSSL

And this allowed us to reduce the size of the application by 1.5 mb
from
App size: 4,8 MB compressed, 11,3 MB uncompressed
to
App size: 4 MB compressed, 9,8 MB uncompressed

If install grpc through cocoapods app size is
App size: 4,2 MB compressed, 10 MB uncompressed

I just wonder how can install grpc through cocoapods also without swift-nio-ssl ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants