什么是面向数据的设计?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (19)

我搜索了这一点,并找不到任何真正的信息,这是什么,更不用说任何代码示例。有没有人熟悉这个术语,并可以提供一个例子?这可能是另外一个字吗?

提问于
用户回答回答于

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

我对面向数据设计的理解是关于组织数据进行高效处理。特别是在缓存未命中等方面。数据驱动设计另一方面是让数据控制很多程序行为

假设你的应用程序中有球物体,并且具有诸如颜色,半径,弹性,位置等属性

面向对象的方法

在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个字节,一个Point占用4个字节。高速缓存插槽也需要64个字节。如果我想更新10个球的位置,我必须将10 * 64 = 640个字节的内存拉入缓存并获得10个缓存未命中。但是,如果我可以将球的位置作为单独的单位工作,那只需要4 * 10 = 40个字节。这适合一个缓存提取。因此我们只得到1个缓存未命中以更新所有10个球。这些数字是任意的我假设缓存块更大。

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

如何布置内存

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

class Body {
  Point  position;
  double radius;
};

class Balls {
  vector<Body>  bodies;
  vector<Color>  color;

  void draw();
};

你应该这样做的原因是,如果一起使用的数据放置在单独的阵列中,则存在竞争缓存中相同插槽的风险。因此加载一个会抛出另一个。

因此,与面向对象编程相比,你最终创建的类与您的心智模型中的实体无关。由于数据是基于数据使用而混合在一起的,因此你不总是会有明智的名称来为您的类提供面向数据的设计。

与关系数据库的关系

面向数据设计背后的思想与你对关系数据库的看法非常相似。优化关系数据库还可能涉及更高效地使用缓存,尽管在这种情况下,缓存不会将CPU缓存放到内存中。一个好的数据库设计人员也可能会将不经常访问的数据拆分到一张单独的表格中,而不是创建一个列数量巨大的表格,而只有少数几列被使用过。他也可能选择对一些表格进行非规范化处理,以便不必从磁盘上的多个位置访问数据。就像面向数据设计一样,这些选择是通过查看数据访问模式是什么以及性能瓶颈在哪里进行的。

用户回答回答于

我只想指出,正在专门讨论我们在游戏开发中面临的一些具体需求。我认为其他正在进行实时软模拟的部门将从中受益,但它不太可能成为一项显着改善一般商业应用的技术。这种设置是为了确保性能的每一点都被挤出底层硬件。

扫码关注云+社区