New issue
Advanced search Search tips

Issue 708865 link

Starred by 2 users

Issue metadata

Status: Fixed
Owner:
Closed: May 2017
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug

Blocking:
issue 681694



Sign in to add a comment

.size diffs have too much noise in them

Project Member Reported by agrieve@chromium.org, Apr 6 2017

Issue description

Noticed some room for improvement when looking at bug 708841.

1. Looks like we should fold together [clone] symbols.
2. Seems to be some random symbols added/removed. I'm unsure as to whether this is due to multiple symbols sharing and address, or from differences in inlining.

Attaching two .size files.
 
master.size
4.1 MB Download
reverted.size
4.1 MB Download
There are also many symbols that seem to have the same name and size but are shown as +/-. E.g.:
blink::scheduler::WebTaskRunnerImpl::postDelayedTask

Perhaps we should be more agressive about ignoring parameter changes.
Project Member

Comment 2 by bugdroid1@chromium.org, Apr 11 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518

commit f70d47db0b462dbc08d4d6ae2e633e4e5b0af518
Author: agrieve <agrieve@chromium.org>
Date: Tue Apr 11 17:48:20 2017

//tools/binary_size: Group [clone] and ** symbols

Two types of groups:
1. Those that end with "[clone .part.#]"
2. Star symbols (e.g.: "** symbol gap 3")

To handle grouped symbols:
* Print(recursive=True) added
* Diff() updated to be recursive
* Tests updated

For the .size files that motivated this change, the diff before had:
    355 symbols added (+), 2964 changed (~), 300 removed (-)
and after:
    345 symbols added (+), 2975 changed (~), 290 removed (-)

I was hoping for a bigger reduction, but it turns out the majority of
the "noise" is actually from different functions being inlined.

This change also changes map2size.py from positional arguments to
having: --elf-file, --output-file. It also adds --no-source-paths.
These flags make it obvious that the tool can still be used with only
a .map file.

BUG= 681694 , 708865 

