Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symbol resolution fails for system libraries in DevTools stack traces in Performance tab #95

Closed
pwasowski2 opened this issue May 25, 2021 · 13 comments · Fixed by #104
Closed
Assignees

Comments

@pwasowski2
Copy link

The problem is described in: #53 (comment)

run an app in profile mode and open the Performance view in Flutter DevTools, you will see this screen:

DevTools view

As you can see in the stack traces at the bottom of the view (CPU Flame Chart), symbols are resolved to their offsets within the shared objects (/proc/self/fd/35/lib/libflutter_engine.so+0x.....) but not their actual names. I'm not sure whether this is normal (because the symbols were stripped out).

@pwasowski2 pwasowski2 self-assigned this May 25, 2021
@pwasowski2 pwasowski2 mentioned this issue May 25, 2021
12 tasks
@bbrto21
Copy link

bbrto21 commented May 27, 2021

The inspiration from this conversation(#97 (comment)) has led to the following progress:

Screenshot from 2021-05-27 12-06-48

@bbrto21
Copy link

bbrto21 commented May 31, 2021

I checked the profile tool using three .so as follows
Among them, most symbols were resolved when using .so with the --unoptimized option.
@pwasowski2 Could you check it?

profile
profile

profile.so.unstripped
profile so unstripped

profile_unopt
profile_unopt
To use --unoptimized, you may need this

diff --git a/shell/platform/tizen/BUILD.gn b/shell/platform/tizen/BUILD.gn
index 809474371..550d19517 100644
--- a/shell/platform/tizen/BUILD.gn
+++ b/shell/platform/tizen/BUILD.gn
@@ -161,6 +161,7 @@ template("embedder_for_profile") {
     public_deps = [ ":flutter_engine" ]
 
     deps = [
+      "//flutter/runtime:libdart",
       "//flutter/shell/platform/common/cpp:common_cpp",
       "//flutter/shell/platform/common/cpp:common_cpp_input",
       "//flutter/shell/platform/common/cpp:common_cpp_library_headers",

@bbrto21
Copy link

bbrto21 commented May 31, 2021

As a result of test and trying based on several config options, I think it depends on "//build/config:debug"

@pwasowski2
Copy link
Author

@bbrto21, I think you've nailed it 👌 Thanks a lot 😃

Native symbols indeed resolve after adding --unoptimized flag. Some of them (e.g. from libc.so) are still not resolved, but installing related *-debug.rpms solves the problem and proper names are shown for them, too.

The question now is, what should we do about it? IMO, turning --unoptimized on by default for release binaries is not an option. Adding this flag makes binaries like libflutter_tizen_mobile.so orders of magnitude larger (15 MB vs 0.35 MB when I checked it) and probably has other side effects, that we wouldn't like to see in release binaries, too.

What about just adding information, that adding --unoptimized flag switches on the symbol resolution, to the wiki (I guess this will be the right place: https://github.com/flutter-tizen/flutter-tizen/wiki/Miscellaneous)?

@bbrto21, @swift-kim what do you think about it?

@swift-kim
Copy link
Member

turning --unoptimized on by default for release binaries is not an option.

Agreed.

and probably has other side effects,

Right. Turning on the unopt flag significantly lowers the performance as well. And that's why we can't use the "unoptimized" binaries for CPU profiling and performance analysis. So if we want to get correct results from the profiling tools, we need to find a way to fix the symbol resolution issue without disabling optimizations.

What about just adding information, that adding --unoptimized flag switches on the symbol resolution, to the wiki

I think the best place would be the "Building the engine" page.

@bbrto21
Copy link

bbrto21 commented Jun 1, 2021

@pwasowski2 @swift-kim I agree too

@pwasowski2
Copy link
Author

Ok, I'll go further down the rabbit hole and see how we can get all the symbols for profile builds ;)

I'll update the wiki afterwards.

@pwasowski2
Copy link
Author

pwasowski2 commented Jun 2, 2021

I have investigated the problem a little bit more and have found out a way of resolving more symbols on profile builds.

First, look at this change draft of tools/gn : pwasowski2@b9b44b9
Flutter devs have commented out enable_profiling flag from gn wrapper script. It means, that enable_profiling is always false and thus this conditional is not executed: https://github.com/flutter/buildroot/blob/ff1975def53bfdaa1ff3f4b0cceabf54e1323392/build/config/compiler/BUILD.gn#L346.
(When enable_profiling is true, -g flag is added to cflags, which seems to be the flag for turning symbols on).

After applying pwasowski2@b9b44b9 and running a build with the following set of gn flags (no --unoptimized):

flutter/tools/gn \
--target-os linux \
--linux-cpu arm \
--no-goma \
--target-toolchain `pwd`/tizen_tools/toolchains \
--target-sysroot `pwd`/tizen_tools/sysroot/arm \
--target-triple armv7l-tizen-linux-gnueabi \
--runtime-mode profile \
--enable-fontconfig \
--embedder-for-target \
--disable-desktop-embeddings \
--build-tizen-shell

we get more symbols in the profiler view.

enable_profiling = false
linux_profile_arm_enable_profiling_commented_out

enable_profiling = true
linux_profile_arm_enable_profiling_uncommented

As you can see, many more symbols are resolved, but some of the libflutter_engine.so parts are still unresolved.
Unfortunately, I haven't found any way to resolve all symbols from this .so.

I have tried increasing symbol_level of profile builds to the same as debug builds: pwasowski2/buildroot@8f6a8a5, but it didn't help to resolve more symbols.

enable_profiling = true, symbol_level = 2
linux_profile_arm_enable_profiling_uncommented_symbols_set_2

In case, you're wondering, if setting gcc's -g3 flag would enable resolution of all the symbols - the answer is no, as you can see in the last screenshot:

enable_profiling = true, symbol_level = 2, -g3 gcc flag
linux_profile_arm_enable_profiling_uncommented_symbols_set_2_gcc_g3_level

I think we can safely apply this pwasowski2@b9b44b9 to get almost all symbols, without setting --unoptimized or any other flag.

@swift-kim, @bbrto21 what do you think about it?

Edit: I've created a PR for enabling enable_profiling: #104

@swift-kim
Copy link
Member

Thank you for the detailed analysis! The suggested change looks good to me, and I have a few quick questions:

  • Are the remaining unresolved symbols related to text rendering? If so, could you check again by deleting the 271st line of the shell/platform/embedder/BUILD.gn file and rebuilding the engine? The version script file flutter_engine_exports.lst is supplied to libflutter_engine.so to prevent libfreetype symbols from being exported (Resolve freetype symbols locally #85).
  • Did you try enabling the enable_full_stack_frames_for_profiling option which is defined along with enable_profiling in build/config/profiler.gni?

And some doubts:

  • Would enabling enable_profiling cause any noticeable performance degradation? It seems they (Google) disabled it because it affected their benchmarks.
  • Would enabling enable_profiling cause any issue on x86 emulator? It seems they (Google) had an issue related to unexpected text relocations on Android x86 by enabling the option, but this shouldn't be a problem on Tizen I think.

@bbrto21
Copy link

bbrto21 commented Jun 3, 2021

I have tried increasing symbol_level of profile builds to the same as debug builds: pwasowski2/buildroot@8f6a8a5, but it didn't help to resolve more symbols.

In case, you're wondering, if setting gcc's -g3 flag would enable resolution of all the symbols - the answer is no, as you can see in the last screenshot:

The last time I tried to use symbol_level, it only worked as expected with "//build/config:debug". of course, there is a slight performance penalty.
@pwasowski2 Could you check the below?

diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 44c276c..70169f8 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -5,6 +5,9 @@
 # define is_wasm
 import("//build/toolchain/wasm.gni")
 
+# define enable_profiling
+import("//build/config/profiler.gni")
+
 # =============================================================================
 # PLATFORM SELECTION
 # =============================================================================
@@ -369,7 +372,10 @@ if (is_clang) {
 }
 
 # Optimizations and debug checking.
-if (is_debug) {
+if (enable_profiling) {
+  _native_compiler_configs += [ "//build/config:debug" ]
+  _default_optimization_config = "//build/config/compiler:optimize"
+} else if (is_debug) {
   _native_compiler_configs += [ "//build/config:debug" ]
   _default_optimization_config = "//build/config/compiler:no_optimize"
 } else {
@@ -382,7 +388,7 @@ _native_compiler_configs += [ _default_optimization_config ]
 if (symbol_level == -1) {
   # Linux is slowed by having symbols as part of the target binary, whereas
   # Mac and Windows have them separate, so in Release Linux, default them off.
-  if (is_debug || !is_linux) {
+  if (is_debug || !is_linux || enable_profiling) {
     symbol_level = 2
   } else if (is_asan || is_lsan || is_tsan || is_msan) {
     # Sanitizers require symbols for filename suppressions to work.

@pwasowski2
Copy link
Author

pwasowski2 commented Jun 4, 2021

Thanks for feedback, I have tested proposed build configuration changes and here's what I've found:

Are the remaining unresolved symbols related to text rendering? If so, could you check again by deleting the 271st line of the shell/platform/embedder/BUILD.gn file and rebuilding the engine? The version script file flutter_engine_exports.lst is supplied to libflutter_engine.so to prevent libfreetype symbols from being exported (#85).

It seems, the unresolved symbols don't come from Freetype. After removeing the ldflags = [ "-Wl,--version-script=" + rebase_path("flutter_engine_exports.lst") ] from shell/platform/embedder/BUILD.gn, some symbols are still unresolved.

enable_profiling = true, 271st line of the shell/platform/embedder/BUILD.gn commented out
linux_profile_arm_enable_profiling_uncommented_freetype_symbols_on

Did you try enabling the enable_full_stack_frames_for_profiling option which is defined along with enable_profiling in build/config/profiler.gni?

Yes, I have and unfortunately, it didn't help, too.

enable_profiling = true, enable_full_stack_frames_for_profiling enabled
linux_profile_arm_enable_profiling_uncommented_enable_full_stack_frames_for_profiling

The last time I tried to use symbol_level, it only worked as expected with "//build/config:debug". of course, there is a slight performance penalty.
@pwasowski2 Could you check the below?

I have applied the diff to my repo and some symbols were still unresolved. When I have tested symbols_level = 2 before, it was properly set by the compiler even without this change in build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn:

 # Optimizations and debug checking.
-if (is_debug) {
+if (enable_profiling) {
+  _native_compiler_configs += [ "//build/config:debug" ]
+  _default_optimization_config = "//build/config/compiler:optimize"
+} else if (is_debug) {

Update
@swift-kim, regarding performance - I have run a little benchmark with enable_profiling enabled and disabled and there was no significant difference in UI rendering time. I have run infinite_list app from https://github.com/flutter/samples and scrolled the screen 10 times. As you can see in the screens below, framerate is almost the same.

enable_profiling enabled
perf_profile_symbols_level_2

enable_profiling disabled
perf_profile_symbols_level_0

Here's the result of the same benchmark for debug build with --unoptimized flag - the framerate is 4 times smaller than in profile builds

debug build with --unoptimized
perf_debug_unopt

@pwasowski2
Copy link
Author

pwasowski2 commented Jun 7, 2021

One more benchmark, that was missing in my previous comment:

profile build with --unoptimized
linux_profile_arm_enable_profiling_commented_out_profile_unoptimized_build

Adding --unoptimized flag to --profile build seems to decrease the performance when compared to --profile with enable_profiling enabled, but only slightly. With both these settings, the same amount of symbols is resolved.

@swift-kim, @bbrto21, I have made this PR ready for review #104. Could you please take a look at it? :)
If we merge this PR, I think, we no longer need to add add information about enabling resolution of more symbols via --unoptimized gn flag to wiki - the same amount of symbols will be resolved by default in all profile builds.

@bbrto21
Copy link

bbrto21 commented Jun 8, 2021

Looks good!, I think this issue is almost closed now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants