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

Side by Side Diff: gm/rebaseline_server/imagediffdb.py

Issue 443013002: rebaseline_server: add "prefetch" directive that just warms the cache without awaiting results (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: download all images, unless downloadOnlyDifferingImages=true Created 6 years, 4 months 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 unified diff | Download patch
« no previous file with comments | « gm/rebaseline_server/compare_rendered_pictures.py ('k') | gm/rebaseline_server/imagepair.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 """ 3 """
4 Copyright 2013 Google Inc. 4 Copyright 2013 Google Inc.
5 5
6 Use of this source code is governed by a BSD-style license that can be 6 Use of this source code is governed by a BSD-style license that can be
7 found in the LICENSE file. 7 found in the LICENSE file.
8 8
9 Calulate differences between image pairs, and store them in a database. 9 Calulate differences between image pairs, and store them in a database.
10 """ 10 """
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 expected_image_locator = _sanitize_locator(expected_image_locator) 94 expected_image_locator = _sanitize_locator(expected_image_locator)
95 actual_image_locator = _sanitize_locator(actual_image_locator) 95 actual_image_locator = _sanitize_locator(actual_image_locator)
96 96
97 # Download the expected/actual images, if we don't have them already. 97 # Download the expected/actual images, if we don't have them already.
98 expected_image_file = os.path.join( 98 expected_image_file = os.path.join(
99 storage_root, expected_images_subdir, 99 storage_root, expected_images_subdir,
100 str(expected_image_locator) + image_suffix) 100 str(expected_image_locator) + image_suffix)
101 actual_image_file = os.path.join( 101 actual_image_file = os.path.join(
102 storage_root, actual_images_subdir, 102 storage_root, actual_images_subdir,
103 str(actual_image_locator) + image_suffix) 103 str(actual_image_locator) + image_suffix)
104 try: 104 for image_file, image_url in [
105 _download_file(gs, expected_image_file, expected_image_url) 105 (expected_image_file, expected_image_url),
106 except Exception: 106 (actual_image_file, actual_image_url)]:
107 logging.exception('unable to download expected_image_url %s to file %s' % 107 if image_file and image_url:
108 (expected_image_url, expected_image_file)) 108 try:
109 raise 109 _download_file(gs, image_file, image_url)
110 try: 110 except Exception:
111 _download_file(gs, actual_image_file, actual_image_url) 111 logging.exception('unable to download image_url %s to file %s' %
112 except Exception: 112 (image_url, image_file))
113 logging.exception('unable to download actual_image_url %s to file %s' % 113 raise
114 (actual_image_url, actual_image_file))
115 raise
116 114
117 # Get all diff images and values from skpdiff binary. 115 # Return early if we do not need to generate diffs.
116 if (expected_image_url == actual_image_url or
117 not expected_image_url or not actual_image_url):
118 return
119
120 # Get all diff images and values using the skpdiff binary.
118 skpdiff_output_dir = tempfile.mkdtemp() 121 skpdiff_output_dir = tempfile.mkdtemp()
119 try: 122 try:
120 skpdiff_summary_file = os.path.join(skpdiff_output_dir, 123 skpdiff_summary_file = os.path.join(skpdiff_output_dir,
121 'skpdiff-output.json') 124 'skpdiff-output.json')
122 skpdiff_rgbdiff_dir = os.path.join(skpdiff_output_dir, 'rgbDiff') 125 skpdiff_rgbdiff_dir = os.path.join(skpdiff_output_dir, 'rgbDiff')
123 skpdiff_whitediff_dir = os.path.join(skpdiff_output_dir, 'whiteDiff') 126 skpdiff_whitediff_dir = os.path.join(skpdiff_output_dir, 'whiteDiff')
124 expected_img = os.path.join(storage_root, expected_images_subdir,
125 str(expected_image_locator) + image_suffix)
126 actual_img = os.path.join(storage_root, actual_images_subdir,
127 str(actual_image_locator) + image_suffix)
128 127
129 # TODO(epoger): Consider calling skpdiff ONCE for all image pairs, 128 # TODO(epoger): Consider calling skpdiff ONCE for all image pairs,
130 # instead of calling it separately for each image pair. 129 # instead of calling it separately for each image pair.
131 # Pro: we'll incur less overhead from making repeated system calls, 130 # Pro: we'll incur less overhead from making repeated system calls,
132 # spinning up the skpdiff binary, etc. 131 # spinning up the skpdiff binary, etc.
133 # Con: we would have to wait until all image pairs were loaded before 132 # Con: we would have to wait until all image pairs were loaded before
134 # generating any of the diffs? 133 # generating any of the diffs?
135 find_run_binary.run_command( 134 find_run_binary.run_command(
136 [SKPDIFF_BINARY, '-p', expected_img, actual_img, 135 [SKPDIFF_BINARY, '-p', expected_image_file, actual_image_file,
137 '--jsonp', 'false', 136 '--jsonp', 'false',
138 '--output', skpdiff_summary_file, 137 '--output', skpdiff_summary_file,
139 '--differs', 'perceptual', 'different_pixels', 138 '--differs', 'perceptual', 'different_pixels',
140 '--rgbDiffDir', skpdiff_rgbdiff_dir, 139 '--rgbDiffDir', skpdiff_rgbdiff_dir,
141 '--whiteDiffDir', skpdiff_whitediff_dir, 140 '--whiteDiffDir', skpdiff_whitediff_dir,
142 ]) 141 ])
143 142
144 # Get information out of the skpdiff_summary_file. 143 # Get information out of the skpdiff_summary_file.
145 with contextlib.closing(open(skpdiff_summary_file)) as fp: 144 with contextlib.closing(open(skpdiff_summary_file)) as fp:
146 data = json.load(fp) 145 data = json.load(fp)
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 # previously downloaded to local disk. 253 # previously downloaded to local disk.
255 # I guess we should figure out how expensive it is to download vs diff the 254 # I guess we should figure out how expensive it is to download vs diff the
256 # image pairs... if diffing them is expensive too, we can write these 255 # image pairs... if diffing them is expensive too, we can write these
257 # _diff_dict objects out to disk if there's too many to hold in RAM. 256 # _diff_dict objects out to disk if there's too many to hold in RAM.
258 # Or we could use virtual memory to handle that automatically. 257 # Or we could use virtual memory to handle that automatically.
259 self._diff_dict = {} 258 self._diff_dict = {}
260 self._diff_dict_writelock = threading.RLock() 259 self._diff_dict_writelock = threading.RLock()
261 260
262 # Set up the queue for asynchronously loading DiffRecords, and start the 261 # Set up the queue for asynchronously loading DiffRecords, and start the
263 # worker threads reading from it. 262 # worker threads reading from it.
264 self._tasks_queue = Queue.Queue(maxsize=2*num_worker_threads) 263 # The queue maxsize must be 0 (infinite size queue), so that asynchronous
264 # calls can return as soon as possible.
265 self._tasks_queue = Queue.Queue(maxsize=0)
265 self._workers = [] 266 self._workers = []
266 for i in range(num_worker_threads): 267 for i in range(num_worker_threads):
267 worker = threading.Thread(target=self.worker, args=(i,)) 268 worker = threading.Thread(target=self.worker, args=(i,))
268 worker.daemon = True 269 worker.daemon = True
269 worker.start() 270 worker.start()
270 self._workers.append(worker) 271 self._workers.append(worker)
271 272
272 def worker(self, worker_num): 273 def worker(self, worker_num):
273 """Launch a worker thread that pulls tasks off self._tasks_queue. 274 """Launch a worker thread that pulls tasks off self._tasks_queue.
274 275
(...skipping 28 matching lines...) Expand all
303 expected_image_url, expected_image_locator, 304 expected_image_url, expected_image_locator,
304 actual_image_url, actual_image_locator): 305 actual_image_url, actual_image_locator):
305 """Asynchronously prepare a DiffRecord for a pair of images. 306 """Asynchronously prepare a DiffRecord for a pair of images.
306 307
307 This method will return quickly; calls to get_diff_record() will block 308 This method will return quickly; calls to get_diff_record() will block
308 until the DiffRecord is available (or we have given up on creating it). 309 until the DiffRecord is available (or we have given up on creating it).
309 310
310 If we already have a DiffRecord for this particular image pair, no work 311 If we already have a DiffRecord for this particular image pair, no work
311 will be done. 312 will be done.
312 313
314 If expected_image_url (or its locator) is None, just download actual_image.
315 If actual_image_url (or its locator) is None, just download expected_image.
316
313 Args: 317 Args:
314 expected_image_url: file, GS, or HTTP url from which we will download the 318 expected_image_url: file, GS, or HTTP url from which we will download the
315 expected image 319 expected image
316 expected_image_locator: a unique ID string under which we will store the 320 expected_image_locator: a unique ID string under which we will store the
317 expected image within storage_root (probably including a checksum to 321 expected image within storage_root (probably including a checksum to
318 guarantee uniqueness) 322 guarantee uniqueness)
319 actual_image_url: file, GS, or HTTP url from which we will download the 323 actual_image_url: file, GS, or HTTP url from which we will download the
320 actual image 324 actual image
321 actual_image_locator: a unique ID string under which we will store the 325 actual_image_locator: a unique ID string under which we will store the
322 actual image within storage_root (probably including a checksum to 326 actual image within storage_root (probably including a checksum to
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 pass 434 pass
431 435
432 436
433 def _sanitize_locator(locator): 437 def _sanitize_locator(locator):
434 """Returns a sanitized version of a locator (one in which we know none of the 438 """Returns a sanitized version of a locator (one in which we know none of the
435 characters will have special meaning in filenames). 439 characters will have special meaning in filenames).
436 440
437 Args: 441 Args:
438 locator: string, or something that can be represented as a string 442 locator: string, or something that can be represented as a string
439 """ 443 """
440 return DISALLOWED_FILEPATH_CHAR_REGEX.sub('_', str(locator)) 444 if locator:
441 445 return DISALLOWED_FILEPATH_CHAR_REGEX.sub('_', str(locator))
446 else:
447 return locator
rmistry 2014/08/06 17:49:01 Is it ok for this to be an empty string or None? s
epoger 2014/08/06 17:53:34 We actually need to allow for None. Added a comme
442 448
443 def _get_difference_locator(expected_image_locator, actual_image_locator): 449 def _get_difference_locator(expected_image_locator, actual_image_locator):
444 """Returns the locator string used to look up the diffs between expected_image 450 """Returns the locator string used to look up the diffs between expected_image
445 and actual_image. 451 and actual_image.
446 452
447 We must keep this function in sync with getImageDiffRelativeUrl() in 453 We must keep this function in sync with getImageDiffRelativeUrl() in
448 static/loader.js 454 static/loader.js
449 455
450 Args: 456 Args:
451 expected_image_locator: locator string pointing at expected image 457 expected_image_locator: locator string pointing at expected image
452 actual_image_locator: locator string pointing at actual image 458 actual_image_locator: locator string pointing at actual image
453 459
454 Returns: already-sanitized locator where the diffs between expected and 460 Returns: already-sanitized locator where the diffs between expected and
455 actual images can be found 461 actual images can be found
456 """ 462 """
457 return "%s-vs-%s" % (_sanitize_locator(expected_image_locator), 463 return "%s-vs-%s" % (_sanitize_locator(expected_image_locator),
458 _sanitize_locator(actual_image_locator)) 464 _sanitize_locator(actual_image_locator))
OLDNEW
« no previous file with comments | « gm/rebaseline_server/compare_rendered_pictures.py ('k') | gm/rebaseline_server/imagepair.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698