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

Yams without Foundation? #358

Open
t089 opened this issue Dec 9, 2022 · 9 comments
Open

Yams without Foundation? #358

t089 opened this issue Dec 9, 2022 · 9 comments

Comments

@t089
Copy link

t089 commented Dec 9, 2022

The state of Foundation on non Apple platforms continues to be less than ideal and brings the additional burden of increased binary size and memory footprint. Many libraries take effort the factor out their Foundation dependency in a separate module (eg. karwa/swift-url, apple/swift-nio, discussion swift-server/async-http-client, ...).

As an example, a simple "Hello World" Swift binary compiled with swift build -c release --static-swift-stdlib on swift:5.7.1 weighs in at 7.6M. Adding the Yams dependency increases the binary size to 50M.

Of course, not relying on Foundation is not trivial, but would be good to at least map out what would need to be done to make it happen.

@t089
Copy link
Author

t089 commented Dec 9, 2022

🤔 Bad timing, maybe there is something brewing at the fruit company.
https://twitter.com/ktosopl/status/1601145297077686272?s=46&t=C2w1wZhSOLAErfvayJ24KQ

@jpsim
Copy link
Owner

jpsim commented Dec 9, 2022

As an example, a simple "Hello World" Swift binary compiled with swift build -c release --static-swift-stdlib on swift:5.7.1 weighs in at 7.6M. Adding the Yams dependency increases the binary size to 50M.

Yikes, that's a pretty heavy dependency.

Why do you need the statically compile the Swift stdlib if you're running it on what appears to be a Docker image with Swift installed?

On macOS, a simple import Yams; print(try Yams.load(yaml: "a: 0")!) CLI executable is 920 KB when built for release for arm64.

@t089
Copy link
Author

t089 commented Dec 9, 2022

Why do you need the statically compile the Swift stdlib if you're running it on what appears to be a Docker image with Swift installed?

Usually, we build on docker swift:5.7 but then deploy on a distroless image which has no (swift) runtime dependencies pre-installed to make the final image as small as possible.

@jpsim
Copy link
Owner

jpsim commented Dec 9, 2022

ok that makes sense.

I hacked up a proof-of-concept to remove Foundation here: https://github.com/jpsim/Yams/compare/jp-no-foundation

It removes a ton of useful features from Yams, but it gets the following compiling without Foundation:

import Yams

let yaml = """
a: 0
b: 1.2
c: [1, 2, 3]
d:
  - a
  - b
  - c
"""

dump(try Yams.load(yaml: yaml)!)

And it builds and runs on Linux

$ docker run -it -v `pwd`:`pwd` -w `pwd` swift:latest swift run -c release
Building for production...
Build complete! (0.20s)
▿ 4 key/value pairs
  ▿ (2 elements)
    ▿ key: AnyHashable("a")
      - value: "a"
    - value: 0
  ▿ (2 elements)
    ▿ key: AnyHashable("d")
      - value: "d"
    ▿ value: 3 elements
      - "a"
      - "b"
      - "c"
  ▿ (2 elements)
    ▿ key: AnyHashable("b")
      - value: "b"
    - value: 1.2
  ▿ (2 elements)
    ▿ key: AnyHashable("c")
      - value: "c"
    ▿ value: 3 elements
      - 1
      - 2
      - 3

There are linker errors when passing --static-swift-stdlib though, so that would need to be sorted out.

But his demonstrates that the core functionality of Yams should be usable without the Foundation dependency.

@t089
Copy link
Author

t089 commented Dec 9, 2022

Nice, that's already a great start. I think you also removed the entire Codable support, that seems like a big loss and sth we should look into maybe. I will check it out in more details as well.

@jpsim
Copy link
Owner

jpsim commented Dec 9, 2022

Nice, that's already a great start. I think you also removed the entire Codable support, that seems like a big loss and sth we should look into maybe. I will check it out in more details as well.

Yes, I removed most of what wasn't needed for my simple Yams.load(yaml:) demo. It's a proof-of-concept and not something meant to be seriously considered, I just wanted to show that the core Yams functionality doesn't strictly require Foundation.

@jpsim
Copy link
Owner

jpsim commented Dec 9, 2022

Re-added YAMLDecoder:

let bandYAML = """
members:
  - name: John Coltrane
    age: 27
  - name: Miles Davis
    age: 23
"""

struct Person: Codable {
    let name: String
    let age: Int
}

struct Band: Codable {
    let members: [Person]
}

let band = try YAMLDecoder().decode(Band.self, from: bandYAML)
dump(band)
$ docker run -it -v `pwd`:`pwd` -w `pwd` swift:latest swift run -c release
Building for production...
Build complete! (0.19s)
▿ 4 key/value pairs
  ▿ (2 elements)
    ▿ key: AnyHashable("b")
      - value: "b"
    - value: 1.2
  ▿ (2 elements)
    ▿ key: AnyHashable("d")
      - value: "d"
    ▿ value: 3 elements
      - "a"
      - "b"
      - "c"
  ▿ (2 elements)
    ▿ key: AnyHashable("a")
      - value: "a"
    - value: 0
  ▿ (2 elements)
    ▿ key: AnyHashable("c")
      - value: "c"
    ▿ value: 3 elements
      - 1
      - 2
      - 3
▿ yams_cli.Band
  ▿ members: 2 elements
    ▿ yams_cli.Person
      - name: "John Coltrane"
      - age: 27
    ▿ yams_cli.Person
      - name: "Miles Davis"
      - age: 23

@jpsim
Copy link
Owner

jpsim commented Dec 9, 2022

It's definitely possible to do this for real, not just as a proof-of-concept demo, it's just a matter of refactoring and time.

Also some questions around what to do for Foundation types. Should Date, UUID & Data just be parsed as String?

@t089
Copy link
Author

t089 commented Dec 10, 2022

It's definitely possible to do this for real, not just as a proof-of-concept demo, it's just a matter of refactoring and time.

That's really cool. I think it would be a great initiative.

Also some questions around what to do for Foundation types. Should Date, UUID & Data just be parsed as String?

Probably yes. The alternative to Data usually is a simple [UInt8].

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

No branches or pull requests

2 participants