Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1946)

Unified Diff: scripts/slave/recipe_modules/isolate/resources/compare_build_artifacts.py

Issue 687723008: Optimize compare_build_artifacts.py to have an even more compact output. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Summum Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: scripts/slave/recipe_modules/isolate/resources/compare_build_artifacts.py
diff --git a/scripts/slave/recipe_modules/isolate/resources/compare_build_artifacts.py b/scripts/slave/recipe_modules/isolate/resources/compare_build_artifacts.py
index 3fd28b1b2722b9a0897b98c787d0c5c5544b777c..ff3866cc689e563a221cdb682ccca6909a172824 100755
--- a/scripts/slave/recipe_modules/isolate/resources/compare_build_artifacts.py
+++ b/scripts/slave/recipe_modules/isolate/resources/compare_build_artifacts.py
@@ -9,7 +9,9 @@ import difflib
import json
import optparse
import os
+import struct
import sys
+import time
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -34,47 +36,86 @@ def get_files_to_compare(build_dir):
check(os.path.join(build_dir, f)))
-def compare_files(first_filepath, second_filepath):
- """Compares two binaries and return the number of differences between them.
+def diff_dict(a, b):
+ """Returns a yaml-like textural diff of two dict.
- Returns None if the files are equal, a string otherwise.
+ It is currently optimized for the .isolated format.
"""
- file_len = os.stat(first_filepath).st_size
- if file_len != os.stat(second_filepath).st_size:
- return 'different size: %d != %d' % (
- file_len, os.stat(second_filepath).st_size)
-
- chunk_size = 1024 * 1024
+ out = ''
+ for key in set(a) | set(b):
+ va = a.get(key)
+ vb = b.get(key)
+ if va.__class__ != vb.__class__:
+ out += '- %s:\n %r != %r\n' % (key, va, vb)
+ elif isinstance(va, dict):
+ c = diff_dict(va, vb)
+ if c:
+ out += '- %s:\n%s\n' % (
+ key, '\n'.join(' ' + l for l in c.splitlines()))
+ elif va != vb:
+ out += '- %s:\n %s != %s\n' % (key, va, vb)
+ return out.rstrip()
+
+
+def diff_binary(first_filepath, second_filepath, file_len):
+ """Returns a compact binary diff if the diff is small enough."""
+ CHUNK_SIZE = 32
+ MAX_STREAMS = 10
diffs = 0
+ streams = []
+ offset = 0
with open(first_filepath, 'rb') as lhs:
with open(second_filepath, 'rb') as rhs:
while True:
- lhs_data = lhs.read(chunk_size)
- rhs_data = rhs.read(chunk_size)
+ lhs_data = lhs.read(CHUNK_SIZE)
+ rhs_data = rhs.read(CHUNK_SIZE)
if not lhs_data:
break
- diffs += sum(l != r for l, r in zip(lhs_data, rhs_data))
+ if lhs_data != rhs_data:
+ diffs += sum(l != r for l, r in zip(lhs_data, rhs_data))
+ if streams is not None:
+ if len(streams) < MAX_STREAMS:
+ streams.append((offset, lhs_data, rhs_data))
+ else:
+ streams = None
+ offset += len(lhs_data)
+ del lhs_data
+ del rhs_data
if not diffs:
return None
-
result = '%d out of %d bytes are different (%.2f%%)' % (
diffs, file_len, 100.0 * diffs / file_len)
+ if streams:
+ encode = lambda text: ''.join(i if 31 < ord(i) < 128 else '.' for i in text)
+ for offset, lhs_data, rhs_data in streams:
+ lhs_line = '%s \'%s\'' % (lhs_data.encode('hex'), encode(lhs_data))
+ rhs_line = '%s \'%s\'' % (rhs_data.encode('hex'), encode(rhs_data))
+ diff = list(difflib.Differ().compare([lhs_line], [rhs_line]))[-1][2:-1]
+ result += '\n0x%-8x: %s\n %s\n %s' % (
+ offset, lhs_line, rhs_line, diff)
+ return result
+
- if diffs and first_filepath.endswith('.isolated'):
- # Unpack the files.
+def compare_files(first_filepath, second_filepath):
+ """Compares two binaries and return the number of differences between them.
+
+ Returns None if the files are equal, a string otherwise.
+ """
+ if first_filepath.endswith('.isolated'):
with open(first_filepath, 'rb') as f:
- lhs = json.dumps(
- json.load(f), indent=2, sort_keys=True,
- separators=(',', ': ')).splitlines()
+ lhs = json.load(f)
with open(second_filepath, 'rb') as f:
- rhs = json.dumps(
- json.load(f), indent=2, sort_keys=True,
- separators=(',', ': ')).splitlines()
+ rhs = json.load(f)
+ diff = diff_dict(lhs, rhs)
+ if diff:
+ return '\n' + diff
- result += '\n' + '\n'.join(
- line for line in difflib.unified_diff(lhs, rhs)
- if not line.startswith(('---', '+++')))
- return result
+ file_len = os.stat(first_filepath).st_size
+ if file_len != os.stat(second_filepath).st_size:
+ return 'different size: %d != %d' % (
+ file_len, os.stat(second_filepath).st_size)
+
+ return diff_binary(first_filepath, second_filepath, file_len)
def compare_build_artifacts(first_dir, second_dir):
@@ -99,6 +140,9 @@ def compare_build_artifacts(first_dir, second_dir):
print >> sys.stderr, '\n'.join(' ' + i for i in sorted(diff))
res += len(diff)
+ epoch_hex = struct.pack('<I', int(time.time())).encode('hex')
+ print('Epoch: %s' %
+ ' '.join(epoch_hex[i:i+2] for i in xrange(0, len(epoch_hex), 2)))
max_filepath_len = max(len(n) for n in first_list & second_list)
for f in sorted(first_list & second_list):
first_file = os.path.join(first_dir, f)
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698