Gau*_*ham 27 c linux context-switch
我们可以编写ac程序来找出在Linux中进行上下文切换所花费的时间吗?如果你有代码,请你分享代码吗?谢谢
Tro*_*nic 24
分析切换时间非常困难,但内核延迟分析工具以及oprofile(可以分析内核本身)将帮助您.
为了对交互式应用程序性能进行基准测试,我编写了一个名为latencybench的小工具来测量意外的延迟峰值:
// Compile with g++ latencybench.cc -o latencybench -lboost_thread-mt
// Should also work on MSVC and other platforms supported by Boost.
#include <boost/format.hpp>
#include <boost/thread/thread.hpp>
#include <boost/date_time.hpp>
#include <algorithm>
#include <cstdlib>
#include <csignal>
volatile bool m_quit = false;
extern "C" void sighandler(int) {
m_quit = true;
}
std::string num(unsigned val) {
if (val == 1) return "one occurrence";
return boost::lexical_cast<std::string>(val) + " occurrences";
}
int main(int argc, char** argv) {
using namespace boost::posix_time;
std::signal(SIGINT, sighandler);
std::signal(SIGTERM, sighandler);
time_duration duration = milliseconds(10);
if (argc > 1) {
try {
if (argc != 2) throw 1;
unsigned ms = boost::lexical_cast<unsigned>(argv[1]);
if (ms > 1000) throw 2;
duration = milliseconds(ms);
} catch (...) {
std::cerr << "Usage: " << argv[0] << " milliseconds" << std::endl;
return EXIT_FAILURE;
}
}
typedef std::map<long, unsigned> Durations;
Durations durations;
unsigned samples = 0, wrongsamples = 0;
unsigned max = 0;
long last = -1;
std::cout << "Measuring actual sleep delays when requesting " << duration.total_milliseconds() << " ms: (Ctrl+C when done)" << std::endl;
ptime begin = boost::get_system_time();
while (!m_quit) {
ptime start = boost::get_system_time();
boost::this_thread::sleep(start + duration);
long actual = (boost::get_system_time() - start).total_milliseconds();
++samples;
unsigned num = ++durations[actual];
if (actual != last) {
std::cout << "\r " << actual << " ms " << std::flush;
last = actual;
}
if (actual != duration.total_milliseconds()) {
++wrongsamples;
if (num > max) max = num;
std::cout << "spike at " << start - begin << std::endl;
last = -1;
}
}
if (samples == 0) return 0;
std::cout << "\rTotal measurement duration: " << boost::get_system_time() - begin << "\n";
std::cout << "Number of samples collected: " << samples << "\n";
std::cout << "Incorrect delay count: " << wrongsamples << boost::format(" (%.2f %%)") % (100.0 * wrongsamples / samples) << "\n\n";
std::cout << "Histogram of actual delays:\n\n";
unsigned correctsamples = samples - wrongsamples;
const unsigned line = 60;
double scale = 1.0;
char ch = '+';
if (max > line) {
scale = double(line) / max;
ch = '*';
}
double correctscale = 1.0;
if (correctsamples > line) correctscale = double(line) / correctsamples;
for (Durations::const_iterator it = durations.begin(); it != durations.end(); ++it) {
std::string bar;
if (it->first == duration.total_milliseconds()) bar = std::string(correctscale * it->second, '>');
else bar = std::string(scale * it->second, ch);
std::cout << boost::format("%5d ms | %s %d") % it->first % bar % it->second << std::endl;
}
std::cout << "\n";
std::string indent(30, ' ');
std::cout << indent << "+-- Legend ----------------------------------\n";
std::cout << indent << "| > " << num(1.0 / correctscale) << " (of " << duration.total_milliseconds() << " ms delay)\n";
if (wrongsamples > 0) std::cout << indent << "| " << ch << " " << num(1.0 / scale) << " (of any other delay)\n";
}
Run Code Online (Sandbox Code Playgroud)
关于Ubuntu 2.6.32-14-通用内核的结果.在测量时,我正在使用四个内核编译C++代码并同时使用OpenGL图形玩游戏(以使其更有趣):
Total measurement duration: 00:01:45.191465
Number of samples collected: 10383
Incorrect delay count: 196 (1.89 %)
Histogram of actual delays:
10 ms | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 10187
11 ms | *************************************************** 70
12 ms | ************************************************************ 82
13 ms | ********* 13
14 ms | ********* 13
15 ms | ** 4
17 ms | *** 5
18 ms | * 2
19 ms | **** 6
20 ms | 1
+-- Legend ----------------------------------
| > 169 occurrences (of 10 ms delay)
| * one occurrence (of any other delay)
Run Code Online (Sandbox Code Playgroud)
使用rt-patched内核,我得到了更好的结果,只有10-12毫秒.
打印输出中的图例似乎正在出现舍入错误或某些东西(并且粘贴的源代码不是完全相同的版本).我从来没有真正完成这个应用程序的发布......
如果您具有超级用户权限,则可以运行带有上下文切换探测点的SystemTap程序,并在每个程序中打印当前时间:
probe scheduler.ctxswitch {
printf("Switch from %d to %d at %d\n", prev_pid, next_pid, gettimeofday_us())
}
Run Code Online (Sandbox Code Playgroud)
我不确定输出数据有多可靠,但这是一种快速简便的方法来获取一些数字.
简短的回答 - 不。长答案如下。
上下文切换大致发生在以下情况:
切换本身是单向的,因此我们在用户空间中可以做的最好的事情(我假设这就是您所要求的)是测量某种 RTT,从我们的进程到另一个进程并返回。另一个进程也需要时间来完成其工作。我们当然可以让两个或多个进程对此进行合作,但问题是内核并不能保证接下来会选择我们的进程之一。使用 RT 调度程序可能可以预见地切换到给定进程,但我在这里没有建议,欢迎提出建议。
小智 5
您如何看待,用秒或毫秒甚至微秒测量上下文切换.所有发生的都不到纳秒.如果你想花费大量的时间进行可以测量的上下文切换,那么...尝试一些写在Assembly上的实模式内核类型代码,你可能会看到一些东西.
| 归档时间: |
|
| 查看次数: |
34075 次 |
| 最近记录: |