# Buggy code
def get_executable_operand_dag(self, op_key, serialize=True):
    """
    Make an operand into a worker-executable dag
    :param op_key: operand key
    :param serialize: whether to return serialized dag
    """
    graph = DAG()

    inputs_to_copied = dict()
    for c in self._op_key_to_chunk[op_key]:
        for inp in set(c.inputs or ()):
            op = TensorFetch(dtype=inp.dtype)
            inp_chunk = op.new_chunk(None, inp.shape, _key=inp.key).data
            inputs_to_copied[inp] = inp_chunk
            graph.add_node(inp_chunk)
        inputs = [inputs_to_copied[inp] for inp in (c.inputs or ())]

        new_op = c.op.copy()
        kws = []
        for o in c.op.outputs:
            kw = dict(_key=o.key, dtype=o.dtype, index=o.index)
            composed = []
            # copy composed
            for j, com in enumerate(o.composed or []):
                new_com_op = com.op.copy()
                if j == 0:
                    inps = inputs
                else:
                    # if more than 1 inputs, means they are exactly the same object
                    inps = [composed[j - 1]] * len(com.inputs)
                new_com = new_com_op.new_chunk(
                    inps, com.shape, index=com.index, dtype=com.dtype, _key=com.key
                )
                composed.append(new_com)
            kw["_composed"] = composed
            kws.append(kw)

        new_outputs = new_op.new_chunks(
            inputs, [o.shape for o in c.op.outputs], kws=kws
        )
        for co in new_outputs:
            exec_chunk = co.data
            graph.add_node(exec_chunk)
            for inp in inputs:
                graph.add_edge(inp, exec_chunk)
    if serialize:
        return serialize_graph(graph)
    else:
        return graph


# Traceback (mars.error)
In [1]: from mars.deploy.local import new_cluster

In [2]: cluster = new_cluster(scheduler_n_process=2, worker_n_process=3, shared_memory='20M',)

In [3]: import mars.tensor as mt

In [4]: import scipy.sparse as sps

In [5]: a = sps.csr_matrix((10000, 10000))

In [6]: b = sps.csr_matrix((10000, 1))

In [7]: t1 = mt.tensor(a)

In [8]: t2 = mt.tensor(b)


In [9]: from mars.session import new_session

In [10]: cluster.session.run(t1 * t2)

Unexpected exception occurred in ChunkHolderActor.spill_size.
Traceback (most recent call last):
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 298, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/worker/chunkholder.py", line 123, in spill_size
raise SpillExhausted
mars.errors.SpillExhausted
Unhandled exception in promise call
Traceback (most recent call last):
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/promise.py", line 304, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 298, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/worker/chunkholder.py", line 123, in spill_size
raise SpillExhausted
mars.errors.SpillExhausted
....

# Fixed code
def get_executable_operand_dag(self, op_key, serialize=True):
    """
    Make an operand into a worker-executable dag
    :param op_key: operand key
    :param serialize: whether to return serialized dag
    """
    graph = DAG()

    inputs_to_copied = dict()
    for c in self._op_key_to_chunk[op_key]:
        for inp in set(c.inputs or ()):
            op = TensorFetch(dtype=inp.dtype, sparse=inp.op.sparse)
            inp_chunk = op.new_chunk(None, inp.shape, _key=inp.key).data
            inputs_to_copied[inp] = inp_chunk
            graph.add_node(inp_chunk)
        inputs = [inputs_to_copied[inp] for inp in (c.inputs or ())]

        new_op = c.op.copy()
        kws = []
        for o in c.op.outputs:
            kw = dict(_key=o.key, dtype=o.dtype, index=o.index)
            composed = []
            # copy composed
            for j, com in enumerate(o.composed or []):
                new_com_op = com.op.copy()
                if j == 0:
                    inps = inputs
                else:
                    # if more than 1 inputs, means they are exactly the same object
                    inps = [composed[j - 1]] * len(com.inputs)
                new_com = new_com_op.new_chunk(
                    inps, com.shape, index=com.index, dtype=com.dtype, _key=com.key
                )
                composed.append(new_com)
            kw["_composed"] = composed
            kws.append(kw)

        new_outputs = new_op.new_chunks(
            inputs, [o.shape for o in c.op.outputs], kws=kws
        )
        for co in new_outputs:
            exec_chunk = co.data
            graph.add_node(exec_chunk)
            for inp in inputs:
                graph.add_edge(inp, exec_chunk)
    if serialize:
        return serialize_graph(graph)
    else:
        return graph