288def CrunchStats(added, removed, changed, unchanged, showsources, showsymbols):
289 """Outputs to stdout a summary of changes based on the symbol lists."""
290
291
292 grown = []
293 shrunk = []
294 for item in changed:
295 if item.old_size < item.new_size:
296 grown.append(item)
297 else:
298 shrunk.append(item)
299
300 new_symbols = CrunchStatsData(added)
301 removed_symbols = CrunchStatsData(removed)
302 grown_symbols = CrunchStatsData(grown)
303 shrunk_symbols = CrunchStatsData(shrunk)
304 sections = [new_symbols, removed_symbols, grown_symbols, shrunk_symbols]
305 for section in sections:
306 for item in section.symbols:
307 section.sources.add(item.file_path)
308 if item.old_size is not None:
309 section.before_size += item.old_size
310 if item.new_size is not None:
311 section.after_size += item.new_size
312 bucket = section.symbols_by_path.setdefault(item.file_path, [])
313 bucket.append((item.symbol_name, item.symbol_type,
314 item.ExtractSymbolDelta()))
315
316 total_change = sum(s.after_size - s.before_size for s in sections)
317 summary =
'Total change: %s bytes' %
DeltaStr(total_change)
320 for section in sections:
321 if not section.symbols:
322 continue
323 if section.before_size == 0:
324 description = (
325 'added, totalling %s bytes' %
DeltaStr(section.after_size))
326 elif section.after_size == 0:
327 description = (
328 'removed, totalling %s bytes' %
DeltaStr(-section.before_size))
329 else:
330 if section.after_size > section.before_size:
331 type_str = 'grown'
332 else:
333 type_str = 'shrunk'
334 description = (
335 '%s, for a net change of %s bytes '
336 '(%d bytes before, %d bytes after)' %
337 (type_str,
DeltaStr(section.after_size - section.before_size),
338 section.before_size, section.after_size))
339 print(
' %d %s across %d sources' % (
len(section.symbols), description,
340 len(section.sources)))
341
342 maybe_unchanged_sources =
set()
343 unchanged_symbols_size = 0
344 for item in unchanged:
345 maybe_unchanged_sources.add(item.file_path)
346 unchanged_symbols_size += item.old_size
347 print(
' %d unchanged, totalling %d bytes' % (
len(unchanged),
348 unchanged_symbols_size))
349
350
351 unchanged_sources = maybe_unchanged_sources
352 for section in sections:
353 unchanged_sources = unchanged_sources - section.sources
354 new_sources = (
355 new_symbols.sources - maybe_unchanged_sources - removed_symbols.sources)
356 removed_sources = (
357 removed_symbols.sources - maybe_unchanged_sources - new_symbols.sources)
358 partially_changed_sources = (
359 grown_symbols.sources | shrunk_symbols.sources | new_symbols.sources |
360 removed_symbols.sources) - removed_sources - new_sources
362 for section in sections:
363 allFiles = allFiles | section.sources
364 allFiles = allFiles | maybe_unchanged_sources
365 print(
'Source stats:')
366 print(
' %d sources encountered.' %
len(allFiles))
367 print(
' %d completely new.' %
len(new_sources))
368 print(
' %d removed completely.' %
len(removed_sources))
369 print(
' %d partially changed.' %
len(partially_changed_sources))
370 print(
' %d completely unchanged.' %
len(unchanged_sources))
371 remainder = (allFiles - new_sources - removed_sources -
372 partially_changed_sources - unchanged_sources)
373 assert len(remainder) == 0
374
375 if not showsources:
376 return
377 print(
'Per-source Analysis:')
378 delta_by_path = {}
379 for section in sections:
380 for path in section.symbols_by_path:
381 entry = delta_by_path.get(path)
382 if not entry:
383 entry = {'plus': 0, 'minus': 0}
384 delta_by_path[path] = entry
385 for symbol_name, symbol_type, symbol_delta in \
386 section.symbols_by_path[path]:
387 if symbol_delta.old_size is None:
388 delta = symbol_delta.new_size
389 elif symbol_delta.new_size is None:
390 delta = -symbol_delta.old_size
391 else:
392 delta = symbol_delta.new_size - symbol_delta.old_size
393
394 if delta > 0:
395 entry['plus'] += delta
396 else:
397 entry['minus'] += (-1 * delta)
398
399 def delta_sort_key(item):
400 _path, size_data = item
401 growth = size_data['plus'] - size_data['minus']
402 return growth
403
404 for path, size_data in sorted(delta_by_path.items(),
405 key=delta_sort_key,
406 reverse=True):
407 gain = size_data['plus']
408 loss = size_data['minus']
409 delta = size_data['plus'] - size_data['minus']
410 header =
' %s - Source: %s - (gained %d, lost %d)' % (
DeltaStr(delta),
411 path, gain, loss)
412 divider =
'-' *
len(header)
417 if showsymbols:
418
419 def ExtractNewSize(tup):
420 symbol_delta = tup[2]
421 return symbol_delta.new_size
422
423 def ExtractOldSize(tup):
424 symbol_delta = tup[2]
425 return symbol_delta.old_size
426
427 if path in new_symbols.symbols_by_path:
428 print(
' New symbols:')
429 for symbol_name, symbol_type, symbol_delta in \
430 sorted(new_symbols.symbols_by_path[path],
431 key=ExtractNewSize,
432 reverse=True):
433 print(
' %8s: %s type=%s, size=%d bytes%s' %
434 (
DeltaStr(symbol_delta.new_size), symbol_name,
435 symbol_type, symbol_delta.new_size,
437 if path in removed_symbols.symbols_by_path:
438 print(
' Removed symbols:')
439 for symbol_name, symbol_type, symbol_delta in \
440 sorted(removed_symbols.symbols_by_path[path],
441 key=ExtractOldSize):
442 print(
' %8s: %s type=%s, size=%d bytes%s' %
443 (
DeltaStr(-symbol_delta.old_size), symbol_name,
444 symbol_type, symbol_delta.old_size,
446 for (changed_symbols_by_path,
447 type_str) in [(grown_symbols.symbols_by_path, "Grown"),
448 (shrunk_symbols.symbols_by_path, "Shrunk")]:
449 if path in changed_symbols_by_path:
450 print(
' %s symbols:' % type_str)
451
452 def changed_symbol_sortkey(item):
453 symbol_name, _symbol_type, symbol_delta = item
454 return (symbol_delta.old_size - symbol_delta.new_size,
455 symbol_name)
456
457 for symbol_name, symbol_type, symbol_delta in \
458 sorted(changed_symbols_by_path[path], key=changed_symbol_sortkey):
460 ' %8s: %s type=%s, (was %d bytes, now %d bytes)%s'
462 symbol_delta.old_size), symbol_name,
463 symbol_type,
464 symbol_delta.old_size, symbol_delta.new_size,
466
467
def SharedInfoStr(symbol_info)
def CrunchStats(added, removed, changed, unchanged, showsources, showsymbols)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
def print(*args, **kwargs)