有限状态机的速度 - OO与程序

时间:2010-09-30 04:20:46

标签: c++ oop performance procedural-programming state-machine

嘿所有,
我正在设计一个程序,它将从输入中接受一系列令牌并将它们提供给我设计的有限状态机。我设计了一个面向对象风格的测试有限状态机,其中包含机器本身和转换等的结构,但我正在编写的应用程序是速度非常重要的应用程序。

到目前为止,使用机器,添加新状态等已被证明是简单而不是非常复杂。很容易理解和离开一个月,回到代码不会很迷惑。但是,我不确定当前OO方法的速度权衡是什么。对象的分配,数据的存储等是否会消除使用一堆标签和goto语句所带来的大部分速度?

5 个答案:

答案 0 :(得分:3)

我更希望结构化有条理,可维护,可理解(即使在离开一个月之后,这是相当高质量的)代码而不是“一堆标签和goto语句”。话虽如此,我还会在代码上运行profiler来检测进行速度分析时的瓶颈。

答案 1 :(得分:3)

而不是根据OO比功能或程序编程更慢地考虑它而不是在操作方面考虑它。调用函数,分支,获取,存储等......所有这些都需要一些时间,并且需要了解每个解决方案的性能,这些解决方案需要记录每个解决方案中需要执行的操作。

最佳方法是使用您的OO测试解决方案,看看它是否足够快。如果没有,那么对其进行分析,找出哪些分支机构或商店花费最多,并查看是否可以避免或简化它们。慢慢重新构建您的解决方案,直到它达到您所追求的性能目标。在某些情况下,您可能需要采用更具功能性或程序性的风格。

最后,如果你编写一个由数百个堆栈变量组成的单个函数并且转到你做错了。代码必须始终可读和可维护。

额外的想法:您是否可以在更好的硬件上再花费5,000美元来避免50,000美元的开发成本优化?

答案 2 :(得分:2)

简而言之,处理器在查找表查找时比分支更快。你描述的OO风格会更快,只要表格易于处理并且足够小以适应缓存。 (我当然不会说这两种范式都与实现有关。)

技术性更强:处理器具有32-64 K的L1缓存和几个到几十个兆字节的L2-L3。分支缓存最多只能达到几千字节。

答案 3 :(得分:1)

状态机多久更改一次?如果它保持一段时间不变,我所做的就是用我喜欢的语言将其翻译成硬编码的例程。

状态机的转换图来自哪里?它来自正则表达式吗?您知道可以直接将其转换为结构化代码,而无需先构建弧集。事实上,开始编写代码可能更容易。

然后我要么只是制作应用程序的那部分,要么我动态编译并将其链接到一个DLL并动态加载它。后者只需几秒钟。

有限状态机非常简单,它们基本上应该只需要加载I / O缓冲区的一小部分时间。他们不应该做任何不必要的内存分配,数据结构构建,任何OO hoo-haw。

请记住,表示为一组状态和弧元组的有限状态机是一个理论模型。它像图灵机一样存在,以证明它的定理。就像图灵机一样,它在代码中不一定是一种很好的实现技术。


为了向您展示我的意思,请考虑十进制整数的正则表达式:

dd*

其中'd'表示数字。作为有限状态机(元组),它将是:

A d -> B
B d -> B

作为代码:

char c = getc();
if (DIGIT(c)){
  c = getc();
  while(DIGIT(c)){
    c = getc();
  }
}

查看此代码与正则表达式的相似性? 不要认为c = getc()为“获得下一个字符c”。 把它想象成“接受当前的角色c”。 我希望你能看到代码实际上不会比这更快。

如果你真的是从弧集开始,你可以生成这个:

c = getc();

A:
if (DIGIT(c)){c = getc(); goto B;}
goto END;

B:
if (DIGIT(c)){c = getc(); goto B;}
goto END;

END:

这是意大利面条代码,但不仅仅是arc-set,它将与结构化代码一样快。 (事实上​​,这或多或少是编译器将结构化代码转换成的内容。)

答案 4 :(得分:0)

我是一名应用程序性能工程师,以下是我对有限状态机性能的看法。请注意,这些是意见,不是我衡量的事实,但我认为它对某些人有用:

  • FSM 对于硬件来说通常很困难。硬件总是在执行它以前从未执行过的代码(因为从一种状态转移到另一种状态需要不同的功能)。
  • 原则上,巨大的 switch 会比 OOP 方法更快,因为整个 switch 都在一个函数内,所以至少有一些空间局部性。如果您使用枚举来保存当前状态,请确保 FSM 中的相邻状态是枚举中的相邻数字,因为这会增加处理状态的函数在指令缓存中的可能性。
  • 在 OOP 的情况下,将来自不同类的所有状态更改函数放入同一个链接器部分(例如,状态更改函数上的 __attribute ((section (".state-machine"))) 属性) - 如果程序是小,如果程序很大很重要

这些是一般性建议。现在,根据您的具体情况,您还有一些建议:

  • 如果您有许多相同的有限机器,请考虑使用面向数据的设计方法来创建它们。这个想法不是随机地处理机器,而是根据它们当前的状态 link