Review-Url: https://codereview.chromium.org/2809043003
Cr-Commit-Position: refs/heads/master@{#463678}

[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/console.py
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/create_html_breakdown.py
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/describe.py
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/file_format.py
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/integration_test.py
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/map2size.py
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/models.py
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/testdata/ActualDiff.golden
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/testdata/ConsoleNullDiff.golden
[add] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/testdata/FullDescription.golden
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/testdata/Map2Size.golden
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/testdata/SymbolGroupMethods.golden
[modify] https://crrev.com/f70d47db0b462dbc08d4d6ae2e633e4e5b0af518/tools/binary_size/testdata/test.map

The commit in #2 helps this a bit, but I'm not 100% sure the remaining "noise" is from different inlining, or whether it could still be improved by using "nm" to gather all the names for symbols at the same address.

E.g.: nm --print-size | sort shows:

002a479c t $t
002a479d 00000004 t base::internal::LockImpl::Unlock()
002a479d 00000004 t ion::port::Mutex::Unlock()
002a479d 00000004 t rtc::CriticalSection::Leave() const
002a479d 00000004 t sfntly::Lock::Unlock()
002a479d 00000004 t unlock_buffer_pool
002a479d 00000004 t v8::base::Mutex::Unlock()
002a479d 00000004 t v8::base::RecursiveMutex::Unlock()
002a479d 00000004 t WTF::MutexBase::unlock()
002a47a0 t $t


And I've confirmed with codesearch that all of these methods are identical.

Only base::internal::LockImpl::Unlock() shows in the linker .map

Another example:
002a5288 t $t
002a5289 0000001a t scoped_refptr<base::SequencedTaskRunner>::~scoped_refptr()
002a5289 0000001a t scoped_refptr<base::SequencedTaskRunner>::~scoped_refptr()
002a5289 0000001a t scoped_refptr<base::SingleThreadTaskRunner>::~scoped_refptr()
002a5289 0000001a t scoped_refptr<base::SingleThreadTaskRunner>::~scoped_refptr()
002a5289 0000001a t scoped_refptr<base::TaskRunner>::~scoped_refptr()
002a5289 0000001a t scoped_refptr<base::TaskRunner>::~scoped_refptr()
002a5289 0000001a t scoped_refptr<blink::scheduler::internal::TaskQueueImpl>::~scoped_refptr()
002a5289 0000001a t scoped_refptr<blink::scheduler::internal::TaskQueueImpl>::~scoped_refptr()
002a5289 0000001a t scoped_refptr<blink::scheduler::TaskQueue>::~scoped_refptr()
002a5289 0000001a t scoped_refptr<blink::scheduler::TaskQueue>::~scoped_refptr()
002a5289 0000001a t syncer::internal::WeakHandleCoreBase::~WeakHandleCoreBase()
002a5289 0000001a t syncer::internal::WeakHandleCoreBase::~WeakHandleCoreBase()
002a52a4 t $t


Some smaller symbols are actually screens long (hundreds that map to the same address for no-op functions)

Some non-trivial functions also have screens worth of dupes, because they are all template specializations of the same template function for similar classes.


Another example: From map file we have:
  560888 t@0x2b72c8   size=4  padding=0  size_without_padding=4
             source_path=chrome/common/file_patcher.mojom.cc    object_path=chrome/common/mojo_bindings/file_patcher.mojom.o
             is_anonymous=0  name=chrome::mojom::FilePatcherStubDispatch::Accept
                        full_name=chrome::mojom::FilePatcherStubDispatch::Accept(chrome::mojom::FilePatcher*, mojo::Message*)
From nm we have:

002b72c8 t $t
002b72c9 00000004 t about_handler::AboutProtocolHandler::IsSafeRedirectTarget(GURL const&) const
002b72c9 00000004 t AndroidLiveTabContext::IsTabPinned(int) const
002b72c9 00000004 t AndroidLiveTabContext::ReplaceRestoredTab(std::__ndk1::vector<sessions::SerializedNavigationEntry, std::__ndk1::allocator<sessions::SerializedNavigationEntry> > const&, int, bool, st
d::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, sessions::PlatformSpecificTabData const*, std::__ndk1::basic_string<char, std::__ndk1::char_traits<ch
ar>, std::__ndk1::allocator<char> > const&)
002b72c9 00000004 t android::SceneLayer::ShouldShowBackground()
002b72c9 00000004 t android::TabWebContentsDelegateAndroid::RequestPpapiBrokerPermission(content::WebContents*, GURL const&, base::FilePath const&, base::Callback<void (bool), (base::internal::CopyMode)
1, (base::internal::RepeatMode)1> const&)
002b72c9 00000004 t app_modal::AppModalDialog::IsJavaScriptModalDialog()
002b72c9 00000004 t autofill::AutofillSaveCardInfoBarDelegateMobile::ShouldExpire(infobars::InfoBarDelegate::NavigationDetails const&) const
002b72c9 00000004 t autofill::IsDesktopPlatform()
002b72c9 00000004 t autofill::mojom::AutofillAgentStubDispatch::AcceptWithResponder(autofill::mojom::AutofillAgent*, mojo::Message*, std::__ndk1::unique_ptr<mojo::MessageReceiverWithStatus, std::__ndk1:
:default_delete<mojo::MessageReceiverWithStatus> >)
002b72c9 00000004 t autofill::mojom::AutofillDriverStubDispatch::AcceptWithResponder(autofill::mojom::AutofillDriver*, mojo::Message*, std::__ndk1::unique_ptr<mojo::MessageReceiverWithStatus, std::__ndk1::default_delete<mojo::MessageReceiverWithStatus> >)
002b72c9 00000004 t autofill::mojom::PasswordGenerationAgentStubDispatch::AcceptWithResponder(autofill::mojom::PasswordGenerationAgent*, mojo::Message*, std::__ndk1::unique_ptr<mojo::MessageReceiverWithStatus, std::__ndk1::default_delete<mojo::MessageReceiverWithStatus> >)
002b72c9 00000004 t autofill::mojom::PasswordManagerClientStubDispatch::AcceptWithResponder(autofill::mojom::PasswordManagerClient*, mojo::Message*, std::__ndk1::unique_ptr<mojo::MessageReceiverWithStatus, std::__ndk1::default_delete<mojo::MessageReceiverWithStatus> >)
002b72c9 00000004 t autofill::mojom::PasswordManagerDriverStubDispatch::AcceptWithResponder(autofill::mojom::PasswordManagerDriver*, mojo::Message*, std::__ndk1::unique_ptr<mojo::MessageReceiverWithStatus, std::__ndk1::default_delete<mojo::MessageReceiverWithStatus> >)
002b72c9 00000004 t autofill::PasswordGenerationPopupViewAndroid::IsPointInPasswordBounds(gfx::Point const&)
002b72c9 00000004 t background_loader::BackgroundLoaderContents::CheckMediaAccessPermission(content::WebContents*, GURL const&, content::MediaStreamType)
002b72c9 00000004 t background_loader::BackgroundLoaderContents::ShouldCreateWebContents(content::WebContents*, content::SiteInstance*, int, int, int, content::mojom::WindowContainerType, GURL const&, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, GURL const&, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, content::SessionStorageNamespace*)
002b72c9 00000004 t background_loader::BackgroundLoaderContents::ShouldFocusPageAfterCrash()
002b72c9 00000004 t banners::AppBannerManager::IsWebAppInstalled(content::BrowserContext*, GURL const&, GURL const&)
002b72c9 00000004 t base::debug::BeingProfiled()
002b72c9 00000004 t base::debug::GetProfilerAddDynamicSymbolFunc()
002b72c9 00000004 t base::debug::GetProfilerDynamicFunctionEntryHookFunc()
002b72c9 00000004 t base::debug::GetProfilerMoveDynamicSymbolFunc()
002b72c9 00000004 t base::debug::GetProfilerReturnAddrResolutionFunc()
002b72c9 00000004 t base::debug::IsBinaryInstrumented()
002b72c9 00000004 t base::GetDefaultThreadStackSize(pthread_attr_t const&)
002b72c9 00000004 t base::HistogramBase::FindCorruption(base::HistogramSamples const&) const
002b72c9 00000004 t base::Histogram::GetHistogramType() const
002b72c9 00000004 t base::internal::LockImpl::PriorityInheritanceAvailable()
002b72c9 00000004 t base::Pickle::HasAttachments() const
002b72c9 00000004 t base::Pickle::ReadAttachment(base::PickleIterator*, scoped_refptr<base::Pickle::Attachment>*) const
002b72c9 00000004 t base::Pickle::WriteAttachment(scoped_refptr<base::Pickle::Attachment>)
<snip> (high hundreds of lines)

It's not clear whether the map file is stable or not though, because nm's output is sorted by symbol name rather than by address :/.

Just how many duplicate symbols are there?
nm.first3t has just <addr> <size>
nm.first3tu is run through uniq
-rw-r----- 1 agrieve eng 6431020 Apr 12 22:39 nm.first3t
-rw-r----- 1 agrieve eng 4949740 Apr 12 22:39 nm.first3tu

So, map file has only 75% of total symbol names in it, and 25% are identical!

Not sure if it's worth adding all the names to .size symbols, or maybe it's worth at least adding a count of symbols folded together so that we know removing a symbol would not help with code size.


Hacked up a version that appends all names to shared symbols, and found that most shared large symbols belong to the same .o file:

Attached dump of "Print(size_info.symbols.WherePathMatches(r'\{shared'), verbose=True)".
Paths have the share count appended to them, and names are join()ed by |<==>|

Here are some interesting parts inline:
-------------------------------------------------------------------

Summary shows that 535kb of symbols in .text are shared. Total .text size is 35.0mb (about 1.5%)


Showing 9,205 symbols with total size: 548692 bytes
.text=535kb      .rodata=0 bytes    other=0 bytes    total=535kb
Number of object files: 3567

-------------------------------------------------------------------

One category of de-dupes show symbols where it looks to be accurate to keep source-file information.

First columns are: running total, type, size
    1640 t@0x8f8780   size=1640  padding=0  size_without_padding=1640
             source_path=third_party/libvpx/source/libvpx/vpx_dsp/arm/loopfilter_16_neon.asm.S {shared by 2 symbols}    object_path=third_party/libvpx/libvpx_assembly_arm.a/loopfilter_16_neon.asm.o {shared}
             is_anonymous=0  name=* _mb_lpf_horizontal_edge|<==>|mb_lpf_horizontal_edge
    3248 t@0x121faf0  size=1608  padding=0  size_without_padding=1608
             source_path=v8/src/compiler/bytecode-analysis.cc {shared by 6 symbols}     object_path=v8/v8_base/bytecode-analysis.o {shared}
             is_anonymous=0  name=* std::__ndk1::deque<v8::internal::compiler::BytecodeAnalysis::LoopStackEntry, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::BytecodeAnalysis::LoopStackEntry> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::GraphReducer::NodeState, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::GraphReducer::NodeState> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::MemoryOptimizer::Token, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::MemoryOptimizer::Token> >::__add_back_capacity()|<==>|std::__ndk1::deque<std::__ndk1::pair<v8::internal::compiler::PendingAssessment const*, int>, v8::internal::RecyclingZoneAllocator<std::__ndk1::pair<v8::internal::compiler::PendingAssessment const*, int> > >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::Node::InputEdges::iterator, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::Node::InputEdges::iterator> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::RepresentationSelector::NodeState, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::RepresentationSelector::NodeState> >::__add_back_capacity()
    4856 t@0x78ac64   size=1608  padding=0  size_without_padding=1608
             source_path=v8/src/compiler/ast-graph-builder.cc {shared by 13 symbols}    object_path=v8/v8_base/ast-graph-builder.o {shared}
             is_anonymous=0  name=* std::__ndk1::deque<v8::internal::compiler::LivenessAnalyzerBlock*, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::LivenessAnalyzerBlock*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::BitVector*, v8::internal::RecyclingZoneAllocator<v8::internal::BitVector*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::Handle<v8::internal::Object>, v8::internal::RecyclingZoneAllocator<v8::internal::Handle<v8::internal::Object> > >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::CodeGenerator::DeoptimizationState*, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::CodeGenerator::DeoptimizationState*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::DeoptimizationExit*, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::DeoptimizationExit*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::Node*, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::Node*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::InstructionScheduler::ScheduleGraphNode*, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::InstructionScheduler::ScheduleGraphNode*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::Instruction*, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::Instruction*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::ReferenceMap*, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::ReferenceMap*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::RpoNumber, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::RpoNumber> >::__add_back_capacity()|<==>|std::__ndk1::deque<int, v8::internal::RecyclingZoneAllocator<int> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::BasicBlock*, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::BasicBlock*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::Map*, v8::internal::RecyclingZoneAllocator<v8::internal::Map*> >::__add_back_capacity()
    6424 t@0x8f8160   size=1568  padding=0  size_without_padding=1568
             source_path=third_party/libvpx/source/libvpx/vpx_dsp/arm/intrapred_neon_asm.asm.S {shared by 2 symbols}    object_path=third_party/libvpx/libvpx_assembly_arm.a/intrapred_neon_asm.asm.o {shared}
             is_anonymous=0  name=* _vpx_v_predictor_4x4_neon|<==>|vpx_v_predictor_4x4_neon

   10420 t@0x8f7b48   size=1228  padding=0  size_without_padding=1228
             source_path=third_party/opus/celt_pitch_xcorr_arm_gnu.S {shared by 2 symbols}      object_path=third_party/opus/libopus.a/celt_pitch_xcorr_arm_gnu.o {shared}
             is_anonymous=0  name=* xcorr_kernel_neon|<==>|xcorr_kernel_neon_start

   16248 t@0x11ae6bc  size=1140  padding=0  size_without_padding=1140
             source_path=v8/src/ast/ast-expression-rewriter.cc {shared by 3 symbols}    object_path=v8/v8_base/ast-expression-rewriter.o {shared}
             is_anonymous=0  name=* v8::internal::AstExpressionRewriter::VisitReturnStatement(v8::internal::ReturnStatement*)|<==>|v8::internal::AstExpressionRewriter::VisitExpressionStatement(v8::internal::ExpressionStatement*)|<==>|v8::internal::AstExpressionRewriter::VisitSloppyBlockFunctionStatement(v8::internal::SloppyBlockFunctionStatement*)

   17384 t@0x8faac0   size=1136  padding=0  size_without_padding=1136
             source_path= {shared by 2 symbols}         object_path=third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a/_arm_muldivdf3.o {shared}
             is_anonymous=0  name=* __muldf3|<==>|__aeabi_dmul
   18456 t@0x8f8de8   size=1072  padding=0  size_without_padding=1072
             source_path=third_party/libvpx/source/libvpx/vpx_dsp/arm/loopfilter_4_neon.asm.S {shared by 2 symbols}     object_path=third_party/libvpx/libvpx_assembly_arm.a/loopfilter_4_neon.asm.o {shared}
             is_anonymous=0  name=* _vpx_lpf_horizontal_4_neon|<==>|vpx_lpf_horizontal_4_neon
   19444 t@0x8f9218   size=988  padding=0  size_without_padding=988
             source_path=third_party/libvpx/source/libvpx/vpx_dsp/arm/loopfilter_8_neon.asm.S {shared by 2 symbols}     object_path=third_party/libvpx/libvpx_assembly_arm.a/loopfilter_8_neon.asm.o {shared}
             is_anonymous=0  name=* _vpx_lpf_horizontal_8_neon|<==>|vpx_lpf_horizontal_8_neon
-------------------------------------------------------------------

Next category of de-dupes is ~100 different versions of std::__ndk1::__tree::destroy

    7836 t@0x2b2eb8   size=1412  padding=0  size_without_padding=1412
             source_path=base/command_line.cc {shared by 53 symbols}    object_path=base/base/command_line.o {shared}
             is_anonymous=0  name=* std::__ndk1::__tree<std::__ndk1::__value_type<base::BasicStringPiece<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const*>, std::__ndk1::__map_value_compare<base::BasicStringPiece<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, std::__ndk1::__value_type<base::BasicStringPiece<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const*>, std::__ndk1::less<base::BasicStringPiece<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > > >, true>, std::__ndk1::allocator<std::__ndk1::__value_type<base::BasicStringPiece<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const*> > >::destroy(std::__ndk1::__tree_node<std::__ndk1::__value_type<base::BasicStringPiece<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const*>, void*>*)|<==>|std::__ndk1::__tree<unsigned int, std::__ndk1::less<unsigned int>, std::__ndk1::allocator<unsigned int> >::destroy(std::__ndk1::__tree_node<unsigned int, void*>*)|<==>|std::__ndk1::__tree<long long, std::__ndk1::less<long long>, std::__ndk1::allocator<long long> >::destroy(std::__ndk1::__tree_node<long long, void*>*)|<==>| SNIP!

    9192 t@0x2e7a38   size=1356  padding=0  size_without_padding=1356
             source_path=base/feature_list.cc {shared by 13 symbols}    object_path=base/base/feature_list.o {shared}
             is_anonymous=0  name=* std::__ndk1::__tree<std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, base::FeatureList::OverrideEntry>, std::__ndk1::__map_value_compare<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, base::FeatureList::OverrideEntry>, std::__ndk1::less<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > >, true>, std::__ndk1::allocator<std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, base::FeatureList::OverrideEntry> > >::destroy(std::__ndk1::__tree_node<std::__ndk1::__value_type<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, base::FeatureList::OverrideEntry>, void*>*)|<==>|std::__ndk1::__tree<std::__ndk1::__value_type<std:

   11604 t@0x736d7c   size=1184  padding=0  size_without_padding=1184
             source_path=v8/src/asmjs/asm-typer.cc {shared by 24 symbols}       object_path=v8/v8_base/asm-typer.o {shared}
             is_anonymous=0  name=* std::__ndk1::__tree<int, std::__ndk1::less<int>, v8::internal::ZoneAllocator<int> >::destroy(std::__ndk1::__tree_node<int, void*>*)|<==>|std::__ndk1::__tree<std::__ndk1::__value_type<int, unsigned int>, std::__ndk1::__map_value_compare<int, std::__ndk1::__value_type<int, unsigned int>, std::__ndk1::less<int>, true>, v8::internal::ZoneAllocator<std::__ndk1::__value_type<int, unsigned int> > >::destroy(std::__ndk1::__tree_node<std::__ndk1::__value_type<int, unsigned int>, void*>*)|<==>|std::

   20428 t@0x5112f8   size=984  padding=0  size_without_padding=984
             source_path=base/supports_user_data.cc {shared by 3 symbols}       object_path=base/base/supports_user_data.o {shared}
             is_anonymous=0  name=* std::__ndk1::__tree<std::__ndk1::__value_type<void const*, std::__ndk1::unique_ptr<base::SupportsUserData::Data, std::__ndk1::default_delete<base::SupportsUserData::Data> > >, std::__ndk1::__map_value_compare<void const*, std::__ndk1::__value_type<void const*, std::__ndk1::unique_ptr<base::SupportsUserData::Data, std::__ndk1::default_delete<base::SupportsUserData::Data> > >, std::__ndk1::less<void const*>, true>, std::__ndk1::allocator<std::__ndk1::__value_type<void const*, std::__ndk1::unique_ptr<base::SupportsUserData::Data, std::__ndk1::default_delete<base::SupportsUserData::Data> > > > >::destroy(std::__ndk1::__tree_node<std::__ndk1::__value_type<void const*, std::__ndk1::unique_ptr<base::SupportsUserData::Data, std::__ndk1::default_delete<base::SupportsUserData::Data> > >, void*>*)|<==>|std::__ndk1::__tree<std::__ndk1::__value_type<gfx::Image::RepresentationType, std::__ndk1::unique_ptr<gfx::internal::ImageRep, std::__ndk1::default_delete<gfx::internal::ImageRep> > >, std::__ndk1::__map_value_compare<gfx::Image::RepresentationType, std::__ndk1::__value_type<gfx::Image::RepresentationType, std::__ndk1::unique_ptr<gfx::internal::ImageRep, std::__ndk1::default_delete<gfx::internal::ImageRep> > >, std::__ndk1::less<gfx::Image::RepresentationType>, true>, std::__ndk1::allocator<std::__ndk1::__value_type<gfx::Image::RepresentationType, std::__ndk1::unique_ptr<gfx::internal::ImageRep, std::__ndk1::default_delete<gfx::internal::ImageRep> > > > >::destroy(std::__ndk1::__tree_node<std::__ndk1::__value_type<gfx::Image::RepresentationT
-------------------------------------------------------------------

Next, we have deque, where blame should be spread out:

   12772 t@0x2b57ec   size=1168  padding=0  size_without_padding=1168
             source_path=base/at_exit.cc {shared by 15 symbols}         object_path=base/base/at_exit.o {shared}
             is_anonymous=0  name=* std::__ndk1::deque<base::Callback<void (), (base::internal::CopyMode)1, (base::internal::RepeatMode)1>, std::__ndk1::allocator<base::Callback<void (), (base::internal::CopyMode)1, (base::internal::RepeatMode)1> > >::__add_back_capacity()|<==>|std::__ndk1::deque<std::__ndk1::unique_ptr<base::internal::Task, std::__ndk1::default_delete<base::internal::Task> >, std::__ndk1::allocator<std::__ndk1::unique_ptr<base::internal::Task, std::__ndk1::default_delete<base::internal::Task> > > >::__add_back_capacity()|<==>|std::__ndk1::deque<std::__ndk1::unique_ptr<cc::DrawPolygon, std::__ndk1::default_delete<cc::DrawPolygon> >, std::__ndk1::allocator<std::__ndk1::unique_ptr<cc::DrawPolygon, std::__ndk1::default_delete<cc::DrawPolygon> > > >::__add_back_capacity()|<==>|std::__ndk1::deque<std::__ndk1::unique_ptr<cc::GLRenderer::SyncQuery, std::__ndk1::default_delete<cc::GLRenderer::SyncQuery> >, std::__ndk1::allocator<std::__ndk1::unique_ptr<cc::GLRenderer::SyncQuery, std::__ndk1::default_delete<cc::GLRenderer::SyncQuery> > > >::__add_back_capacity()|<==>|std::__ndk1::deque<std::__ndk1::unique_ptr<cc::StagingBuffer, std::__ndk1::default_delete<cc::StagingBuffer> >, std::__ndk1::allocator<std::__ndk1::unique_ptr<cc::StagingBuffer, std::__ndk1::default_delete<cc::StagingBuffer> > > >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::CompilationJob*, std::__ndk1::allocator<v8::internal::CompilationJob*> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::HeapObject*, std::__ndk1::allocator<v8::internal::HeapObject*> >::__add_


   13940 t@0x433d18   size=1168  padding=0  size_without_padding=1168
             source_path=base/files/file_enumerator_posix.cc {shared by 4 symbols}      object_path=base/base/file_enumerator_posix.o {shared}
             is_anonymous=0  name=* std::__ndk1::deque<base::FilePath, std::__ndk1::allocator<base::FilePath> >::__add_back_capacity()|<==>|std::__ndk1::deque<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::allocator<std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > > >::__add_back_capacity()|<==>|std::__ndk1::deque<std::__ndk1::vector<std::__ndk1::unique_ptr<cc::ResourceProvider::ScopedReadLockGL, std::__ndk1::default_delete<cc::ResourceProvider::ScopedReadLockGL> >, std::__ndk1::allocator<std::__ndk1::unique_ptr<cc::ResourceProvider::ScopedReadLockGL, std::__ndk1::default_delete<cc::ResourceProvider::ScopedReadLockGL> > > >, std::__ndk1::allocator<std::__ndk1::vector<std::__ndk1::unique_ptr<cc::ResourceProvider::ScopedReadLockGL, std::__ndk1::default_delete<cc::ResourceProvider::ScopedReadLockGL> >, std::__ndk1::allocator<std::__ndk1::unique_ptr<cc::ResourceProvider::ScopedReadLockGL, std::__ndk1::default_delete<cc::ResourceProvider::ScopedReadLockGL> > > > > >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::HeapGraphEdge, std::__ndk1::allocator<v8::internal::HeapGraphEdge> >::__add_back_capacity()
   15108 t@0x942b28   size=1168  padding=0  size_without_padding=1168
             source_path=base/trace_event/trace_log.cc {shared by 3 symbols}    object_path=base/base/trace_log.o {shared}
             is_anonymous=0  name=* std::__ndk1::deque<base::TimeTicks, std::__ndk1::allocator<base::TimeTicks> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::TranslatedState::ObjectPosition, std::__ndk1::allocator<v8::internal::TranslatedState::ObjectPosition> >::__add_back_capacity()|<==>|std::__ndk1::deque<std::__ndk1::pair<void (*)(v8::Isolate*, void*), void*>, std::__ndk1::allocator<std::__ndk1::pair<void (*)(v8::Isolate*, void*), void*> > >::__add_back_capacity()


-------------------------------------------------------------------

But then, we have deque, where blame is localized to v8:

   22260 t@0x1246edc  size=884  padding=0  size_without_padding=884
             source_path=v8/src/compiler/int64-lowering.cc {shared by 2 symbols}        object_path=v8/v8_base/int64-lowering.o {shared}
             is_anonymous=0  name=* std::__ndk1::deque<v8::internal::compiler::Int64Lowering::NodeState, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::Int64Lowering::NodeState> >::__add_back_capacity()|<==>|std::__ndk1::deque<v8::internal::compiler::SimdScalarLowering::NodeState, v8::internal::RecyclingZoneAllocator<v8::internal::compiler::SimdScalarLowering::NodeState> >::__add_back_capacity()



Thus far, this is on 20kb out of 500kb total, and I don't see any great heuristics (other than: _vpx_convolve8_horiz_neon|<==>|vpx_convolve8_horiz_neon, which accounts for 7kb)
shared_syms.txt.gz
1.7 MB Download
Blocking: 681694
Here's another source of noise found in: https://bugs.chromium.org/p/chromium/issues/detail?id=716393

+       44 r@0x2a13ba8  24      obj/third_party/WebKit/Source/platform/platform/RecordingImageBufferSurface.o
               CSWTCH.61
-       20 r@0x2a0f9b8  -24     obj/third_party/WebKit/Source/platform/platform/RecordingImageBufferSurface.o
               CSWTCH.62
-        4 r@0x2b58888  -16     obj/third_party/WebKit/Source/modules/vr/libvr.a(VRDisplay.o)
               ._468
+       20 r@0x2b5ca88  16      obj/third_party/WebKit/Source/modules/vr/libvr.a(VRDisplay.o)
               ._470
-        4 r@0x2b7e148  -16     obj/components/history/content/browser/libbrowser.a(download_conversions.o)
               CSWTCH.29
-      -12 r@0x2a101c0  -16     obj/third_party/WebKit/Source/platform/platform/SkiaUtils.o
               CSWTCH.31
+        4 r@0x2a143a0  16      obj/third_party/WebKit/Source/platform/platform/SkiaUtils.o
               CSWTCH.32
+       20 r@0x2b7e120  16      obj/chrome/browser/ui/libui.a(page_info_ui.o)
               CSWTCH.34
Project Member

Comment 7 by bugdroid1@chromium.org, May 1 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/e2db5397b49842931f2f2a6b2c666c2a8892fd89

commit e2db5397b49842931f2f2a6b2c666c2a8892fd89
Author: agrieve <agrieve@chromium.org>
Date: Mon May 01 18:34:24 2017

supersize: Track symbol aliases and shared symbols

An alias is when multiple names map to the same symbol. This happens a
lot with small member functions (e.g. getters), as well as with C++
templates. The .map file choses only one name for each symbol, but using
nm we can recover the complete list.

A shared symbol is one that exists in multiple .o files. The linker map
picks one path to attribute the symbol to, but using nm we can recover
the complete list of .o files containing the symbol.

For aliases, each one is stored as a separate Symbol entry, and a new
attribute "pss" returns size / num_aliases.

For shared symbols, rather than storing all paths for a symbol, the
paths are altered to be the common ancestor. E.g.:
/a/b/c.o and /a/d/f.o --> /a/{shared}/2  (2 is the number of paths)

For ChromePublic.apk:
* 17717 symbols have shared ownership (991402 bytes)
* Contains 83869 aliases, mapped to 9209 addresses (550582 bytes)

BUG= 708865 

Review-Url: https://codereview.chromium.org/2851473003
Cr-Commit-Position: refs/heads/master@{#468362}

[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/archive.py
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/concurrent.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/console.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/describe.py
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/diff.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/file_format.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/helpers.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/html_report.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/integration_test.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/linker_map_parser.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/main.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/models.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/ninja_parser.py
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/nm.py
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/template/D3SymbolTreeMap.js
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/Archive.golden
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/Archive_Elf.golden
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/Archive_OutputDirectory.golden
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/Console.golden
[rename] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/Diff_Basic.golden
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/FullDescription.golden
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/create-test-size.sh
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_output_directory/args.gn
[rename] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_output_directory/build.ninja
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_output_directory/elf
[rename] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_output_directory/sub.ninja
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_toolchain/c++filt
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_toolchain/git
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_cppfilt.py
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_git.py
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_nm.py
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_readelf.py
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_toolchain/nm
[add] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/mock_toolchain/readelf
[modify] https://crrev.com/e2db5397b49842931f2f2a6b2c666c2a8892fd89/tools/binary_size/libsupersize/testdata/test.map

Project Member

Comment 8 by bugdroid1@chromium.org, May 3 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/47f9431d5a69ae9e81faa6472d8b5a188eb63242

commit 47f9431d5a69ae9e81faa6472d8b5a188eb63242
Author: agrieve <agrieve@chromium.org>
Date: Wed May 03 18:41:04 2017

supersize: Tweak diff symbol matching for generated symbols

E.g. CSWTCH.61 and CSWTCH.62 will now match as long as they are in the
same object file.

BUG= 708865 , 717550 

Review-Url: https://codereview.chromium.org/2857153002
Cr-Commit-Position: refs/heads/master@{#469045}

[modify] https://crrev.com/47f9431d5a69ae9e81faa6472d8b5a188eb63242/tools/binary_size/libsupersize/diff.py
[modify] https://crrev.com/47f9431d5a69ae9e81faa6472d8b5a188eb63242/tools/binary_size/libsupersize/integration_test.py
[modify] https://crrev.com/47f9431d5a69ae9e81faa6472d8b5a188eb63242/tools/binary_size/libsupersize/models.py

Status: Fixed (was: Assigned)
All known causes for noise are fixed! Let's file a new one should anything else come up as this is getting a bit hard to follow.
Labels: -binary-size Performance-Size

Sign in to add a comment