byteverse / haskell-ip

IP Address implementation
Other
20 stars 19 forks source link

Large dependency footprint. Split into separate packages? #68

Open dminuoso opened 3 years ago

dminuoso commented 3 years ago

Right now the presence of the aeson and byte* dependencies makes for a sizable footprint of ip. This to me makes ip an uninteresting candidate for use in libraries that just need to carry IP or Mac data around, but may not even have to parse them (or it parses them directly off a wire protocol).

The typical choice seems to be, to provide a package ip-core that exposes only the basic types/bindings/instances, and then ip as a wholesale meal with orphan instances and parser utilities. This is similar to the yesod-ip package.

Aside from bumping a major version to satisfy PVP, this should have no other impact on users.

What do you think? I'd be willing to do the work to get it done.

andrewthad commented 3 years ago

I'm am somewhat against this change because I don't think the benefit from this is worth the cost. In libraries where I need to represent, for example, IPv4 addresses, but I don't need any of the machinery from ip, I typically just use a Word32. But let's consider how this would need to be set up, just in case the tide ever changes. We would need:

I think that's how it would get split up if we were going to do this. But at the moment, I'm not convinced that this is really worth doing.

dminuoso commented 2 years ago

This library has 75 transitive dependencies, roughly ~50 of which are from aeson alone.

haskell-ip dependency footprint

This drives up compilation time, makes auditing transitive updates harder, increases build plan complications (as a nix user this regularly affecfts me), and has quite a hefty penalty on object size in the absence of split sections + stripping. And it might deter some users.

A simple IP library should not have some "batteries-included" type of footprint like a web framework.

chessai commented 2 years ago

This library has 75 transitive dependencies, roughly ~50 of which are from aeson alone.

haskell-ip dependency footprint

This drives up compilation time, makes auditing transitive updates harder, increases build plan complications (as a nix user this regularly affecfts me), and has quite a hefty penalty on object size in the absence of split sections + stripping. And it might deter some users.

A simple IP library should not have some "batteries-included" type of footprint like a web framework.

I've been writing rust for a while now and one thing their packages have, which I wish Haskell's did, is feature flags. Feature flags can be on or off by default. In some cases, feature flags can be used to distinguish between async runtimes (example). They're a very versatile feature with a high power-to-weight ratio and smooth UX. In Haskell we have CPP flags, which are more annoying to use, but get the job done. In short, I think these features should be behind CPP flags, and be on or off by default depending on what's reasonable. They're easy enough to override with cabal, stack, and nix. You won't get caching with nix this way, though, unless nixpkgs or haskell.nix start doing something with combinations of flags (doubtful), or unless you start hosting your own infra (which I have done many times).

Splitting stuff out into multiple packages achieves the same effect but with more burden on maintainers, IMO.

dminuoso commented 2 years ago

So this is an interesting proposition. The main downfall is that flags cannot be specified in .cabal files, they are cabal.project settings. Because of this aeson and byte* would have to be enabled by default. Also, any user who does disable these should probably make sure it builds with these flags enabled as well, but that's just for their sake.

Added benefit is that it has no impact on all existing users. Thoughts @andrewthad?

I'd be willing to implement this.

chessai commented 2 years ago

So this is an interesting proposition. The main downfall is that flags cannot be specified in .cabal files, they are cabal.project settings. Because of this aeson and byte* would have to be enabled by default. Also, any user who does disable these should probably make sure it builds with these flags enabled as well, but that's just for their sake.

Added benefit is that it has no impact on all existing users. Thoughts @andrewthad?

I'd be willing to implement this.

To my knowledge, cabal.project just creates the relevant arguments for Setup.hs, though without the cabal.project I believe that you must specify flags at the command line with eg --constraint='pkg +flag'.

However I don't really think this is much of a downside, cabal.projects are so useful, to the point I use them in most of my projects and I wish they were just part of .cabal, and stack and nix already support this option without additional files.

andrewthad commented 2 years ago

I'm fine with a feature flag that removes the aeson dependency (and all related instances). If anyone wants to implement this, I would accept a PR.