diff --git a/aidge_core/export_utils/export_registry.py b/aidge_core/export_utils/export_registry.py
index dd200ac8bc2d6f9b5ee869e58df50e56d1a42936..b0f77a783b43f273277eca74750626417cb1c2b5 100644
--- a/aidge_core/export_utils/export_registry.py
+++ b/aidge_core/export_utils/export_registry.py
@@ -56,7 +56,7 @@ class ExportLib(): # Should be abstract ?
         if len(cls._export_node_registry[node.type()]) != 1:
             raise RuntimeError("ExportLib registry doesn't support when multiple export node are available yet ...")
         else:
-            return cls._export_node_registry[node.type()][0](node)
+            return cls._export_node_registry[node.type()][0]
     @classmethod
     def add_export_node(cls, key:str, eNode:ExportNode)->None:
         if key not in cls._export_node_registry:
diff --git a/aidge_core/export_utils/node_export.py b/aidge_core/export_utils/node_export.py
index d311e43aa5374471ce48a681198d4a9e6e470c9b..dff852c1660d3fb8ce35c6348d275fbce7bac8d1 100644
--- a/aidge_core/export_utils/node_export.py
+++ b/aidge_core/export_utils/node_export.py
@@ -3,6 +3,8 @@ from pathlib import Path
 
 from aidge_core.export_utils import data_conversion, code_generation
 from abc import ABC, abstractmethod
+from typing import List
+
 
 def get_chan(tensor: aidge_core.Tensor) -> int:
     """Given a tensor return the number of channel
@@ -10,9 +12,9 @@ def get_chan(tensor: aidge_core.Tensor) -> int:
     dformat = tensor.dformat()
     dims = tensor.dims()
     if dformat == aidge_core.dformat.Default:
-        if len(dims) == 4: # Suppose NCHW
+        if len(dims) == 4:  # Suppose NCHW
             return dims[1]
-        elif len(dims) == 2: # Suppose NC
+        elif len(dims) == 2:  # Suppose NC
             return dims[1]
         else:
             return None
@@ -36,9 +38,9 @@ def get_height(tensor: aidge_core.Tensor) -> int:
     dformat = tensor.dformat()
     dims = tensor.dims()
     if dformat == aidge_core.dformat.Default:
-        if len(dims) == 4: # Suppose NCHW
+        if len(dims) == 4:  # Suppose NCHW
             return dims[2]
-        elif len(dims) == 2: # Suppose NC
+        elif len(dims) == 2:  # Suppose NC
             return 1
         else:
             return None
@@ -62,9 +64,9 @@ def get_width(tensor: aidge_core.Tensor) -> int:
     dformat = tensor.dformat()
     dims = tensor.dims()
     if dformat == aidge_core.dformat.Default:
-        if len(dims) == 4: # Suppose NCHW
+        if len(dims) == 4:  # Suppose NCHW
             return dims[3]
-        elif len(dims) == 2: # Suppose NC
+        elif len(dims) == 2:  # Suppose NC
             return 1
         else:
             return None
@@ -111,7 +113,7 @@ class ExportNode(ABC):
     """
 
     @abstractmethod
-    def __init__(self, aidge_node: aidge_core.Node) -> None:
+    def __init__(self, aidge_node: aidge_core.Node, mem_info: List[dict]) -> None:
         """Create ExportNode and retieve attriubtes from ``aidge_node``:
         """
 
@@ -150,6 +152,20 @@ class ExportNode(ABC):
         self.attributes["out_height"] = [None] * self.attributes["nb_out"]
         self.attributes["out_width"] = [None] * self.attributes["nb_out"]
 
+        # Producer don't have meminfo
+        # TODO: document this attribute
+        # true if node have meminfo else false
+        self.attributes["meminfo"] = self.node.type() != "Producer"
+        if self.attributes["meminfo"]:
+            self.attributes["mem_info_size"] = [None] * self.attributes["nb_out"]
+            self.attributes["mem_info_offset"] = [None] * self.attributes["nb_out"]
+            self.attributes["mem_info_stride"] = [None] * self.attributes["nb_out"]
+            self.attributes["mem_info_length"] = [None] * self.attributes["nb_out"]
+            self.attributes["mem_info_cont_size"] = [None] * self.attributes["nb_out"]
+            self.attributes["mem_info_cont_offset"] = [None] * self.attributes["nb_out"]
+            self.attributes["mem_info_wrap_offset"] = [None] * self.attributes["nb_out"]
+            self.attributes["mem_info_wrap_size"] = [None] * self.attributes["nb_out"]
+
         for idx, parent_node_in_id in enumerate(self.node.inputs()):
             parent_node, out_id = parent_node_in_id
             self.inputs.append(parent_node)
