代码之家  ›  专栏  ›  技术社区  ›  ryeguy

什么是面向数据的设计?

  •  128
  • ryeguy  · 技术社区  · 15 年前

    我在读书 this article 这个人继续谈论如何将面向数据的设计与OOP相结合,让每个人都能从中受益匪浅。不过,他没有显示任何代码示例。

    我在谷歌上搜索了一下,没有找到任何关于这是什么的真实信息,更不用说任何代码示例了。是否有人熟悉这个术语并能提供一个例子?这可能是另一个词吗?

    4 回复  |  直到 8 年前
        1
  •  240
  •   Community    7 年前

    首先,不要将其与数据驱动设计混淆。

    我对面向数据设计的理解是,它是关于组织数据以进行有效的处理。尤其是在缓存未命中等方面,数据驱动的设计另一方面是让数据控制许多程序行为(由 Andrew Keith's answer )

    假设应用程序中有具有颜色、半径、弹性、位置等属性的球对象。

    面向对象方法

    在OOP中,你会这样描述你的球:

    class Ball {
      Point  position;
      Color  color;
      double radius;
    
      void draw();
    };
    

    然后你会创建一个这样的球集合:

    vector<Ball> balls;
    

    面向数据的方法

    然而,在面向数据的设计中,您更可能编写这样的代码:

    class Balls {
      vector<Point>  position;
      vector<Color>  color;
      vector<double> radius;
    
      void draw();
    };
    

    正如你所看到的,没有一个单位代表一个球了。球对象仅隐式存在。

    这在性能方面有许多优势。通常我们想同时对许多球进行操作。硬件通常需要大量连续的内存块来有效地运行。

    其次,您可以执行只影响部分球属性的操作。例如,如果您以各种方式组合所有球的颜色,那么您希望缓存只包含颜色信息。但是,当所有球属性都存储在一个单元中时,您也将拉入球的所有其他属性。即使你不需要它们。

    缓存使用示例

    假设一个球,每个球占64字节,一个点占4字节。一个缓存插槽也需要64个字节。如果我想更新10个球的位置,我必须将10*64=640字节的内存拉入缓存,并得到10个缓存未命中。但是,如果我能把球的位置作为单独的单元来处理,那就只需要4*10=40字节。这适用于一个缓存提取。因此,我们只得到1个缓存未命中来更新所有10个球。这些数字是任意的,我假设缓存块更大。

    但它说明了内存布局如何会对缓存命中造成严重影响,从而影响性能。这只会随着CPU和RAM速度之间的差异的扩大而增加重要性。

    如何布局内存

    在我的Ball示例中,我将问题简化了很多,因为通常对于任何普通的应用程序,您都可能一起访问多个变量。例如,位置和半径可能经常一起使用。那么你的结构应该是:

    class Body {
      Point  position;
      double radius;
    };
    
    class Balls {
      vector<Body>  bodies;
      vector<Color>  color;
    
      void draw();
    };
    

    您应该这样做的原因是,如果将一起使用的数据放在不同的数组中,那么它们将面临在缓存中竞争相同插槽的风险。因此,装载一个将丢弃另一个。

    因此,与面向对象编程相比,最终生成的类与问题的心理模型中的实体无关。由于数据是根据数据使用情况集中在一起的,所以在面向数据的设计中,您不可能总是有合理的名称来给类命名。

    关系数据库

    面向数据设计背后的思想与您如何看待关系数据库非常相似。优化关系数据库也可能涉及到更高效地使用缓存,尽管在这种情况下,缓存不是CPU缓存,而是将页面放入内存中。一个好的数据库设计器也可能将不经常访问的数据拆分成一个单独的表,而不是创建一个包含大量列的表,因为只有很少的列被使用过。他还可能选择取消某些表的规范化,这样就不必从磁盘上的多个位置访问数据。与面向数据的设计一样,这些选择是通过查看数据访问模式是什么以及性能瓶颈在哪里做出的。

        2
  •  13
  •   Alexei Averchenko    8 年前

    迈克·阿克顿公开谈论 Data oriented design 最近:

    我对它的基本总结是:如果你想要性能,那么考虑一下数据流,找到最有可能让你头疼的存储层,并对其进行优化。 很难。 Mike将重点放在二级缓存未命中上,因为他正在进行实时操作,但我认为同样的事情也适用于数据库(磁盘读取)甚至Web(HTTP请求)。我认为这是一种有用的系统编程方法。

    注意,这并不能免除你对算法和时间复杂性的思考,它只是把你的注意力集中在找出最昂贵的操作类型上,然后你必须以疯狂的CS技能为目标。

        3
  •  12
  •   bill c    15 年前

    我只是想指出,诺埃尔是专门谈论一些具体的需要,我们面临的游戏开发。我想其他正在进行实时软仿真的部门也会从中受益,但这不太可能是一种对一般业务应用程序有显著改进的技术。这种设置是为了确保底层硬件中的每一个性能的最后一位都被挤出。

        4
  •  -2
  •   Andrew Keith    15 年前

    面向数据的设计是应用程序的逻辑由数据集而不是过程算法构成的设计。例如

    程序方法。

    int animation; // this value is the animation index
    
    if(animation == 0)
       PerformMoveForward();
    else if(animation == 1)
      PerformMoveBack();
    .... // etc
    

    数据设计方法

    typedef struct
    {
       int Index;
       void (*Perform)();
    }AnimationIndice;
    
    // build my animation dictionary
    AnimationIndice AnimationIndices[] = 
      {
          { 0,PerformMoveForward }
          { 1,PerformMoveBack }
      }
    
    // when its time to run, i use my dictionary to find my logic
    int animation; // this value is the animation index
    AnimationIndices[animation].Perform();
    

    这样的数据设计促进了数据的使用,以构建应用程序的逻辑。它更容易管理,特别是在视频游戏中,可能有数千个基于动画或其他因素的逻辑路径。

    推荐文章