Sunday, 23 April 2017

Garbage Collection

 A system that automatically recycles unused memory in a programming language.

Pros -
  • Makes programming easier
  • Helps developers to avoid several memory problems
Cons -
  • Consumes computing resources
  • Consumes memory to store status of objects
  • Recycle process may even block the program potentially
Memory Problems -
  • Dangling pointers - point to an object that no longer exists
  • Freeing a region of memory that s already free
  • Memory leaks - Unreachable region of memory that can never be freed
Designing Garbage Collection -    All objects in-memory heap are like a directional graph. All the nodes(vertices) which are not reachable from root(s) can be freed.
Problem - Find unreachable nodes in a directional graph
Solution -

Edge.java
public class Edge<T> {
    private final int cost;
    private final Vertex<T> to;
    private final Vertex<T> from;
    public Edge(Vertex<T> from, Vertex<T> to, int cost) {
        this.cost = cost;
        this.to = to;
        this.from = from;
    }
    public Vertex<T> getTo() { return to; }
    public Vertex<T> getFrom() { return from; }

    @Override   public boolean equals(Object obj) {
        Objects.requireNonNull(obj);
        if(this==obj) return  true;
        Edge other = null;
        if(obj instanceof Edge)
            other = (Edge)obj;
        if (!this.getFrom().equals(other.getFrom())) return false;
        if (!this.getTo().equals(other.getTo()))  return false;
        return true;
    }
}

Vertex.java 
public class Vertex<T> {

    private Color markState;
    private final String name;
    private final T value;
    private List<Edge<T>> edges;
    private List<Edge<T>> incomingEdges;
    private List<Edge<T>> outgoingEdges;

    public Vertex(String name, T value) {
        this.name = name;
        this.value = value;
        incomingEdges = new ArrayList<>();
        outgoingEdges = new ArrayList<>();
        edges = new ArrayList<>();
    }

    public Edge<T> findEdge(com.graph.Vertex<T> to) {
        Optional<Edge<T>> e = edges.stream()
        .filter(edge -> edge.getFrom().equals(this) && edge.getTo().equals(to))
        .findAny();
        return e.isPresent() ? e.get():null;
    }

    public void addEdge(Edge<T> e, boolean isIncoming) {
        this.edges.add(e);
        if (isIncoming) { incomingEdges.add(e);
        } else {  outgoingEdges.add(e); }
    }

    public void remove(Edge<T> e) {
        incomingEdges.remove(e);
        outgoingEdges.remove(e);
        edges.remove(e);
    }

    public void clearMark() { this.markState = null; }

    public void setMarkState(Color markState) {
        this.markState = markState;
    }

    public Color getMarkState() { return markState; }

    public String getName() { return name; }

    public T getValue() { return  value; }

    public List<Edge<T>> getOutgoingEdges() { return outgoingEdges; }

    public List<Edge<T>> getIncomingEdges() { return incomingEdges; }
}
Color.java
public enum Color { BLACK, WHITE, GREY }
Graph.java
class Graph<T> {
    Set<Vertex<T>> vertices;
    List<Edge<T>> edges;
    Vertex rootVertex;

    public Graph() {
        vertices = new HashSet<>();
        edges = new ArrayList<>();
    }

    public boolean isEmpty() {  return size() == 0; }
   
    public Vertex getRootVertex() { return rootVertex; }

    public void setRootVertex(Vertex rootVertex) {
        this.rootVertex = rootVertex;
        this.addVertex(rootVertex);
    }

    public Vertex getVertex(T value) {
        return vertices.stream().filter(val -> value.equals(val)).findAny().get();
    }

    public boolean addEdge(Vertex<T> from, Vertex<T> to, int cost) {
        if (!(vertices.contains(from) || vertices.contains(to))) {
            throw new NoSuchElementException("Element not found");
        }
        Edge<T> e = new Edge<T>(from, to, cost);
        if (from.findEdge(to) == null) {
            from.addEdge(e, false);
            to.addEdge(e, true);
            edges.add(e);
            return true;
        }
        return false;
    }

