- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我是 Spirit 和 Boost 的新手。我正在尝试解析 VRML 文件的一部分,如下所示:
point
[
#coordinates written in meters.
-3.425386e-001 -1.681608e-001 0.000000e+000,
-3.425386e-001 -1.642545e-001 0.000000e+000,
-3.425386e-001 -1.603483e-001 0.000000e+000,
以#开头的注释是可选的。
我写了一个语法,工作正常,但解析过程花费了很长时间。我想优化它运行得更快。我的代码如下所示:
struct Point
{
double a;
double b;
double c;
Point() : a(0.0), b(0.0), c(0.0){}
};
BOOST_FUSION_ADAPT_STRUCT
(
Point,
(double, a)
(double, b)
(double, c)
)
namespace qi = boost::spirit::qi;
namespace repo = boost::spirit::repository;
template <typename Iterator>
struct PointParser :
public qi::grammar<Iterator, std::vector<Point>(), qi::space_type>
{
PointParser() : PointParser::base_type(start, "PointGrammar")
{
singlePoint = qi::double_>>qi::double_>>qi::double_>>*qi::lit(",");
comment = qi::lit("#")>>*(qi::char_("a-zA-Z.") - qi::eol);
prefix = repo::seek[qi::lexeme[qi::skip[qi::lit("point")>>qi::lit("[")>>*comment]]];
start %= prefix>>qi::repeat[singlePoint];
//BOOST_SPIRIT_DEBUG_NODES((prefix)(comment)(singlePoint)(start));
}
qi::rule<Iterator, Point(), qi::space_type> singlePoint;
qi::rule<Iterator, qi::space_type> comment;
qi::rule<Iterator, qi::space_type> prefix;
qi::rule<Iterator, std::vector<Point>(), qi::space_type> start;
};
我打算解析的部分位于输入文本的中间,因此我需要跳过文本部分才能到达它。我使用 repo::seek 实现了它。这是最好的方法吗?
我按以下方式运行解析器:
std::vector<Point> points;
typedef PointParser<std::string::const_iterator> pointParser;
pointParser g2;
auto start = ch::high_resolution_clock::now();
bool r = phrase_parse(Data.begin(), Data.end(), g2, qi::space, points);
auto end = ch::high_resolution_clock::now();
auto duration = ch::duration_cast<boost::chrono::milliseconds>(end - start).count();
要解析输入文本中的大约 80k 个条目,大约需要 2.5 秒,这对我的需求来说相当慢。我的问题是有没有办法以更优化的方式编写解析规则以使其(更快)更快?我如何总体上改进此实现?
我是 Spirit 的新手,所以非常感谢一些解释。
最佳答案
我已将您的语法连接到 Nonius 基准测试中,并生成了约 85k 行的均匀随机输入数据(下载:http://stackoverflow-sehe.s3.amazonaws.com/input.txt,7.4 MB)。
在预先读取文件时,我总是得到 ~36ms 的时间来解析整个文件。
clock resolution: mean is 17.616 ns (40960002 iterations)
benchmarking sample
collecting 100 samples, 1 iterations each, in estimated 3.82932 s
mean: 36.0971 ms, lb 35.9127 ms, ub 36.4456 ms, ci 0.95
std dev: 1252.71 μs, lb 762.716 μs, ub 2.003 ms, ci 0.95
found 6 outliers among 100 samples (6%)
variance is moderately inflated by outliers
代码:见下文。
注意事项:
您似乎对使用 skippers 和 seek 有矛盾。我建议您简化 prefix
:
comment = '#' >> *(qi::char_ - qi::eol);
prefix = repo::seek[
qi::lit("point") >> '[' >> *comment
];
prefix
将使用空格跳过器,并忽略任何匹配的属性(因为规则声明类型)。通过从规则声明中删除船长,使 comment
隐式地成为一个 lexeme:
// implicit lexeme:
qi::rule<Iterator> comment;
Note See Boost spirit skipper issues for more background information.
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/repository/include/qi_seek.hpp>
namespace qi = boost::spirit::qi;
namespace repo = boost::spirit::repository;
struct Point { double a = 0, b = 0, c = 0; };
BOOST_FUSION_ADAPT_STRUCT(Point, a, b, c)
template <typename Iterator>
struct PointParser : public qi::grammar<Iterator, std::vector<Point>(), qi::space_type>
{
PointParser() : PointParser::base_type(start, "PointGrammar")
{
singlePoint = qi::double_ >> qi::double_ >> qi::double_ >> *qi::lit(',');
comment = '#' >> *(qi::char_ - qi::eol);
prefix = repo::seek[
qi::lit("point") >> '[' >> *comment
];
//prefix = repo::seek[qi::lexeme[qi::skip[qi::lit("point")>>qi::lit("[")>>*comment]]];
start %= prefix >> *singlePoint;
//BOOST_SPIRIT_DEBUG_NODES((prefix)(comment)(singlePoint)(start));
}
private:
qi::rule<Iterator, Point(), qi::space_type> singlePoint;
qi::rule<Iterator, std::vector<Point>(), qi::space_type> start;
qi::rule<Iterator, qi::space_type> prefix;
// implicit lexeme:
qi::rule<Iterator> comment;
};
#include <nonius/benchmark.h++>
#include <nonius/main.h++>
#include <boost/iostreams/device/mapped_file.hpp>
static boost::iostreams::mapped_file_source src("input.txt");
NONIUS_BENCHMARK("sample", [](nonius::chronometer cm) {
std::vector<Point> points;
using It = char const*;
PointParser<It> g2;
cm.measure([&](int) {
It f = src.begin(), l = src.end();
return phrase_parse(f, l, g2, qi::space, points);
bool ok = phrase_parse(f, l, g2, qi::space, points);
if (ok)
std::cout << "Parsed " << points.size() << " points\n";
else
std::cout << "Parsed failed\n";
if (f!=l)
std::cout << "Remaining unparsed input: '" << std::string(f,std::min(f+30, l)) << "'\n";
assert(ok);
});
})
图表:
另一个运行输出,实时:
关于c++ - 提升精神 : slow parsing optimization,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32968409/
下面的代码应该淡入淡出。我究竟做错了什么? $(window).scroll(function(){ if ($(window).scrollTop() > 910){ $('
我正在 java swing applet 上创建一个 whack a mole 游戏,但我在计时 mole 出现时遇到了问题。我似乎无法避免 paint () 在我身上循环,从而过快地随机化地鼠的坐
如果我从solaris服务器ssh到美国服务器,ssh连接很快,比如删除一个文件很快就可以完成。 但是为什么powershell远程处理这么慢,我进入远程 session 后,然后删除一个项目,需要1
我正在获取一个 Java 小程序来填充数据库。 我在 HP i3 ram6gb 上使用 JDK 1.7 和 XAMPP 3.2.1 32 位。我的数据库很大并且具有以下结构: [TABLE] attr
我正在使用 OpenGL 在 C++ 中制作塔防游戏。当尝试使用 Windows.H 中的“ sleep ”功能时,它会导致我的 OpenGL 窗口打开我输休眠眠的任何值的总时间,然后打开窗口。有什么
我有以下代码,它可以工作,但在每个切换操作结束时变得有点跳动。 切换段落会不会更流畅?我正在尝试获取该段落,但我不知道该怎么做。 body {width: 660px; margin: 0 aut
我在想这个。我创建了一个 Complex 类只是为了好玩(用于存储复数)并习惯于 TDD。 并且我编写了以下测试: [TestMethod] [TestCategory("COMPLE
我正在开发一款每 30 秒向互联网发布一次的应用程序。一切正常,直到屏幕熄灭。计时器似乎变慢了。发布需要大约 5 分钟。我已经尝试获取唤醒锁和 setforegroundactivity 但没有任何效
我有一个很大的表,我决定通过从另一个表中引入一个带有 ID 的新列并删除另外两个列来减小它的大小。以下是表格: Table tests: +---------------+--------------
每次我想对一些代码进行快速测试时,android studio 需要 20-40 分钟来加载一个模拟器,这导致我的笔记本电脑崩溃或运行速度非常慢。有什么方法可以只使用系统日志而不加载整个应用程序,类似
我正在尝试查看(主要是)阿拉伯语句子列表,并删除那些不是阿拉伯语的句子。我有一个判断字符是否为阿拉伯语的技巧:阿拉伯语没有大小写,所以如果字符是字母但不是大写或小写,它就是阿拉伯语。 我有下面的代码,
我有一个问题,我不知道怎么解释好,但我会尝试......例如,在某些游戏中,文本输出“慢”,一个接一个地写char,而不是所有的一次短语......那么,我怎样才能复制这种行为? 我想这样......
基于 Java 反射慢的名声,我一直避免使用它。我在当前项目的设计中达到了一个点,能够使用它会使我的代码更具可读性和优雅,所以我决定试一试。 我只是对差异感到惊讶,我注意到有时运行时间几乎长了 100
一个普通WEB站点的页面常常需要查询N条SQL语句后才能得出页面结果,当网站访问速度慢而前端做了大量优化工作以后,数据库瓶颈的查找也是WEB优化的一个重要部分。 MySQL中提供了一个
启用 slow log 有两种启用方式: 1, 在my.cnf 里 通过 log-slow-queries[=file_name] 2, 在mysqld进程启动时,指定--lo
scipy.special 中的 expit 函数是一个向量化的 sigmoid 函数。它计算 1/(1+e^(-x)),这很复杂,可能涉及泰勒级数。 我了解了“快速 sigmoid”,1/(1 +
我使用 PyCharm,我是 python 的新手。 经过 2 天弄清楚 tensorflow 的工作原理后,我成功了,但启动时间很慢。在句子之前一切正常:'Adding visible gpu de
因此,我们从一家安全公司获得了此报告,称我们在IIS 8.0上运行的MVC网站容易受到缓慢的HTTP post DoS攻击的攻击。报告说我们应该 限制请求属性是通过元素实现的, 特别是maxAllow
(请提供这个重复的问题。我很失望我找不到它。) 我的开发机器“慢”。我等待它“很多”。 想要帮助公平、准确地衡量那个时间的决策者曾问过我。您如何量化您在计算机上等待的时间(在编译期间,每天等待应用程序
我正在使用 jquery fadein fadeout 和慢速选项,但它对我来说仍然有点太快了。现在我读到你只能在快和慢之间进行选择,但是有没有办法让它变慢呢? 最佳答案 你有两个选择。第一种是在调用
我是一名优秀的程序员,十分优秀!