mirror of https://gitlab.com/ita1024/waf.git
112 lines
2.4 KiB
Python
112 lines
2.4 KiB
Python
#! /usr/bin/env python
|
|
# encoding: UTF-8
|
|
|
|
"""
|
|
This tool can help to reduce the memory usage in very large builds featuring many tasks with after/before attributes.
|
|
It may also improve the overall build time by decreasing the amount of iterations over tasks.
|
|
|
|
Usage:
|
|
def options(opt):
|
|
opt.load('mem_reducer')
|
|
"""
|
|
|
|
import itertools
|
|
from waflib import Utils, Task, Runner
|
|
|
|
class SetOfTasks(object):
|
|
"""Wraps a set and a task which has a list of other sets.
|
|
The interface is meant to mimic the interface of set. Add missing functions as needed.
|
|
"""
|
|
def __init__(self, owner):
|
|
self._set = owner.run_after
|
|
self._owner = owner
|
|
|
|
def __iter__(self):
|
|
for g in self._owner.run_after_groups:
|
|
#print len(g)
|
|
for task in g:
|
|
yield task
|
|
for task in self._set:
|
|
yield task
|
|
|
|
def add(self, obj):
|
|
self._set.add(obj)
|
|
|
|
def update(self, obj):
|
|
self._set.update(obj)
|
|
|
|
def set_precedence_constraints(tasks):
|
|
cstr_groups = Utils.defaultdict(list)
|
|
for x in tasks:
|
|
x.run_after = SetOfTasks(x)
|
|
x.run_after_groups = []
|
|
x.waiting_sets = []
|
|
|
|
h = x.hash_constraints()
|
|
cstr_groups[h].append(x)
|
|
|
|
# create sets which can be reused for all tasks
|
|
for k in cstr_groups.keys():
|
|
cstr_groups[k] = set(cstr_groups[k])
|
|
|
|
# this list should be short
|
|
for key1, key2 in itertools.combinations(cstr_groups.keys(), 2):
|
|
group1 = cstr_groups[key1]
|
|
group2 = cstr_groups[key2]
|
|
# get the first entry of the set
|
|
t1 = next(iter(group1))
|
|
t2 = next(iter(group2))
|
|
|
|
# add the constraints based on the comparisons
|
|
if Task.is_before(t1, t2):
|
|
for x in group2:
|
|
x.run_after_groups.append(group1)
|
|
for k in group1:
|
|
k.waiting_sets.append(group1)
|
|
elif Task.is_before(t2, t1):
|
|
for x in group1:
|
|
x.run_after_groups.append(group2)
|
|
for k in group2:
|
|
k.waiting_sets.append(group2)
|
|
|
|
Task.set_precedence_constraints = set_precedence_constraints
|
|
|
|
def get_out(self):
|
|
tsk = self.out.get()
|
|
if not self.stop:
|
|
self.add_more_tasks(tsk)
|
|
self.count -= 1
|
|
self.dirty = True
|
|
|
|
# shrinking sets
|
|
try:
|
|
ws = tsk.waiting_sets
|
|
except AttributeError:
|
|
pass
|
|
else:
|
|
for k in ws:
|
|
try:
|
|
k.remove(tsk)
|
|
except KeyError:
|
|
pass
|
|
|
|
return tsk
|
|
Runner.Parallel.get_out = get_out
|
|
|
|
def skip(self, tsk):
|
|
tsk.hasrun = Task.SKIPPED
|
|
|
|
# shrinking sets
|
|
try:
|
|
ws = tsk.waiting_sets
|
|
except AttributeError:
|
|
pass
|
|
else:
|
|
for k in ws:
|
|
try:
|
|
k.remove(tsk)
|
|
except KeyError:
|
|
pass
|
|
Runner.Parallel.skip = skip
|
|
|