    private int size() { return vertices.size(); }

    public boolean addVertex(Vertex<T> vertex) {
        Objects.requireNonNull(vertices, "Vertices are null");
        return vertices.add(vertex);
    }

    public boolean insertBiEdge(Vertex<T> from, Vertex<T> to, int cost)
            throws IllegalArgumentException {
        return addEdge(from, to, cost) && addEdge(to, from, cost);
    }

    public Vertex<T> findVertexByName(String name) {
        return vertices.stream().filter(vertex -> vertex.getName().equals(name))
             .findAny().get();
    }

    public Vertex<T> findVertexByValue(T value) {
        return vertices.stream().filter(vertex -> value.equals(vertex.getValue()))
              .findAny().get();
    }

    public String toString() {
        StringBuffer tmp = new StringBuffer("Graph[");
        vertices.stream().forEach(v -> tmp.append(v.getValue()).append(" "));
        tmp.append(']');
        return tmp.toString();
    }

    public boolean removeVertex(Vertex<T> v) {
        if (v == rootVertex)
            rootVertex = null;
        // Remove the edges associated with v     
            v.getOutgoingEdges().forEach(e -> {
            v.remove(e);
            Vertex<T> to = e.getTo();
            to.remove(e);
            edges.remove(e);
        });

        v.getIncomingEdges().forEach(e -> {
            v.remove(e);
            Vertex<T> from = e.getFrom();
            from.remove(e);
            edges.remove(e);
        });
        return true;
    }

    public boolean removeEdge(Vertex<T> from, Vertex<T> to) {
        Edge<T> e = from.findEdge(to);
        if (e != null) {
            from.remove(e);
            to.remove(e);
            edges.remove(e);
            return true;
        }
        return false;
    }
    public void clearMark() {
        vertices.stream().forEach(vertex -> vertex.clearMark());
    }
    public void garbageCollection() {
        vertices.stream().forEach(v -> v.setMarkState(Color.WHITE));
        visit(getRootVertex());
        vertices.stream().filter(vertex -> vertex.getMarkState() == Color.WHITE)
              .forEach(vertex -> removeVertex(vertex));
        vertices.removeIf(vertex -> vertex.getMarkState() == Color.WHITE);
        clearMark();    }
    private void visit(Vertex<T> v) {
        v.setMarkState(Color.GREY);
        v.getOutgoingEdges().stream().forEach(edge -> {
            Vertex<T> u = edge.getTo();
            if (u.getMarkState() == Color.WHITE)
                visit(u);
            v.setMarkState(Color.BLACK);  });
    }
Main class - DirectionalGraph.java
public class DirectionalGraph { public static void main(String[] args) { Graph graph = new Graph(); Vertex<String> vertexA = new Vertex<>("a", "a"); Vertex<String> vertexB = new Vertex<>("b", "b"); Vertex<String> vertexC = new Vertex<>("c", "c"); Vertex<String> vertexD = new Vertex<>("d", "d"); Vertex<String> vertexE = new Vertex<>("e", "e"); Vertex<String> vertexF = new Vertex<>("f", "f"); graph.setRootVertex(vertexA); graph.addVertex(vertexA); graph.addVertex(vertexB); graph.addVertex(vertexC); graph.addVertex(vertexD); graph.addVertex(vertexE); graph.addVertex(vertexF); graph.addEdge(vertexA, vertexB, 5); graph.addEdge(vertexA, vertexC, 5); graph.addEdge(vertexB, vertexD, 5); graph.addEdge(vertexB, vertexE, 5); graph.addEdge(vertexD, vertexE, 5); System.out.println(graph); graph.garbageCollection(); System.out.println(graph); } }
Output - 

Graph[e d b a c f ]
Graph[e d b a c ]
  1. As f is not connected to any node is removed from Graph. Garbage collected

No comments:

Post a Comment