Mesmo programas trivialmente pequenos de Haskell se transformam em executáveis gigantescos.
Eu escrevi um pequeno programa, que foi compilado (com GHC) no binário com o tamanho de 7 MB!
O que pode fazer com que até mesmo um pequeno programa Haskell seja compilado no enorme binário?
O que posso fazer para reduzir isso?
strip
no binário para remover a tabela de símbolos.strip test
. Este comando remove algumas informações de depuração do programa e as reduz.data M3 = M3 !V3 !V3 !V3
edata V3 = V3 !Float !Float !Float
. Compile comghc -O2 -funbox-strict-fields
.Respostas:
Vamos ver o que está acontecendo, tente
Você vê pela
ldd
saída que o GHC produziu um executável vinculado dinamicamente, mas apenas as bibliotecas C estão dinamicamente vinculadas ! Todas as bibliotecas Haskell são copiadas literalmente.Além disso: como esse é um aplicativo com muitos gráficos, eu definitivamente compilaria com
ghc -O2
Há duas coisas que você pode fazer.
Símbolos de remoção
Uma solução fácil: retire o binário:
A faixa descarta símbolos do arquivo do objeto. Eles geralmente são necessários apenas para depuração.
Bibliotecas Haskell vinculadas dinamicamente
Mais recentemente, o GHC ganhou suporte para vinculação dinâmica das bibliotecas C e Haskell . A maioria das distros agora distribui uma versão do GHC criada para oferecer suporte à vinculação dinâmica de bibliotecas Haskell. As bibliotecas Haskell compartilhadas podem ser compartilhadas entre muitos programas Haskell, sem copiá-las no executável a cada vez.
No momento da escrita, Linux e Windows são suportados.
Para permitir que as bibliotecas Haskell sejam vinculadas dinamicamente, você precisa compilá-las da seguinte
-dynamic
maneira:Além disso, todas as bibliotecas que você deseja compartilhar devem ser construídas com
--enabled-shared
:E você terminará com um executável muito menor, com as dependências C e Haskell resolvidas dinamicamente.
E, voilà!
que você pode tirar para torná-lo ainda menor:
Um executável eensy weensy, construído a partir de várias partes C e Haskell vinculadas dinamicamente:
Um ponto final: mesmo em sistemas com vinculação estática, você pode usar -split-objs para obter um arquivo .o por função de nível superior, o que pode reduzir ainda mais o tamanho das bibliotecas vinculadas estaticamente. Ele precisa que o GHC seja construído com -split-objs, o que alguns sistemas esquecem de fazer.
fonte
cabal install
tira o binário instalado por padrão?enable-shared
foi considerado. launchpad.net/ubuntu/+source/pandoc/+bugsHaskell usa vinculação estática por padrão. Ou seja, todas as ligações ao OpenGL são copiadas para o seu programa. Como eles são muito grandes, seu programa é inflado desnecessariamente. Você pode contornar isso usando o vínculo dinâmico, embora não esteja ativado por padrão.
fonte
--enabled-shared
", portanto, se a sua plataforma Haskell vier com bibliotecas criadas sem que--enabled shared
você precise recompilar as bibliotecas base, o que pode ser bastante doloroso.