@@ -167,7 +183,8 @@ class ExportNode(ABC):
             else:
                 print(f"No input for {self.node.name()}")
         for idx, list_child_node_in_id in enumerate(self.node.outputs()):
-            self.outputs += [node_in_id[0] for node_in_id in list_child_node_in_id]
+            self.outputs += [node_in_id[0]
+                             for node_in_id in list_child_node_in_id]
             if self.operator.get_output(idx) is not None:
                 tensor = self.operator.get_output(idx)
                 self.attributes["out_name"][idx] = f"{self.attributes['name']}_output_{idx}"
@@ -179,11 +196,47 @@ class ExportNode(ABC):
                 self.attributes["out_chan"][idx] = get_chan(tensor)
                 self.attributes["out_height"][idx] = get_height(tensor)
                 self.attributes["out_width"][idx] = get_width(tensor)
+                # Output meminfo
+                # TODO: add to docstring
+                if self.attributes["meminfo"]:
+                    if "size" in mem_info[idx]:
+                        self.attributes["mem_info_size"][idx] = mem_info[idx]["size"]
+                    else:
+                        raise RuntimeError("Size is mandatory")
+                    if "offset" in mem_info[idx]:
+                        self.attributes["mem_info_offset"][idx] = mem_info[idx]["offset"]
+                    else:
+                        raise RuntimeError("Offset is mandatory")
+                    if "stride" in mem_info[idx]:
+                        self.attributes["mem_info_stride"][idx] = mem_info[idx]["stride"]
+                    else:
+                        self.attributes["mem_info_stride"][idx] = mem_info[idx]["size"]
+                    if "length" in mem_info[idx]:
+                        self.attributes["mem_info_length"][idx] = mem_info[idx]["length"]
+                    else:
+                        self.attributes["mem_info_length"][idx] = tensor.size()
+                    if "cont_size" in mem_info[idx]:
+                        self.attributes["mem_info_cont_size"][idx] = mem_info[idx]["cont_size"]
+                    else:
+                        self.attributes["mem_info_cont_size"][idx] = tensor.size()
+                    if "cont_offset" in mem_info[idx]:
+                        self.attributes["mem_info_cont_offset"][idx] = mem_info[idx]["cont_offset"]
+                    else:
+                        self.attributes["mem_info_cont_offset"][idx] = 0
+                    if "cont_offset" in mem_info[idx]:
+                        self.attributes["mem_info_wrap_offset"][idx] = mem_info[idx]["wrap_offset"]
+                    else:
+                        self.attributes["mem_info_wrap_offset"][idx] = 0
+                    if "wrap_size" in mem_info[idx]:
+                        self.attributes["mem_info_wrap_size"][idx] = mem_info[idx]["wrap_size"]
+                    else:
+                        self.attributes["mem_info_wrap_size"][idx] = 0
             else:
                 print(f"No output for {self.node.name()}")
+
     @classmethod
     @abstractmethod
-    def exportable(cls, node: aidge_core.Node)->bool:
+    def exportable(cls, node: aidge_core.Node) -> bool:
         """Given a :py:class:`aidge_core.Node` return if the node can be exported or not.
 
         :param node: Node to test the exportability
@@ -193,6 +246,7 @@ class ExportNode(ABC):
         """
         pass
 
+
 class ExportNodeCpp(ExportNode):
     # Path to the template defining how to export the node definition
     config_template: str = None
@@ -229,8 +283,9 @@ class ExportNodeCpp(ExportNode):
                 kernel_path,
                 str(export_folder / "include" / self.kernels_path)
             )
