Porque é que a inicialização de um aplicativo no Linux mais lento quando se utiliza bibliotecas compartilhadas?

StackOverflow https://stackoverflow.com/questions/1410691

  •  05-07-2019
  •  | 
  •  

Pergunta

No dispositivo incorporado que estou trabalhando, o tempo de inicialização é uma questão importante. Todo o aplicativo consiste em vários executáveis ??que usam um conjunto de bibliotecas. Como o espaço na memória FLASH é limitado gostaríamos de usar bibliotecas compartilhadas.

Os workes aplicação como de costume quando compilado e vinculado com bibliotecas compartilhadas e a quantidade de memória FLASH é reduzido conforme o esperado. A diferença para a versão que está ligado a bibliotecas estáticas é que o tempo de inicialização do aplicativo é de cerca de 20 anos mais e não tenho idéia do porquê.

O aplicativo é executado em uma CPU ARM9 a 180 MHz com Linux 2.6.17 OS, 16 MB FLASH (Sistema JFFS Arquivo) e 32 MB RAM.

Foi útil?

Solução

Bacause bibliotecas compartilhadas tem que ser ligado a pelo tempo de execução, geralmente por dlopen () ou algo similar. Não há tal passo para bibliotecas estáticas.

Edit: mais alguns detalhes. dlopen tem que realizar as seguintes tarefas.

  • Encontre a biblioteca compartilhada
  • Coloque-o na memória
  • Recursively carregar todas as dependências (e suas dependências ....)
  • Resolver todos os símbolos

Isto requer um monte de operações de IO de realizar.

Em um programa ligado estaticamente todos os itens acima é feito em tempo de compilação, não em tempo de execução. Portanto, é muito mais rápido para carregar um programa ligado estaticamente.

No seu caso, a diferença é exagerada pelo hardware relativamente lento o seu código tem que correr.

Outras dicas

Este é um belo exemplo da troca clássica de velocidade e espaço.

Você estaticamente pode ligar todos os seus arquivos executáveis ??de modo que eles são mais rápidos, mas depois eles vão ter mais espaço

ou

Você pode ter bibliotecas que tomam menos espaço, mas também mais tempo para carga compartilhada.

Portanto, decidir o que você quer sacrificar.

Há muitos fatores para essa diferença (OS, compilador etc), mas uma boa lista de razões podem ser encontrados aqui . bibliotecas basicamente compartilhadas foram criadas por razões de espaço e grande parte da "mágica" envolvidos para torná-los trabalho tem um impacto no desempenho.

(Como uma nota histórica do navegador Netscape original no Linux / Unix foi um grande executável gordura estaticamente ligado).

Isto pode ajudar outras pessoas com problemas semelhantes:

A razão pela qual a inicialização demorou tanto tempo no meu caso era que a configuração padrão do GCC é exportar todos os símbolos dentro de uma biblioteca. Uma grande melhoria é estabelecer um ambiente de compilador "-fvisibility = escondida".

Todos os símbolos que o lib tem para exportação tem que ser aumentada com a declaração

__attribute__ ((visibility("default")))

gcc wiki
eo artigo muito bem como escrever bibliotecas compartilhadas

Ok, eu aprendi agora que o uso de bibliotecas compartilhadas tem suas disadvatages referente à velocidade. Eu encontrei este artigo sobre ligação dinâmica e carregamento enlighting. O processo de carregamento parece ser muito mais longas do que eu esperava.

Interessante .. tempo normalmente carregar para uma biblioteca compartilhada é imperceptível a partir de um aplicativo de gordura que é ligado estaticamente. Então eu só posso supor que o sistema está muito lento para carregar uma biblioteca de memória flash, ou a biblioteca que é carregada está a ser verificada, de alguma forma (por exemplo .NET os aplicativos executar um checksum para todas as DLLs carregadas, reduzindo o tempo de inicialização consideravelmente em alguns casos). Pode ser que as bibliotecas compartilhadas estão sendo carregados conforme a necessidade, e descarregados depois o que poderia indicar um problema de configuração.

Então, desculpe, eu não posso ajudar, dizer por que, mas eu acho que é um problema com o dispositivo ARM / OS. Você tentou instrumentar o código de inicialização, ou estaticamente vinculação com 1 das bibliotecas mais comumente usados ??para ver se isso faz uma grande diferença. colocar também as bibliotecas compartilhadas no mesmo diretório como o aplicativo para reduzir o tempo que leva para pesquisar os FS para o lib.

Uma opção que parece óbvio para mim, é estaticamente ligar os vários programas de todos em um único binário. Dessa forma, você continuará a compartilhar tanto código quanto possível (provavelmente mais do que antes), mas você também vai evitar a sobrecarga do vinculador dinâmico e salvar o espaço de ter o vinculador dinâmico no sistema em tudo.

É muito fácil de combinar vários executáveis ??na mesma, você normalmente apenas examinar argv e decidir qual rotina de chamada com base nisso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top