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

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: addressed review comments by wittman Created 3 years, 7 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 | « base/profiler/native_stack_sampler_posix.cc ('k') | base/profiler/stack_sampling_profiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/lazy_instance.h" 18 #include "base/lazy_instance.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/macros.h" 20 #include "base/macros.h"
21 #include "base/memory/ptr_util.h"
21 #include "base/profiler/win32_stack_frame_unwinder.h" 22 #include "base/profiler/win32_stack_frame_unwinder.h"
22 #include "base/strings/string_util.h" 23 #include "base/strings/string_util.h"
23 #include "base/strings/stringprintf.h" 24 #include "base/strings/stringprintf.h"
24 #include "base/strings/utf_string_conversions.h" 25 #include "base/strings/utf_string_conversions.h"
25 #include "base/time/time.h" 26 #include "base/time/time.h"
26 #include "base/win/pe_image.h" 27 #include "base/win/pe_image.h"
27 #include "base/win/scoped_handle.h" 28 #include "base/win/scoped_handle.h"
28 29
29 namespace base { 30 namespace base {
30 31
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 class NativeStackSamplerWin : public NativeStackSampler { 388 class NativeStackSamplerWin : public NativeStackSampler {
388 public: 389 public:
389 NativeStackSamplerWin(win::ScopedHandle thread_handle, 390 NativeStackSamplerWin(win::ScopedHandle thread_handle,
390 AnnotateCallback annotator, 391 AnnotateCallback annotator,
391 NativeStackSamplerTestDelegate* test_delegate); 392 NativeStackSamplerTestDelegate* test_delegate);
392 ~NativeStackSamplerWin() override; 393 ~NativeStackSamplerWin() override;
393 394
394 // StackSamplingProfiler::NativeStackSampler: 395 // StackSamplingProfiler::NativeStackSampler:
395 void ProfileRecordingStarting( 396 void ProfileRecordingStarting(
396 std::vector<StackSamplingProfiler::Module>* modules) override; 397 std::vector<StackSamplingProfiler::Module>* modules) override;
397 void RecordStackSample(StackSamplingProfiler::Sample* sample) override; 398 void RecordStackSample(StackBuffer* stack_buffer,
398 void ProfileRecordingStopped() override; 399 StackSamplingProfiler::Sample* sample) override;
400 void ProfileRecordingStopped(StackBuffer* stack_buffer) override;
399 401
400 private: 402 private:
401 // Intended to hold the largest stack used by Chrome. The default Win32
402 // reserved stack size is 1 MB and Chrome Windows threads currently always
403 // use the default, but this allows for expansion if it occurs. The size
404 // beyond the actual stack size consists of unallocated virtual memory pages
405 // so carries little cost (just a bit of wasted address space).
406 static constexpr size_t kStackCopyBufferSize = 2 * 1024 * 1024;
407
408 // Attempts to query the module filename, base address, and id for 403 // Attempts to query the module filename, base address, and id for
409 // |module_handle|, and store them in |module|. Returns true if it succeeded. 404 // |module_handle|, and store them in |module|. Returns true if it succeeded.
410 static bool GetModuleForHandle(HMODULE module_handle, 405 static bool GetModuleForHandle(HMODULE module_handle,
411 StackSamplingProfiler::Module* module); 406 StackSamplingProfiler::Module* module);
412 407
413 // Gets the index for the Module corresponding to |module_handle| in 408 // Gets the index for the Module corresponding to |module_handle| in
414 // |modules|, adding it if it's not already present. Returns 409 // |modules|, adding it if it's not already present. Returns
415 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be 410 // StackSamplingProfiler::Frame::kUnknownModuleIndex if no Module can be
416 // determined for |module|. 411 // determined for |module|.
417 size_t GetModuleIndex(HMODULE module_handle, 412 size_t GetModuleIndex(HMODULE module_handle,
418 std::vector<StackSamplingProfiler::Module>* modules); 413 std::vector<StackSamplingProfiler::Module>* modules);
419 414
420 // Copies the information represented by |stack| into |sample| and |modules|. 415 // Copies the information represented by |stack| into |sample| and |modules|.
421 void CopyToSample(const std::vector<RecordedFrame>& stack, 416 void CopyToSample(const std::vector<RecordedFrame>& stack,
422 StackSamplingProfiler::Sample* sample, 417 StackSamplingProfiler::Sample* sample,
423 std::vector<StackSamplingProfiler::Module>* modules); 418 std::vector<StackSamplingProfiler::Module>* modules);
424 419
425 win::ScopedHandle thread_handle_; 420 win::ScopedHandle thread_handle_;
426 421
427 const AnnotateCallback annotator_; 422 const AnnotateCallback annotator_;
428 423
429 NativeStackSamplerTestDelegate* const test_delegate_; 424 NativeStackSamplerTestDelegate* const test_delegate_;
430 425
431 // The stack base address corresponding to |thread_handle_|. 426 // The stack base address corresponding to |thread_handle_|.
432 const void* const thread_stack_base_address_; 427 const void* const thread_stack_base_address_;
433 428
434 // Buffer to use for copies of the stack. We use the same buffer for all the
435 // samples to avoid the overhead of multiple allocations and frees.
436 const std::unique_ptr<unsigned char[]> stack_copy_buffer_;
437
438 // Weak. Points to the modules associated with the profile being recorded 429 // Weak. Points to the modules associated with the profile being recorded
439 // between ProfileRecordingStarting() and ProfileRecordingStopped(). 430 // between ProfileRecordingStarting() and ProfileRecordingStopped().
440 std::vector<StackSamplingProfiler::Module>* current_modules_; 431 std::vector<StackSamplingProfiler::Module>* current_modules_;
441 432
442 // Maps a module handle to the corresponding Module's index within 433 // Maps a module handle to the corresponding Module's index within
443 // current_modules_. 434 // current_modules_.
444 std::map<HMODULE, size_t> profile_module_index_; 435 std::map<HMODULE, size_t> profile_module_index_;
445 436
446 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin); 437 DISALLOW_COPY_AND_ASSIGN(NativeStackSamplerWin);
447 }; 438 };
448 439
449 NativeStackSamplerWin::NativeStackSamplerWin( 440 NativeStackSamplerWin::NativeStackSamplerWin(
450 win::ScopedHandle thread_handle, 441 win::ScopedHandle thread_handle,
451 AnnotateCallback annotator, 442 AnnotateCallback annotator,
452 NativeStackSamplerTestDelegate* test_delegate) 443 NativeStackSamplerTestDelegate* test_delegate)
453 : thread_handle_(thread_handle.Take()), 444 : thread_handle_(thread_handle.Take()),
454 annotator_(annotator), 445 annotator_(annotator),
455 test_delegate_(test_delegate), 446 test_delegate_(test_delegate),
456 thread_stack_base_address_( 447 thread_stack_base_address_(
457 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase), 448 GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase) {
458 stack_copy_buffer_(new unsigned char[kStackCopyBufferSize]) {
459 DCHECK(annotator_); 449 DCHECK(annotator_);
460 } 450 }
461 451
462 NativeStackSamplerWin::~NativeStackSamplerWin() { 452 NativeStackSamplerWin::~NativeStackSamplerWin() {
463 } 453 }
464 454
465 void NativeStackSamplerWin::ProfileRecordingStarting( 455 void NativeStackSamplerWin::ProfileRecordingStarting(
466 std::vector<StackSamplingProfiler::Module>* modules) { 456 std::vector<StackSamplingProfiler::Module>* modules) {
467 current_modules_ = modules; 457 current_modules_ = modules;
468 profile_module_index_.clear(); 458 profile_module_index_.clear();
469 } 459 }
470 460
471 void NativeStackSamplerWin::RecordStackSample( 461 void NativeStackSamplerWin::RecordStackSample(
462 StackBuffer* stack_buffer,
472 StackSamplingProfiler::Sample* sample) { 463 StackSamplingProfiler::Sample* sample) {
464 DCHECK(stack_buffer);
473 DCHECK(current_modules_); 465 DCHECK(current_modules_);
474 466
475 std::vector<RecordedFrame> stack; 467 std::vector<RecordedFrame> stack;
476 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_, 468 SuspendThreadAndRecordStack(thread_handle_.Get(), thread_stack_base_address_,
477 stack_copy_buffer_.get(), kStackCopyBufferSize, 469 stack_buffer->buffer(), stack_buffer->size(),
478 &stack, annotator_, sample, test_delegate_); 470 &stack, annotator_, sample, test_delegate_);
479 CopyToSample(stack, sample, current_modules_); 471 CopyToSample(stack, sample, current_modules_);
480 } 472 }
481 473
482 void NativeStackSamplerWin::ProfileRecordingStopped() { 474 void NativeStackSamplerWin::ProfileRecordingStopped(StackBuffer* stack_buffer) {
483 current_modules_ = nullptr; 475 current_modules_ = nullptr;
484 } 476 }
485 477
486 // static 478 // static
487 bool NativeStackSamplerWin::GetModuleForHandle( 479 bool NativeStackSamplerWin::GetModuleForHandle(
488 HMODULE module_handle, 480 HMODULE module_handle,
489 StackSamplingProfiler::Module* module) { 481 StackSamplingProfiler::Module* module) {
490 wchar_t module_name[MAX_PATH]; 482 wchar_t module_name[MAX_PATH];
491 DWORD result_length = 483 DWORD result_length =
492 GetModuleFileName(module_handle, module_name, arraysize(module_name)); 484 GetModuleFileName(module_handle, module_name, arraysize(module_name));
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 thread_id); 543 thread_id);
552 544
553 if (thread_handle) { 545 if (thread_handle) {
554 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin( 546 return std::unique_ptr<NativeStackSampler>(new NativeStackSamplerWin(
555 win::ScopedHandle(thread_handle), annotator, test_delegate)); 547 win::ScopedHandle(thread_handle), annotator, test_delegate));
556 } 548 }
557 #endif 549 #endif
558 return std::unique_ptr<NativeStackSampler>(); 550 return std::unique_ptr<NativeStackSampler>();
559 } 551 }
560 552
553 size_t NativeStackSampler::GetStackBufferSize() {
554 // The default Win32 reserved stack size is 1 MB and Chrome Windows threads
555 // currently always use the default, but this allows for expansion if it
556 // occurs. The size beyond the actual stack size consists of unallocated
557 // virtual memory pages so carries little cost (just a bit of wasted address
558 // space).
559 return 2 << 20; // 2 MiB
560 }
561
561 } // namespace base 562 } // namespace base
OLDNEW
« no previous file with comments | « base/profiler/native_stack_sampler_posix.cc ('k') | base/profiler/stack_sampling_profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698