jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
2.4KB

  1. #! /usr/bin/env python
  2. # encoding: UTF-8
  3. """
  4. This tool can help to reduce the memory usage in very large builds featuring many tasks with after/before attributes.
  5. It may also improve the overall build time by decreasing the amount of iterations over tasks.
  6. Usage:
  7. def options(opt):
  8. opt.load('mem_reducer')
  9. """
  10. import itertools
  11. from waflib import Utils, Task, Runner
  12. class SetOfTasks(object):
  13. """Wraps a set and a task which has a list of other sets.
  14. The interface is meant to mimic the interface of set. Add missing functions as needed.
  15. """
  16. def __init__(self, owner):
  17. self._set = owner.run_after
  18. self._owner = owner
  19. def __iter__(self):
  20. for g in self._owner.run_after_groups:
  21. #print len(g)
  22. for task in g:
  23. yield task
  24. for task in self._set:
  25. yield task
  26. def add(self, obj):
  27. self._set.add(obj)
  28. def update(self, obj):
  29. self._set.update(obj)
  30. def set_precedence_constraints(tasks):
  31. cstr_groups = Utils.defaultdict(list)
  32. for x in tasks:
  33. x.run_after = SetOfTasks(x)
  34. x.run_after_groups = []
  35. x.waiting_sets = []
  36. h = x.hash_constraints()
  37. cstr_groups[h].append(x)
  38. # create sets which can be reused for all tasks
  39. for k in cstr_groups.keys():
  40. cstr_groups[k] = set(cstr_groups[k])
  41. # this list should be short
  42. for key1, key2 in itertools.combinations(cstr_groups.keys(), 2):
  43. group1 = cstr_groups[key1]
  44. group2 = cstr_groups[key2]
  45. # get the first entry of the set
  46. t1 = next(iter(group1))
  47. t2 = next(iter(group2))
  48. # add the constraints based on the comparisons
  49. if Task.is_before(t1, t2):
  50. for x in group2:
  51. x.run_after_groups.append(group1)
  52. for k in group1:
  53. k.waiting_sets.append(group1)
  54. elif Task.is_before(t2, t1):
  55. for x in group1:
  56. x.run_after_groups.append(group2)
  57. for k in group2:
  58. k.waiting_sets.append(group2)
  59. Task.set_precedence_constraints = set_precedence_constraints
  60. def get_out(self):
  61. tsk = self.out.get()
  62. if not self.stop:
  63. self.add_more_tasks(tsk)
  64. self.count -= 1
  65. self.dirty = True
  66. # shrinking sets
  67. try:
  68. ws = tsk.waiting_sets
  69. except AttributeError:
  70. pass
  71. else:
  72. for k in ws:
  73. try:
  74. k.remove(tsk)
  75. except KeyError:
  76. pass
  77. return tsk
  78. Runner.Parallel.get_out = get_out
  79. def skip(self, tsk):
  80. tsk.hasrun = Task.SKIPPED
  81. # shrinking sets
  82. try:
  83. ws = tsk.waiting_sets
  84. except AttributeError:
  85. pass
  86. else:
  87. for k in ws:
  88. try:
  89. k.remove(tsk)
  90. except KeyError:
  91. pass
  92. Runner.Parallel.skip = skip