Skip to content

Improve footprint by allowing element selection during static link stage

Introduction

This MR intends to alleviate gst-full library by splitting the plugin into elements and add these elements to a static plugin removing all the unnecessary code from non selected elements.

By reorganizing the code after declaring all the individual element (GST_ELEMENT_REGISTER_DEFINE) from a plugin, the dead code path (elements not selected and their code dependencies) will be removed. It will result in a smaller gst-full library containing with only the set of libs and the set of plugins/elements selected.

This MR depends on other MRs to demonstrate the mechanism:

gstreamer!661 (merged): Where new defines have been introduced to declare a single element and a demonstration of the split in coreelements.

gst-plugins-base!900 (merged): With an advanced use of this mechanism (put common method in a separate file) and use of GST_ELEMENT_REGISTER_DEFINE_WITH_COE

With ELF format compilers, linkers are able to drop dead code which are not used. We could use -gc-sections linker flag but the result might be unpredictable (see below).

Two concepts have been introduced:

  • Declare all elements to be registered by another plugin
  • Separate the code to avoid full object inclusion when only one method from an object is necessary

That's why I introduced first in gst/gstelement.h the macros to declare the elements.:

  • GST_ELEMENT_REGISTER_DEFINE(element,name,rank,type): Declare a method containing gst_element_register with a element decalration as before(name,rank etc.). This method will be called with a given plugin, ie gst_init_static_plugins() generated by gst-build in build-dir/gstinitstaticplugins.c.

  • GST_ELEMENT_REGISTER_DEFINE_WITH_CODE(element, name,rank,type, code): Declare a method which call another piece ofinit_method`. This method usually calls a common init (once) and gst_element_register (see alsa or playback in gst-plugins-base!900 (merged))

  • GST_ELEMENT_REGISTER_DEFINE_CUSTOM(element, method): This method allows to create the gst_element_register method and call directly a method instead of defining the method with rank, type etc. See playbin3 in gst-plugins-base!900 (merged)

Then in gst-plugins-base!900 (merged) I put the common element_init method in a separate file from plugin.c to gstpluginnameelement.c to avoid dragging all the code from the other plugin's element and use the rule for the linker by separating the code in individual objects:

=> If there is one method from an object necessary, all the methods from the object will be kept.

Then I created a gstpluginnameelement.c(optional) containing the common init method and gstpluginnameelement.h(always) containing the GST_ELEMENT_REGISTER_DECLARE macros for all the elements of a plugin.

With this approach we avoid to use gc-sections and -ffunctions-section -fdata-section where the benefits can be undefined:

Only use these options when there are significant benefits from doing so. When you specify these options, the assembler and linker create larger object and executable files and are also slower. You cannot use gprof on all systems if you specify this option, and you may have problems with debugging if you specify both this option and -g.

On gst-build side, the only change here is to introduce gst-full-elements option which will allow to select the elements from a given plugin and generates gstinitstaticplugins.c.

Syntax:

-Dgst-full-elements=coreelements;playback:playbin,decodebin;alsa:alsasink

In gst-full only these elements will be present:

  • coreelements plugin with all his elements
  • playbin, decodebin from playback and alsasink from alsa in a plugin named NULL

example to demonstrate the gain. Here if we are

meson build-gst-full  -Ddoc=disabled -Dintrospection=disabled -Dtests=enabled -Dpython=disabled -Dbuildtype=release -Ddefault_library=static -Dgst-full-version-script= -Dgst-full-elements=coreelements:filesrc,fakesink,identity '-Dgst-full-libraries=[]' -Dbad=disabled -Dugly=disabled -Dlibav=disabled -Dlibav=disabled -Dbase=disabled -Dgood=disabled -Dbackend=ninja

Here is some numbers where only filesrc, identity and fakesink are enabled:

lib (stripped) 1 2
ligstreamer-full.so 2197016 1649592
  1. before any mods in gst repos (except removing base and good from the build, see commit): build without -Dgst-full-elements=coreelements:filesrc,fakesink,identity in the meson command line.
  2. Final build with command line above.

This work has been performed in collaboration with @julian, @gdesmott, @xclaesse, @ocrete.

Edited by Stéphane Cerveau

Merge request reports