【问题标题】:Does optimizing code in TI-BASIC actually make a difference?在 TI-BASIC 中优化代码真的会产生影响吗?
【发布时间】:2017-02-20 15:49:38
【问题描述】:

我知道在 TI-BASIC 中,惯例是痴迷优化并尽可能多地节省位(我承认这很有趣)。

例如,

DelVar Z
Prompt X
If X=0
Then
    Disp "X is zero"
End                   //28 bytes

将被清理为

DelVar ZPrompt X
If not(X
    "X is zero        //20 bytes

但是以这种方式优化代码真的会产生影响吗?它的运行速度明显加快还是节省了内存?

【问题讨论】:

  • 提示:在“清理”代码部分,您可以删除最后一行的Disp。在 TI-Basic 程序的最后一行计算的任何内容(设置为 Ans)都会隐式显示。 (如果最后一行没有设置Ans,则显示Done)。
  • @Timtech 我不知道,谢谢!现已编辑。
  • 即使这确实节省了执行时间,但当您稍后尝试修改程序时,您将失去所有节省的时间来试图弄清楚程序在做什么。即使在 TI-Basic 中,在大多数情况下也最好为人类编写。
  • @Vaelus 我编写自己的程序并为自己编写,因此不需要可读性。另外 TI-84 真的很慢,我需要尽可能节省时间。

标签: optimization micro-optimization ti-basic


【解决方案1】:

当然,它会有所作为。我为 TI-84+CSE 编写了一个完整的彩色 RPG,让我告诉你,如果不优化我的任何代码,游戏将完全无法运行。目前,在 CSE 上,Uvutu 的巫术只有在所有其他程序都存档并且所有其他内存都用完 RAM 的情况下才能运行。 单独程序和数据存储在 RAM 中占用 20k 字节,或者在所有可用用户内存下仅占用 1kb。在使用所有变量的情况下,内存接近危险的低点。在我的开发过程中,由于优化不佳,我什至无法在没有“内存全部消失”错误的情况下启动游戏。我有计划实施各种额外的东西,但由于空间和速度方面的考虑,不可能这样做。这只是对空间的考虑。

在速度部门,游戏在整个世界变得并且仍然是缓慢的。与其他游戏相比,在主世界中四处走动慢得令人痛苦,这是因为我必须在该代码中做些什么;我必须检查碰撞,检查用户是否正在移动到新地图,检查他们是否按下了应该非法响应的键,检查是否应该继续战斗等等。我能够对步行速度进行轻微的优化,但即便如此,我也可以公然说我已经做出了改进。它仍然非常慢(至少与我制作的所有其他端口相比),但我让它变得更容易忍受了。

总之,通过我自己制作大型项目的经验,我可以说在 TI-Basic 中,优化代码确实会有所作为。其他答案提到了这一点,但 TI-Basic 是一种解释性语言。这意味着代码不会被编译成更快、更低级别的代码,但是您放入程序中的内容会在执行时直接读取,由解释器解释,调用子例程和执行所需的其他内容命令,然后返回读取下一行。因此,以及 TI-84+ 系列 CPU、Zilog Z80 是在 1976 年设计的这一事实,你会得到一个相当慢的解释器,尤其是在这个时代。因此,您运行的命令越少,您就越能利用系统的怪异之处,例如 Ans 是最快的变量,也可以保存最多类型的数据(整数/浮点数、字符串、列表、矩阵等),获得更好的性能。

来源:我自己的经历,记录在这里:https://codewalr.us/index.php?topic=778.msg27190#msg27190

TI-84+CSE RAM 编号来自这里:https://education.ti.com/en/products/calculators/graphing-calculators/ti-84-plus-c-se?category=specifications

关于 Z80 的信息来自这里:http://segaretro.org/Zilog_Z80

【讨论】:

    【解决方案2】:

    TI-BASIC 是一种解释型语言,这通常意味着每次操作都会产生巨大的开销。

    解释语言的工作方式是,不是将程序实际编译成直接在 CPU 上运行的代码,而是每个操作都是对解释器的函数调用,解释器查看需要做什么,然后调用函数来完成那些子任务。在大多数情况下,开销是速度的一个或两个因素,通常也是堆栈内存使用量。但是,非堆栈的内存通常是相同的。

    在您上面的示例中,您正在执行完全相同数量的操作,这应该意味着它们的运行速度完全相同。您应该优化的是 i = i + 1 之类的东西,这是 4 个操作,i++ 是 2 个操作。 (例如,TI-BASIC 不支持 ++ 运算符)。

    这并不意味着所有操作都需要完全相同的时间,在内部,一个操作可能会调用数百个其他函数,或者它可能像更新单个变量一样简单。解释器的程序员也可能已经实现了各种优化非常具体的语言结构的窥孔优化,例如for(int i = 0; i < count; i++) 既可以实现为一组昂贵的解释器函数,其行为就像i 是通用的,也可以优化为编译循环,它只需要更新变量i 并重新评估count .

    现在,并非所有解释型语言都注定要这样苍白的存在。比如JavaScript曾经是一个,但是现在所有主要的js引擎都JIT编译代码直接在CPU上运行。

    更新:澄清并非所有操作都是平等的。

    【讨论】:

    • 但事实并非如此,命令的性能存在巨大差异,并不是 1 个命令 = 1 个单位时间。例如:goto 很慢(并且可能导致内存泄漏),if 的性能特征取决于它后面是否有thenIS>( 比正常递增慢(但确实存在!)但是如果你可以使用内置的跳过它比等效增量+if更快。
    • 补充@harold 所说的,TI-BASIC 中有一些奇怪的怪癖,例如 For( 循环在特定情况下运行得慢得多(例如,当以下 If 语句没有Then 为假)如果没有右括号。
    【解决方案3】:

    是的。优化您的 TI-Basic 代码会产生影响,而且这种差异比大多数编程语言所发现的要大得多。

    在我看来, 对 TI-Basic 程序最重要的优化是 size(使它们尽可能小)。这对我来说很重要,因为我的计算器上有几十个程序,只有 24 kB 的用户可访问 RAM。在这种情况下,实际上没有必要花费大量时间来节省几个字节的空间。相反,我只是建议学习最短且最有效的做事方法,这样当你编写程序时,它们自然会变得很小。

    此外, TI-Basic 程序应针对速度进行优化。我想到的例子包括未封闭的For(循环的怪癖,计算一次值而不是在循环的每次迭代中计算它(如果可能的话),以及使用快速访问的变量,例如Ans和每当必须多次访问变量(例如 1000 次以上)时,财务变量。

    第三种可能的优化是针对运行时内存使用。每个循环、函数调用等都有必须存储在内存堆栈中的开销,以便在程序执行期间返回原始位置、计算值等。避免内存泄漏很重要(例如使用Goto 跳出循环)。

    由您决定如何平衡这些优化。我更喜欢:

    1. 首先,确保我的程序中没有内存泄漏或错误嵌套循环。
    2. 利用对程序速度影响很小或没有影响的任何大小优化。
    3. 考虑速度优化,并确定增加的速度是否值得增加程序大小。

    【讨论】:

      猜你喜欢
      • 2019-06-24
      • 2012-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-28
      • 1970-01-01
      • 2023-03-27
      相关资源
      最近更新 更多