
This is a partial revert of this change https://chromium-review.googlesource.com/c/chromium/src/+/2157967/30/content/common/profiling_utils.cc#b46 because using too many profiling data files ends up using way too much disk space on the profiling bots (which can't easily be upgraded) and this is blocking us from deploying them. This shouldn't be an issue in practice, Yuke pointed me to https://reviews.llvm.org/rG6694b2b36bdd3dbb3b047315411cb38432d19d02#change-0QKaaw3pmGjk which ensure that the current approach will automatically merge the profiling data when multiple processes try to write to the same profiling file (as we're setting the merge bit to 1 when calling __llvm_profile_set_file_object) Bug: 1059335 Change-Id: I736772604a3cf7635ede21991c0a035010fea170 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2174906 Commit-Queue: Sébastien Marchand <sebmarchand@chromium.org> Reviewed-by: Nasko Oskov <nasko@chromium.org> Cr-Commit-Position: refs/heads/master@{#764718}
118 lines
3.8 KiB
C++
118 lines
3.8 KiB
C++
// Copyright 2019 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "content/public/common/profiling_utils.h"
|
|
|
|
#include <limits>
|
|
#include <memory>
|
|
|
|
#include "base/base_paths.h"
|
|
#include "base/bind.h"
|
|
#include "base/callback_forward.h"
|
|
#include "base/clang_profiling_buildflags.h"
|
|
#include "base/environment.h"
|
|
#include "base/files/file.h"
|
|
#include "base/files/file_path.h"
|
|
#include "base/files/file_util.h"
|
|
#include "base/guid.h"
|
|
#include "base/logging.h"
|
|
#include "base/path_service.h"
|
|
#include "base/rand_util.h"
|
|
#include "base/run_loop.h"
|
|
#include "base/strings/strcat.h"
|
|
#include "base/strings/string16.h"
|
|
#include "base/strings/string_number_conversions.h"
|
|
#include "base/strings/utf_string_conversions.h"
|
|
#include "base/synchronization/waitable_event.h"
|
|
#include "base/task/task_traits.h"
|
|
#include "base/task/thread_pool.h"
|
|
#include "base/threading/thread_restrictions.h"
|
|
#include "build/build_config.h"
|
|
|
|
namespace content {
|
|
|
|
base::File OpenProfilingFile() {
|
|
base::ScopedAllowBlockingForTesting allows_blocking;
|
|
std::unique_ptr<base::Environment> env(base::Environment::Create());
|
|
std::string prof_template;
|
|
base::FilePath path;
|
|
if (env->GetVar("LLVM_PROFILE_FILE", &prof_template)) {
|
|
#if defined(OS_WIN)
|
|
path = base::FilePath(base::UTF8ToUTF16(prof_template)).DirName();
|
|
#else
|
|
path = base::FilePath(prof_template).DirName();
|
|
#endif
|
|
base::CreateDirectory(path);
|
|
} else {
|
|
base::PathService::Get(base::DIR_CURRENT, &path);
|
|
}
|
|
|
|
// sajjadm@ and liaoyuke@ experimentally determined that a size 4 pool works
|
|
// well for the coverage builder.
|
|
// TODO(https://crbug.com/1059335): Check if this is an appropriate value for
|
|
// the PGO builds.
|
|
int pool_index = base::RandInt(0, 3);
|
|
std::string filename = base::StrCat(
|
|
{"child_pool-", base::NumberToString(pool_index), ".profraw"});
|
|
#if defined(OS_WIN)
|
|
path = path.Append(base::UTF8ToUTF16(filename));
|
|
#else
|
|
path = path.Append(filename);
|
|
#endif
|
|
uint32_t flags = base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
|
|
base::File::FLAG_WRITE;
|
|
|
|
base::File file(path, flags);
|
|
if (!file.IsValid()) {
|
|
LOG(ERROR) << "Opening file: " << path << " failed with "
|
|
<< file.error_details();
|
|
}
|
|
|
|
return file;
|
|
}
|
|
WaitForProcessesToDumpProfilingInfo::WaitForProcessesToDumpProfilingInfo() =
|
|
default;
|
|
WaitForProcessesToDumpProfilingInfo::~WaitForProcessesToDumpProfilingInfo() =
|
|
default;
|
|
|
|
void WaitForProcessesToDumpProfilingInfo::WaitForAll() {
|
|
base::RunLoop nested_run_loop(base::RunLoop::Type::kNestableTasksAllowed);
|
|
|
|
// Some of the waitable events will be signaled on the main thread, use a
|
|
// nested run loop to ensure we're not preventing them from signaling.
|
|
base::ThreadPool::PostTask(
|
|
FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
|
|
base::BindOnce(
|
|
&WaitForProcessesToDumpProfilingInfo::WaitForAllOnThreadPool,
|
|
base::Unretained(this), nested_run_loop.QuitClosure()));
|
|
nested_run_loop.Run();
|
|
}
|
|
|
|
void WaitForProcessesToDumpProfilingInfo::WaitForAllOnThreadPool(
|
|
base::OnceClosure quit_closure) {
|
|
base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_blocking;
|
|
|
|
std::vector<base::WaitableEvent*> events_raw;
|
|
events_raw.reserve(events_.size());
|
|
for (const auto& iter : events_)
|
|
events_raw.push_back(iter.get());
|
|
|
|
// Wait for all the events to be signaled.
|
|
while (events_raw.size()) {
|
|
size_t index =
|
|
base::WaitableEvent::WaitMany(events_raw.data(), events_raw.size());
|
|
events_raw.erase(events_raw.begin() + index);
|
|
}
|
|
|
|
std::move(quit_closure).Run();
|
|
}
|
|
|
|
base::WaitableEvent*
|
|
WaitForProcessesToDumpProfilingInfo::GetNewWaitableEvent() {
|
|
events_.push_back(std::make_unique<base::WaitableEvent>());
|
|
return events_.back().get();
|
|
}
|
|
|
|
} // namespace content
|