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

Side by Side Diff: base/profiler/native_stack_sampler_win.cc

Issue 2601633002: Use a common buffer across all instances for stack-copy. (Closed)
Patch Set: change from shared static buffer to caller-owned 'common' buffer Created 3 years, 11 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/profiler/native_stack_sampler.h" 5 #include "base/profiler/native_stack_sampler.h"
6 6
7 #include <objbase.h> 7 #include <objbase.h>
8 #include <windows.h> 8 #include <windows.h>
9 #include <stddef.h> 9 #include <stddef.h>
10 #include <winternl.h> 10 #include <winternl.h>
11 11
12 #include <cstdlib> 12 #include <cstdlib>
13 #include <map> 13 #include <map>
14 #include <memory> 14 #include <memory>
15 #include <utility> 15 #include <utility>
16 #include <vector> 16 #include <vector>
17 17
18 #include "base/atomicops.h"
Mike Wittman 2017/01/24 17:20:57 No longer needed.
bcwhite 2017/02/07 15:16:36 Done.
18 #include "base/lazy_instance.h" 19 #include "base/lazy_instance.h"
19 #include "base/logging.h" 20 #include "base/logging.h"
20 #include "base/macros.h" 21 #include "base/macros.h"
22 #include "base/memory/ptr_util.h"
21 #include "base/profiler/win32_stack_frame_unwinder.h" 23 #include "base/profiler/win32_stack_frame_unwinder.h"
22 #include "base/strings/string_util.h" 24 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h" 25 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h" 26 #include "base/strings/utf_string_conversions.h"
27 #include "base/synchronization/lock.h"
Mike Wittman 2017/01/24 17:20:57 No longer needed.
bcwhite 2017/02/07 15:16:36 Done.
25 #include "base/time/time.h" 28 #include "base/time/time.h"
26 #include "base/win/pe_image.h" 29 #include "base/win/pe_image.h"
27 #include "base/win/scoped_handle.h" 30 #include "base/win/scoped_handle.h"
28 31
29 namespace base { 32 namespace base {
30 33
31 // Stack recording functions -------------------------------------------------- 34 // Stack recording functions --------------------------------------------------
32 35
33 namespace { 36 namespace {
34 37
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 // NativeStackSamplerWin ------------------------------------------------------ 388 // NativeStackSamplerWin ------------------------------------------------------
386 389
387 class NativeStackSamplerWin : public NativeStackSampler { 390 class NativeStackSamplerWin : public NativeStackSampler {
388 public: 391 public:
389 NativeStackSamplerWin(win::ScopedHandle thread_handle, 392 NativeStackSamplerWin(win::ScopedHandle thread_handle,
390 AnnotateCallback annotator, 393 AnnotateCallback annotator,
391 NativeStackSamplerTestDelegate* test_delegate); 394 NativeStackSamplerTestDelegate* test_delegate);
392 ~NativeStackSamplerWin() override; 395 ~NativeStackSamplerWin() override;
393 396
394 // StackSamplingProfiler::NativeStackSampler: 397 // StackSamplingProfiler::NativeStackSampler:
398 std::unique_ptr<Common> CreateCommon() override;
395 void ProfileRecordingStarting( 399 void ProfileRecordingStarting(
400 Common* common,
396 std::vector<StackSamplingProfiler::Module>* modules) override; 401 std::vector<StackSamplingProfiler::Module>* modules) override;
397 void RecordStackSample(StackSamplingProfiler::Sample* sample) override; 402 void RecordStackSample(Common* common,
398 void ProfileRecordingStopped() override; 403 StackSamplingProfiler::Sample* sample) override;
404 void ProfileRecordingStopped(Common* common) override;
399 405
400 private: 406 private:
401 enum { 407 enum {
402 // Intended to hold the largest stack used by Chrome. The default Win32 408 // Intended to hold the largest stack used by Chrome. The default Win32
403 // reserved stack size is 1 MB and Chrome Windows threads currently always 409 // reserved stack size is 1 MB and Chrome Windows threads currently always
404 // use the default, but this allows for expansion if it occurs. The size 410 // use the default, but this allows for expansion if it occurs. The size
405 // beyond the actual stack size consists of unallocated virtual memory pages 411 // beyond the actual stack size consists of unallocated virtual memory pages
406 // so carries little cost (just a bit of wasted address space). 412 // so carries little cost (just a bit of wasted address space).
407 kStackCopyBufferSize = 2 * 1024 * 1024 413 kStackCopyBufferSize = 2 * 1024 * 1024
408 }; 414 };
409 415
416 class WinCommon : public Common {
Mike Wittman 2017/01/24 17:20:57 WinCommon => CommonWin (or actually StackBufferWin
bcwhite 2017/02/07 15:16:35 Done.
417 public:
418 WinCommon() {}
419 ~WinCommon() override {}
420
421 // Buffer to use for copies of the stack.
422 unsigned char stack_copy_buffer_[kStackCopyBufferSize];
423 };
424
410 // Attempts to query the module filename, base address, and id for 425 // Attempts to query the module filename, base address, and id for
411 // |module_handle|, and store them in |module|. Returns true if it succeeded. 426 // |module_handle|, and store them in |module|. Returns true if it succeeded.
412 static bool GetModuleForHandle(HMODULE module_handle, 427 static bool GetModuleForHandle(HMODULE module_handle,
413 StackSamplingProfiler::Module* module); 428 StackSamplingProfiler::Module* module);
414 429
415 // Gets the index for the Module corresponding to |module_handle| in 430 // Gets the index for the Module corresponding to |module_handle| in
416 // |modules|, adding it if it's not already present. Returns 431 // |modules|, adding it if it's not already present. Returns
417 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be 432 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be
418 // determined for |module|. 433 // determined for |module|.
419 size_t GetModuleIndex(HMODULE module_handle, 434 size_t GetModuleIndex(HMODULE module_handle,
420 std::vector<StackSamplingProfiler::Module>* modules); 435 std::vector<StackSamplingProfiler::Module>* modules);
421 436
422 // Copies the information represented by |stack| into |sample| and |modules|. 437 // Copies the information represented by |stack| into |sample| and |modules|.
423 void CopyToSample(const std::vector<RecordedFrame>& stack, 438 void CopyToSample(const std::vector<RecordedFrame>& stack,
424 StackSamplingProfiler::Sample* sample, 439 StackSamplingProfiler::Sample* sample,
425 std::vector<StackSamplingProfiler::Module>* modules); 440 std::vector<StackSamplingProfiler::Module>* modules);
426 441
427 win::ScopedHandle thread_handle_; 442 win::ScopedHandle thread_handle_;
428 443
429 const AnnotateCallback annotator_; 444 const AnnotateCallback annotator_;
430 445
431 NativeStackSamplerTestDelegate* const test_delegate_; 446 NativeStackSamplerTestDelegate* const test_delegate_;
432 447
433 // The stack base address corresponding to |thread_handle_|. 448 // The stack base address corresponding to |thread_handle_|.
434 const void* const thread_stack_base_address_; 449 const void* const thread_stack_base_address_;
435 450
436 // Buffer to use for copies of the stack. We use the same buffer for all the
437 // samples to avoid the overhead of multiple allocations and frees.
438 const std::unique_ptr<unsigned char[]> stack_copy_buffer_;
439
440 // Weak. Points to the modules associated with the profile being recorded 451 // Weak. Points to the modules associated with the profile being recorded
441 // between ProfileRecordingStarting() and ProfileRecordingStopped(). 452 // between ProfileRecordingStarting() and ProfileRecordingStopped().
442 std::vector<StackSamplingProfiler::Module>* current_modules_; 453 std::vector<StackSamplingProfiler::Module>* current_modules_;
443 454
444 // Maps a module handle to the corresponding Module's index within 455 // Maps a module handle to the corresponding Module's index within
445 // current_modules_. 456 // current_modules_.
446 std::map<HMODULE, size_t> profile_module_index_; 457 std::map<HMODULE, size_t> profile_module_index_;
447 458
459 // This "in use" flag is used to validate the assumption that there are no
460 // concurrent stack sampling requests regardless of how many instances of
461 // this class are currently active.
462 static subtle::AtomicWord stack_copy_buffer_in_use_;
Mike Wittman 2017/01/24 17:20:57 No longer needed.
bcwhite 2017/02/07 15:16:35 Done.
463
448 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin); 464 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin);
449 }; 465 };
450 466
451 NativeStackSamplerWin::NativeStackSamplerWin( 467 NativeStackSamplerWin::NativeStackSamplerWin(
452 win::ScopedHandle thread_handle, 468 win::ScopedHandle thread_handle,
453 AnnotateCallback annotator, 469 AnnotateCallback annotator,
454 NativeStackSamplerTestDelegate* test_delegate) 470 NativeStackSamplerTestDelegate* test_delegate)
455 : thread_handle_(thread_handle.Take()), 471 : thread_handle_(thread_handle.Take()),
456 annotator_(annotator), 472 annotator_(annotator),
457 test_delegate_(test_delegate), 473 test_delegate_(test_delegate),
458 thread_stack_base_address_( 474 thread_stack_base_address_(
459 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase), 475 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase) {
460 stack_copy_buffer_(new unsigned char[kStackCopyBufferSize]) {
461 DCHECK(annotator_); 476 DCHECK(annotator_);
462 } 477 }
463 478
464 NativeStackSamplerWin::~NativeStackSamplerWin() { 479 NativeStackSamplerWin::~NativeStackSamplerWin() {
465 } 480 }
466 481
482 std::unique_ptr<NativeStackSampler::Common>
483 NativeStackSamplerWin::CreateCommon() {
484 return MakeUnique<WinCommon>();
485 }
486
467 void NativeStackSamplerWin::ProfileRecordingStarting( 487 void NativeStackSamplerWin::ProfileRecordingStarting(
488 Common* common,
468 std::vector<StackSamplingProfiler::Module>* modules) { 489 std::vector<StackSamplingProfiler::Module>* modules) {
469 current_modules_ = modules; 490 current_modules_ = modules;
470 profile_module_index_.clear(); 491 profile_module_index_.clear();
471 } 492 }
472 493
473 void NativeStackSamplerWin::RecordStackSample( 494 void NativeStackSamplerWin::RecordStackSample(
495 Common* common,
474 StackSamplingProfiler::Sample* sample) { 496 StackSamplingProfiler::Sample* sample) {
497 DCHECK(common);
475 DCHECK(current_modules_); 498 DCHECK(current_modules_);
476 499
477 if (!stack_copy_buffer_)
478 return;
479
480 std::vector<RecordedFrame> stack; 500 std::vector<RecordedFrame> stack;
481 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_, 501 SuspendThreadAndRecordStack(
482 stack_copy_buffer_.get(), kStackCopyBufferSize, 502 thread_handle_.Get(), thread_stack_base_address_,
483 &stack, annotator_, sample, test_delegate_); 503 reinterpret_cast<WinCommon*>(common)->stack_copy_buffer_,
Mike Wittman 2017/01/24 17:20:57 static_cast for downcast
bcwhite 2017/02/07 15:16:36 Done.
504 kStackCopyBufferSize, &stack, annotator_, sample, test_delegate_);
484 CopyToSample(stack, sample, current_modules_); 505 CopyToSample(stack, sample, current_modules_);
485 } 506 }
486 507
487 void NativeStackSamplerWin::ProfileRecordingStopped() { 508 void NativeStackSamplerWin::ProfileRecordingStopped(Common* common) {
488 current_modules_ = nullptr; 509 current_modules_ = nullptr;
489 } 510 }
490 511
491 // static 512 // static
492 bool NativeStackSamplerWin::GetModuleForHandle( 513 bool NativeStackSamplerWin::GetModuleForHandle(
493 HMODULE module_handle, 514 HMODULE module_handle,
494 StackSamplingProfiler::Module* module) { 515 StackSamplingProfiler::Module* module) {
495 wchar_t module_name[MAX_PATH]; 516 wchar_t module_name[MAX_PATH];
496 DWORD result_length = 517 DWORD result_length =
497 GetModuleFileName(module_handle, module_name, arraysize(module_name)); 518 GetModuleFileName(module_handle, module_name, arraysize(module_name));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 578
558 if (thread_handle) { 579 if (thread_handle) {
559 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin( 580 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin(
560 win::ScopedHandle(thread_handle), annotator, test_delegate)); 581 win::ScopedHandle(thread_handle), annotator, test_delegate));
561 } 582 }
562 #endif 583 #endif
563 return std::unique_ptr<NativeStackSampler>(); 584 return std::unique_ptr<NativeStackSampler>();
564 } 585 }
565 586
566 } // namespace base 587 } // namespace base
OLDNEW
« base/profiler/native_stack_sampler.h ('K') | « base/profiler/native_stack_sampler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698