-            kernel_include_list.append(self.kernels_path + "/" + kernel_path.stem + kernel_path.suffix)
-        path_to_definition =  f"layers/{self.attributes['name']}.h"
+            kernel_include_list.append(
+                self.kernels_path + "/" + kernel_path.stem + kernel_path.suffix)
+        path_to_definition = f"layers/{self.attributes['name']}.h"
         code_generation.generate_file(
             str(export_folder / path_to_definition),
             self.config_template,
diff --git a/aidge_core/mem_info.py b/aidge_core/mem_info.py
new file mode 100644
index 0000000000000000000000000000000000000000..0541ccf4f58cc281216ead354672267af7a180d9
--- /dev/null
+++ b/aidge_core/mem_info.py
@@ -0,0 +1,133 @@
+import os
+import shutil
+from pathlib import Path
+import aidge_core
+from typing import Tuple, List
+
+
+# Default memory management, which can be used for development
+def compute_default_mem_info(scheduler: aidge_core.Scheduler) -> Tuple[int, List]:
+    """Basic memory management concatenate memory block, no memory reuse !
+
+    :param scheduler: Aidge scheduler
+    :type scheduler: :py:class:`aidge_core.Scheduler`
+    :return: The total memory size (in number of elements) and a list (of size nb node) of list (of size nb output) of dictionnary (size, offset)
+    :rtype: Tuple[int, list]
+    """
+    mem_info = {}
+    mem_size = 0
+
+    # Exclude Producers and the last layers (because the results are stored outside the export)
+    for i, node in enumerate(scheduler.get_static_scheduling()):
+        if node.type() != "Producer":
+            node_mem_info = []
+            for out_id in range(node.get_nb_outputs()):
+                dims = node.get_operator().get_output(out_id).dims()
+                mem = 1
+                for dim in dims:
+                    mem *= dim
+
+                # Add memeory info
+                node_mem_info.append({
+                    "size": mem,
+                    "offset": mem_size
+                })
+
+                # Increment offset for the next layer
+                mem_size += mem
+            print(f"Adding meminfo to {node.name()}")
+            mem_info[node] = node_mem_info
+        else:
+            mem_info[node] = [] # No meminfo for producer
+    return mem_size, mem_info
+
+
+def generate_optimized_memory_info(scheduler: aidge_core.Scheduler, stats_folder: Path, wrapping: bool = False) -> Tuple[int, List[dict]]:
+
+    # The forward dims has to done outside the function
+    # Also supposed the generation of the scheduler has been performed outside
+    # Otherwise decomment the following line
+    # scheduler.generate_scheduling()
+    # Generate the memory manager
+    # So far, the Producers are not take in consideration in the meory manager => inc_producers=False
+    mem_manager = scheduler.generate_memory(
+        inc_producers=False, wrap_around_buffer=wrapping)
+
+    # List of nodes which are connected at the input of the graph (None if input is not connected)
+    nodes_at_input = [n[0] for n in scheduler.graph_view().inputs()]
+    # Use gnuplot to generate the log
+    try:
+        os.makedirs(str(stats_folder / "graph"), exist_ok=True)
+        mem_manager.log("memory_info")
+        os.chmod("memory_info_plot.gnu", 0o777)
+        os.system("./memory_info_plot.gnu")
+        shutil.move("memory_info", str(stats_folder / "graph" / "memory_info"))
+        shutil.move("memory_info_plot.png", str(
+            stats_folder / "graph" / "memory_info_plot.png"))
+        os.remove("memory_info_plot.gnu")
+    except:
+        print("Please install gnuplot if you want memory plot from MemoryManager.")
+
+    # In the export, we currently use an unified memory buffer whose size
+    # is determined by the memory peak usage
+    mem_size = mem_manager.get_peak_usage()
+    mem_info = []
+
+    mem_planes = mem_manager.get_planes()
+
+    for node in scheduler.get_static_scheduling():
+        if node.type() == "Producer":
+            continue  # Skipping memory management for producers
+        if node in nodes_at_input:
+            # Input memory management (suppose tensor ends with [:, channel, height, width]))
+            tensor = node.get_operator().get_output(0)
+            if tensor is None:
+                raise RuntimeError("Warning input producer not provided")
+            if len(tensor.dims()) < 3:
+                raise RuntimeError(
+                    f"Input producer dimensions must be with [:, channel, height, width] but got {tensor.dims()} instead")
+
+            name = node.name()
+            offset = 0                  # Suppose input data is stored outside the export function
+            # so the memory offset is not important to consider
+            # TODO : use get_chan get_height and get_width function !
+            size = tensor.dims()[-3]    # Should be nb_channels
+            stride = tensor.dims()[-3]  # Should be nb_channels
+            length = tensor.dims()[-1]  # Should be width
+            count = tensor.dims()[-2]   # Should be height
+            cont_offset = 0             # Suppose input data is stored outside the export function
+            # so the memory offset is not important to consider
+            # Size of input
+            cont_size = tensor.dims()[-1] * \
+                tensor.dims()[-2] * tensor.dims()[-3]
+            wrap_offset = 0     # No wrapping
+            wrap_size = 0       # No wrapping
+        else:
+            plane = mem_planes[node][0]
+            name = node.name()
+            offset = plane.offset
+            size = plane.size
+            stride = plane.stride
+            length = plane.length
+            count = plane.count
+            cont_offset = plane.get_contiguous_offset()
+            cont_size = plane.get_contiguous_size()
+            wrap_offset = plane.get_wrapped_offset()
+            wrap_size = plane.get_wrapped_size()
+
+        mem_info.append({
+            "layer_name": name,
+            "size": size,
+            "offset": offset,
+            "stride": stride,
+            "length": length,
+            "count": count,
+            "cont_offset": cont_offset,
+            "cont_size": cont_size,
+            "wrap_offset": wrap_offset,
+            "wrap_size": wrap_size
+        })
+
+    return mem_size, mem_info
+
+