c++ - 脚本到二进制转换和对象序列化

标签 c++ actionscript-3 flash serialization scripting

我编写的所有代码(C++或AS3)都包含大量脚本(JSON或XML)。我的问题是,解析有时可能会非常缓慢,尤其是在使用功能较弱的设备(例如手机)时尤其如此。

这是我的Flash脚本的示例:

        <players class="fanlib.gfx.TSprite" vars="x=0|y=-50|visible=Bool:true">
            <player0 class="fanlib.gfx.TSprite" vars="x=131|y=138">
                <name class="fanlib.text.TTextField" format="Myriad Pro,18,0xffffff,true,,,,,center,,,,0" alignX="center" alignY="bottom" filters="DropShadow,2" vars="background=Bool:false|backgroundColor=0|embedFonts=Bool:true|multiline=Bool:false|mouseEnabled=Bool:false|autoSize=center|text=fae skata|y=-40"/>
                <avatar class="fanlib.gfx.FBitmap" alignX="center" alignY="center" image="userDefault.png"/>
                <chip class="fanlib.gfx.FBitmap" alignX="center" alignY="center" image="chip1.png" vars="x=87|y=68"/>
                <info class="fanlib.text.TTextField" format="Myriad Pro,18,0xffffff,true,,,,,center,,,,0" alignX="center" alignY="top" filters="DropShadow,2" css=".win {color: #40ff40}" vars="y=40|background=Bool:false|backgroundColor=0|embedFonts=Bool:true|multiline=Bool:false|mouseEnabled=Bool:false|autoSize=center"/>
            </player0>

            <player1 class="Copy:player0" vars="x=430|y=70">
                <chip class="Child:chip" image="chip2.png" vars="x=-82|y=102"/>
            </player1>
            <player2 class="Copy:player0" vars="x=778|y=70">
                <chip class="Child:chip" image="chip3.png" vars="x=88|y=103"/>
            </player2>
            <player3 class="Copy:player0" vars="x=1088|y=137">
                <chip class="Child:chip" image="chip4.png" vars="x=-111|y=65"/>
            </player3>
            <player4 class="Copy:player0" vars="x=1088|y=533">
                <chip class="Child:chip" image="chip5.png" vars="x=-88|y=-23"/>
            </player4>
            <player5 class="Copy:player0" vars="x=585|y=585">
                <chip class="Child:chip" image="chip6.png" vars="x=82|y=-54"/>
            </player5>
            <player6 class="Copy:player0" vars="x=117|y=533">
                <chip class="Child:chip" image="chip7.png" vars="x=85|y=-26"/>
            </player6>
        </players>

上面的脚本创建“本机”(如“非动态”)Flash对象。 TSprite是Sprite的后代,FBitmap继承自Bitmap等。在71KBs上,要花数十秒才能在我的Sony XPeria上进行解析。

我正在考虑将脚本转换为二进制文件,而不是优化解析器(无论如何也不会获得太大 yield ),以便将脚本用于调试,并将最终版本的二进制文件用于发布构建的代码。

一个问题是,当序列化一个对象时,一个对象如何处理从一个对象到另一个的指针?指针如何从内存转换为磁盘文件友好格式,然后又转换回内存?

另一个问题是,“嵌套”对象如何处理?例如,在Flash中,一个对象可以是其他对象的图形容器。这样的状态可以序列化吗?还是必须单独保存对象,并在从磁盘加载对象时通过嵌套功能(即addChild等)将其添加到其父对象?

如果可能的话,我希望可以适用于C++或AS3不同语言的通用准则。

最佳答案

据我了解,您的想法是通过将对象的创建(从一些固件脚本(xml / json)替换为反序列化(从二进制)先前序列化的对象)来节省一些时间。如果真是这样,我相信您采用错误的方法来解决此问题。

由于您已要求一般性准则,因此我将尽力解释我的推理,而不必过于深入地研究特定于语言的细节。请注意,我将讨论常见情况,并且可能会有异常(exception)。没有灵丹妙药,您应该分析您的方案以选择最佳解决方案。

