我做了一个符合W3规范的简单实现.在这里,我只是持有不同的合法字符集(合法的起始字符不同于以下字符)并使用string.Contains.但是这些合法字符组合令人惊讶地(对我来说)很大,只是在候选字符串的时候检查一个字符变得有点贵.
目前这不是一个问题,因为我需要每次执行一次(几秒钟,几分钟甚至几小时)验证一些字符串一次(花费几毫秒),但我很想知道其他人会建议什么.
这是我直截了当的实现:
using System;
using System.Text;
using Project.Common; // Guard
namespace Project.Common.XmlUtilities
{
static public class XmlUtil
{
static public bool IsLegalElementName(string localName)
{
Guard.ArgumentNotNull(localName, "localName");
if (localName == "")
return false;
if (NameStartChars.IndexOf(localName[0]) == -1)
return false;
for (int i = 1; i < localName.Length; i++)
if (NameChars.IndexOf(localName[i]) == -1)
return false;
return true;
}
// See W3 spec at http://www.w3.org/TR/REC-xml/#NT-NameStartChar.
static public readonly string NameStartChars = AZ.ToLower() + AZ + ":_" + GetStringFromCharRanges(0xC0, 0xD6, 0xD8, 0xF6, 0xF8, …Run Code Online (Sandbox Code Playgroud) 有什么方法可以通过 Linux 中的 perf 工具捕获 L3 缓存命中和未命中。根据 的输出perf list cache,支持 L1 和 LLC 缓存。根据perf源码中perf_evsel__hw_cache数组的定义:
const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
[PERF_EVSEL__MAX_ALIASES] = {
{ "L1-dcache", "l1-d", "l1d", "L1-data", },
{ "L1-icache", "l1-i", "l1i", "L1-instruction", },
{ "LLC", "L2", },
{ "dTLB", "d-tlb", "Data-TLB", },
{ "iTLB", "i-tlb", "Instruction-TLB", },
{ "branch", "branches", "bpu", "btb", "bpc", },
{ "node", },
};
Run Code Online (Sandbox Code Playgroud)
LLC 是 L2-cache 的别名。我的问题是如何通过 Linux 中的 perf 工具捕获 L3 缓存命中和未命中。提前致谢!
我正在尝试使用符号编译的Linux perf调试webkit构建.
"perf report -g"的输出具有半人类可读符号和另一半字母数字值.
例如:
_ZN7WebCore12RenderObject18setAnimatableStyleEN3WTF10PassRefPtrINS_11RenderStyleEEE
|
|--91.30%-- _ZN7WebCore4Node14setRenderStyleEN3WTF10PassRefPtrINS_11RenderStyleEEE
| _ZN7WebCore7Element11recalcStyleENS_4Node11StyleChangeE
| _ZN7WebCore7Element11recalcStyleENS_4Node11StyleChangeE
| _ZN7WebCore7Element11recalcStyleENS_4Node11StyleChangeE
Run Code Online (Sandbox Code Playgroud)
这里发生了什么事?
什么是_ZN7?
我的预感是这与C++有关,也许我需要编译更多的选项来使符号正确地表示为perf.
这里的任何指针将不胜感激.我在文档中的任何地方都找不到任何相关内容.
我试图了解 perf 记录的缓存未命中。我有一个最小的程序:
int main(void)
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我编译这个:
gcc -std=c99 -W -Wall -Werror -O3 -S -o test.S test.c
Run Code Online (Sandbox Code Playgroud)
我得到了一个预期的小程序:
.file "test.c"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
xorl %eax, %eax
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 4.7.2-5) 4.7.2"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
只有两条指令, xorland ret,程序的大小应该小于一个缓存行,所以我希望如果我运行perf -e "cache-misses:u" ./test我应该只看到一个缓存未命中。但是,我看到的是 2 到 ~400。同样,perf -e "cache-misses" ./test结果是 ~700 到 ~2500。
这只是一个估计计数的情况,还是缓存未命中发生的方式使对它们的推理近似?例如,如果我生成并读取内存中的一个整数数组,我是否可以推理预取(顺序访问应该允许完美预取)或者还有其他东西在起作用吗?
我正在学习如何使用 perf. 我使用了性能统计数据,然后使用了性能报告。所以我注意到 memcpy 中的缓存未命中。是否可以进行某种回溯来找出这是哪个 memcpy?仅仅知道它来自 memcpy 是毫无用处的。
我正在 ARM 板上的旧版本内核上运行 perf record。内核版本为3.18.21-rt19
板上的 perf 版本同样是 perf 版本 3.18.21。
虽然我可以在此性能上记录和使用报告功能,但此版本的报告 TUI 非常糟糕/不存在。它不是可扩展部分(在图形模式下),而是显示为一个巨大的可滚动函数列表,非常难以使用。另外,由于某种原因,我的 C++ 函数名称没有被破坏,因此很难阅读它。
是否有可能以某种方式:
将在此较旧 ARM 内核上创建的 perf.data 导出到运行较新内核和较新版本 perf 的 x86 计算机,并使用该计算机上的 perf 报告。当我尝试这样做时(我在运行 perf 版本 4.4.13 的内核 4.4.0-31-generic 上运行),我丢失了所有符号,即使在 ARM 计算机上运行 perf 报告显示符号很好(C++ 名称仍然被破坏) )。我不确定这是否只是因为这些内核版本之间的 perf.data 格式发生了变化,或者 x86 版本是否完全无法读取 ARM 机器生成的数据。
为我的旧内核构建一个更新的性能版本(至少是前端),它可以进行整理并公开更新的更好的 TUI。
更改 ARM 板上的内核版本对我来说不是一个选择。
我试图在主机上使用 Intel-PT,而我在来宾计算机中运行通用软件程序。所以我期望在主机中运行的 Intel-PT 将记录所有相关的数据包(如 PIP、FUP、TSC 等)以及所有基于 VM 的数据包,如 VMCS。
我使用以下命令 -
./perf kvm --host --guest --guestkallsyms=guest-kallsyms --guestmodules=guest-modules record -e intel_pt//
guest-kallsyms 和 guest-modules 是我从来宾复制到主机上的 kallsyms 和模块文件。
然后我将启动我的虚拟机。我将在客户机上运行一个程序。程序执行完成后,我将在主机中按Ctrl + C (SIGINT) 停止录制。
我看到,一旦我尝试使用 perf 报告读取使用以下命令生成的文件 -
./perf kvm report -i perf.data.kvm
它返回“未找到样本”。这意味着 Intel-PT 未能记录任何样本。
注意:MSR_IA32_VMX_MISC对于我的处理器,我发现 MSR 中值的第 14 位是 0。根据 Intel 文档,对于要在 VMX 操作中使用的 Intel-PT,该位应为 1。这是否会以任何方式影响 Intel-PT 不记录任何样本的原因?
INTEL-PT 即使在 VM 开启时也能工作吗?还是我记录数据的方法不对?
编辑:我使用的是Linux 内核 4.11.3,具有 Ubuntu 17.04和支持 Intel-PT 的 Broadwell CPU。
我想在我的代码中为每个函数调用动态指令计数,以便我可以将该计数器视为:
name of function | instructions
foo() | 3533
bar() | 1234
Run Code Online (Sandbox Code Playgroud)
以下是子问题:
perf吗?perf我应该使用什么样的标志来获取(至少)这些信息?我编写了一个简单的代码进行测试prof。
double bar_compute (double d) {
double t = std::abs(d);
t += std::sqrt(d);
t += std::cos(d);
return t;
}
// Do some computation n times
double foo_compute(unsigned n) {
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<double> dist(0.0, 1.0);
double total = 0;
for (int i=0; i<n; i++) {
double d = dist(mt);
total += bar_compute(d);
}
return total;
}
Run Code Online (Sandbox Code Playgroud)
当我运行prof并查看输出时,它是
56.14% runcode libm-2.23.so [.] __cos_avx
27.34% runcode runcode [.] _Z11foo_computej
13.92% runcode runcode [.] _Z11bar_computed
0.86% runcode libm-2.23.so …Run Code Online (Sandbox Code Playgroud) 我有一个执行指针追踪的程序,我正在尝试尽可能地优化指针追踪循环。我注意到perf record检测到函数中大约 20% 的执行时间myFunction()用于执行跳转指令(用于在读取特定值后退出循环)。
需要注意的一些事项:
__builtin_expect以避免分支预测错误的成本没有显着影响perf record 有以下输出:
Samples: 153K of event 'cycles', 10000 Hz, Event count (approx.): 35559166926
myFunction /tmp/foobar [Percent: local hits]
Percent? endbr64
...
80.09 ?20: mov (%rdx,%rbx,1),%ebx
0.07 ? add $0x1,%rax
? cmp $0xffffffff,%ebx
19.84 ? ? jne 20
...
Run Code Online (Sandbox Code Playgroud)
我希望在这个循环中花费的大部分周期都用于从内存中读取值,这是由 perf 确认的。我还希望剩余的周期在执行循环中剩余的指令时会有些均匀地花费。相反, perf 报告的是剩余周期的很大一部分用于执行跳转。
我怀疑通过了解用于执行这些指令的微操作,我可以更好地了解这些成本,但我对从哪里开始有点迷茫。
perf ×10
linux ×6
c++ ×2
caching ×2
algorithm ×1
assembly ×1
avx ×1
c# ×1
cpu ×1
glibc ×1
instructions ×1
kvm ×1
linux-kernel ×1
performance ×1
pointers ×1
trace ×1
trigonometry ×1
x86 ×1
xml ×1