2

我尝试做的事情:

我想在 RAM 中存储很多数据。为了更快的访问和更少的内存占用,我需要使用一个结构值数组:

MyStruct[] myStructArray = new MyStruct[10000000000];

现在我想在 MyStruct 中存储一个、两个、三个或四个字节的无符号整数值。但它应该只使用尽可能少的内存量。当我将一个值存储为一个字节时,它应该只使用一个字节,依此类推。

我可以用类来实现它,但这在这里不合适,因为在 64 位系统上,指向对象的指针需要 8 个字节。所以最好为每个数组条目存储 4 个字节。但我只想在需要时存储/使用一/二/三字节。所以我不能使用一些花哨的类。

我也不能使用一个带有一个字节的数组,一个带有两个字节的数组等等,因为我需要值的特殊顺序。而且这些值非常混杂,因此在切换到另一个数组时存储一个额外的引用将无济于事。

不管我只需要存储一个字节,大约 60% 的时间里只需要存储两个字节,大约 25% 的时间里只需要存储三个字节,是否有可能想要或者是唯一的方法来存储一个 4 字节的 uint 数组?

4

4 回答 4

6

这是不可能的。CLR 将如何处理以下表达式?

myStructArray[100000]

如果元素的大小可变,则 CLR 无法知道第 100000 个元素的地址。因此,数组元素始终是固定大小的。

如果您不需要O(1)访问,您可以在 a 上实现可变长度元素byte[]并自己搜索数组。

您可以将列表拆分为 1000 个单独打包的子列表。这样,您可以获得O(n/2000)平均搜索性能。也许这在实践中已经足够好了。

O(n/2)平均只能搜索“打包”数组。但是,如果您的部分数组是大小的 1/1000,它将变为O(n/2000). 您可以选择部分数组,O(1)因为它们都具有相同的大小。

此外,您可以调整部分数组的数量,使它们的大小分别约为 1k 个元素。那时,数组对象的开销和对它的引用消失了。这会给你O(1000/2 + 1)查找性能,我认为这是一个很大的改进O(n/2)。这是一个常数时间查找(有一个大常数)。

于 2012-07-07T22:31:09.020 回答
2

如果您愿意牺牲一些额外的 CPU 时间并为每个存储值浪费额外的 2 或 4 位,您可以接近您想要的。

您可以只使用 bytebyte[]并将其与BitArraycollection结合使用。然后,在 byte[] 中,您只需顺序存储一个、两个、三个或四个字节,并在 BitArray 中以二进制形式(两位对)表示,或者只是将一个位设置为值 1 以表示一组新的字节刚刚开始(或结束,但是你实现它)在你的数据数组中。

但是你可以在内存中得到这样的东西:

byte[]   --> [byte][byte][byte][byte][byte][byte][byte]...
BitArray --> 1001101...

这意味着您的字节数组中存储了 3 个字节、1 个字节、2 个字节等值。

或者您也可以将您的位数组编码为二进制对以使其更小。这意味着每个实际数据字节会占用 1.0625 到 1.25 个字节。

这取决于您的实际数据(您的MyStruct)是否足够。如果您需要区分这些字节真正对应的结构中的哪些值,您可能会在BitArray.

更新您的 O(1) 要求:

使用另一种索引结构,该结构将为每个 N 个元素存储一个索引,例如 1000。然后,您可以例如访问索引为 234241 的项目作为

indexStore[234241/1000]

它为您提供元素 234000 的索引,然后您只需通过检查 BitArray 中的几百个元素来计算元素 234241 的确切索引。

O(const) 是这样实现的,const 可以通过主索引的密度来控制,当然你用时间换空间。

于 2012-07-07T22:34:43.147 回答
1

你不能这样做。

如果数据没有排序,并且您对此无话可说,那么您将无法做您想做的事情。

简单场景:

array[3]

应该指向一些内存地址。但是,你怎么知道array[0]-的尺寸是array[2]多少?要以 O(1) 的方式存储该信息,您只会浪费比一开始想要保存的更多的内存。

您正在跳出框框思考,这很棒。但是,我的猜测是,这是您试图摆脱的错误盒子。如果您的数据确实是随机的,并且您希望直接访问每个数组成员,则您必须使用每个数字所需的最大宽度。对不起。

我有一种类似的情况,我需要存储的长度小于 32 位。但它们都是固定宽度,所以我能够通过自定义容器和一些位移来解决这个问题。

希望:

http://www.dcc.uchile.cl/~gnavarro/ps/spire09.3.pdf

也许您可以阅读它,并且您不仅可以每个数字拥有 8、16、24、32 位,而且可以拥有任何数字大小......

于 2012-07-07T23:16:30.587 回答
0

我几乎要开始研究一些短字编码的变体,比如 PkZip 程序。

甚至是 RLE 编码。

或者尝试更好地了解您的数据的使用情况。就像,如果这些都是向量或其他东西,那么某些组合是不允许的,例如,-1、-1、-1 对于金融图形应用程序基本上没有意义,因为它表示数据超出了可绘制范围。如果你能发现一些关于你的数据的奇怪之处,你可以通过为不同的需求使用不同的结构来减小大小。

于 2012-07-07T23:47:47.863 回答