从一个 Angular 来看,基于fixture / script创建对象集与从二进制反序列化对象没有什么不同。最后,它们都是关于将某些“压缩”状态转换为可以使用的对象。是的,确实,二进制文件通常较小,但是像JSON这样的格式在普通情况下没有那么多开销(尽管XML通常更具冗余性)。通常,在从二进制反序列化此状态,而不是从脚本解析的状态下,您不会节省很多时间/内存。这是我工作时遇到的一个真实示例:Mental Ray是电影行业中渲染3d场景\特殊效果的实际标准。它使用textual file format表示场景,这些场景在很多方面都与JSON相似。 Mental Ray的计算工作很繁重,性能是此处的关键问题之一,但如果没有二进制场景文件格式,它的性能就很好。因此,从这方面分析,您可以说这两种方法之间没有实质性差异。

从另一个 Angular 来看,可能会有差异。虽然反序列化对象意味着仅将对象的加载状态加载到字段中,但是从脚本创建对象还可以在之上包括一些额外的初始化。因此,在某些情况下,使用反序列化方法可能会受益。

但是,最后我会说,简单地将脚本对象替换为序列化对象不是一个好主意,因为脚本和序列化在概念上是并具有不同的用途(尽管它们确实有一些共同点)。使用序列化方法,您可以灵活地修改固定状态(通常,人类要编辑二进制文件而不是JSON / XML更加困难)以及进行初始化工作的能力。

因此,请考虑您在方案中实际需要的内容并坚持下去。那是最好的方法。

现在,如果碰巧您实际上需要对对象进行脚本编写,但是这种方法不够快,我将研究通过以下两种方法之一来加速它:

  • 分析是否可以以较少的加载时间来重组数据。这并非总是可能的,但是,值得尝试一下。
  • 除了简单地创建对象并将状态加载到其字段中并尝试对其进行优化之外,还分析脚本引擎对初始化对象所做的其他操作。这种方法实际上具有最大的潜力,因为这是唯一在性能方面(脚本和反序列化方法之间)具有实质性差异并且不会导致概念误用的部分。尝试看看您是否能够减少初始化对象所需的工作量。如果您当前正在使用一些通用脚本引擎\框架,则针对您的需求量身定制一些更合适的方法。

  • 现在,回答您的原始问题...

    how does one handle pointers from one object to another when serializing them?



    引用是令人头疼的,大多数序列化实现都不会引起麻烦。

    一种方法是在序列化过程中使用某些东西来标识对象(例如,指针),序列化保留此身份的对象,并将从另一个对象到该对象的引用存储为不是原始类型,而是作为引用类型(基本上保存身份) )。反序列化时-跟踪所有反序列化的对象,并在反序列化引用类型字段时重用它们。

    How are pointers translated from memory to disk file-friendly format,then back to memory?



    序列化处理原始内存的情况很少。这种方法仅适用于原始类型,不适用于Poiners /引用。支持反射\自省(introspection)的语言通常使用它来检查字段的值以序列化对象。如果我们谈论的是纯C++,那么反射效果很差-除了使对象本身定义将其序列化为字节流并使用这些方法的方法外,没有其他可靠的方法。

    Another question is, what about "nested" objects? In Flash for example, an object can be a graphics container of other objects. Could such a state be serialized? Or must objects be saved separately and, when loaded from disk, added to their parents through the nesting functions (i.e. addChild etc...)?



    如果我们谈论反序列化-应该将它们视为引用(请参阅上面的答案)。使用诸如addChild之类的方法不是一个好主意,因为它可能包含会弄乱事情的逻辑。

    希望这能回答您的问题。

    关于c++ - 脚本到二进制转换和对象序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20354256/

    相关文章:

    javascript - 解决方法 Flash 不允许来自 Javascript 的全屏

    javascript - "open"在网络浏览器中修改 "save as"文件到 javascript/flash/silverlight 或 java,而不上传到服务器?

    c++ - 标准的意图是任何形式的 `nested-type-specifier followed by an identifier` 都可以称为合格 ID

    c++ - 没有模式有异常(exception)是什么意思? (数组中出现次数最多的数)?

    c++ - 我不知道为什么c++中复制构造函数的调用不稳定

    python - 在 C++ 中嵌入 python 的编码

    c# - 在 C# 中使用正则表达式更改字符串(基于 ActionScript 函数)

    arrays - 使用最小间隔/分布填充随机数数组?

    actionscript-3 - 加载 NetStream 视频时出现问题

    javascript - JS/Flash - 拖动包含 img 的 anchor vs 拖动不带 anchor 的图像 - 如何获取 anchor 内的 img?