我正在开发的应用程序,用户可以在其中模拟测试并离线回答。我有一个软件,可以从我的数据库中获取数据(问题、备选方案、问题类型等),并将它们转换为数组。
我不知道哪一种是最有效的(记忆方面):用一个大数组创建一个包含所有问题的对象,或者用一个数组创建单独的对象(例如每个主题),或者在同一个对象中创建多个数组。创建一个内部有1000个阵列的阵列可以吗?还是最好将该阵列拆分为…10个阵列,每个阵列内部有100个阵列?
p.S:在测试过程中,我只会使用数组中的30个项目,所以我会从大数组(或多个数组)中提取条目,并将它们添加到小的30个条目数组中,该数组将根据用户的输入创建。
我想使用什么
我想要一个大数组,因为对我来说,排序和创建随机测试会更容易,有些人说1000个条目并不多,所以我想我会坚持使用大数组。什么东西会太大?10k,100k?
有三种效率需要考虑">
- 内存效率;即最小化RAM利用率
- CPU效率
- 程序员效率;即最大限度地减少您在编写、编写测试用例、调试和维护代码上花费的宝贵时间
请注意,上述标准相互作用。
内存效率
给出的Java中引用N数组的内存大小(以字节为单位)
N * reference_size + array_header_size + padding
其中:
reference_size
是引用的大小,单位为字节(通常为4或8)array_header_size
通常为12字节padding
大于或等于零,并且小于堆节点大小粒度
数组本身也有一个唯一的引用,该引用必须保存在内存中的某个位置。
因此,如果您将一个大阵列拆分为M个较小的阵列,您将使用至少(M - 1) * 16
额外字节的RAM,甚至可能更多。另一方面,我们在这里谈论的是字节,而不是千字节或兆字节。因此,这并不重要。
CPU效率
这很难预测。CPU利用率的影响将在很大程度上取决于你对阵列做什么,以及你如何做
如果只是对数组进行下标(索引),则该操作不取决于数组大小。但是,如果您有多个数组(例如,一个数组数组),那么在确定要在下标中使用哪个数组时会有额外的开销。
如果你在一个数组中搜索某个东西,那么你必须搜索的数组越大,所需时间就越长(平均而言)。但是,如果您将一个大阵列拆分为更小的阵列,这并不一定有帮助。。。除非您事先知道要搜索哪个较小的数组。
程序员效率
如果使用多个数组而不是一个数组,这可能会使代码更加复杂。更复杂的代码意味着程序员在应用程序开发和维护生命周期的所有阶段都要付出更多的努力。很难量化需要付出多少额外的努力。然而,程序员的努力意味着成本(支付工资)和时间(截止日期、上市时间等),这可能会超过内存和CPU的任何微小节省。
可扩展性
你说:
有些人说1000个条目并不多,所以我想我会坚持使用大数组。什么东西会太大?10k,100k?
再一次,它取决于上下文。事实上,用于X的100K个实例的数组的内存在很大程度上取决于X的平均大小。您很可能会耗尽内存来表示X实例而不是数组。
因此,如果你想让你的应用程序无限期地扩展,你可能应该改变架构,让它按需从数据库中获取问题/答案,而不是在启动时将它们全部加载到内存中。
过早优化
唐纳德·克努思经常(错误地)引用1的话说:
"过早的优化是万恶之源">
他指出的是,程序员倾向于优化那些并不真正需要优化的东西,或者基于错误的直觉来优化代码的错误区域。
我对此的建议如下:
不要过早地进行细粒度优化。(这并不意味着你应该忽视设计和编码阶段的效率问题,但我的建议是只考虑主要问题,例如算法的复杂性、API和数据库查询的粒度等。尤其是以后需要花很多精力才能解决的问题。)
如果您进行优化,请科学地进行:
- 使用基准来衡量性能
- 使用探查器查找性能热点,并将精力集中在这些热点上
- 使用基准测试来查看优化是否有所改进,并放弃没有帮助的优化
为您的优化设定一些现实的目标(或时间限制),并在达到这些目标时停止。
1-完整的报价更加细致入微。查一下。事实上,克努思自己也在引用托尼·霍尔的话。要对此进行更深入的探索,请参阅https://ubiquity.acm.org/article.cfm?id=1513451
老实说,1000不是一个大尺寸,但它关系到元素的大小。
然而,在未来,你的入口规模会增加,所以你肯定不想每次都改变逻辑。因此,你必须设计高效的东西,这对增长数据也应该是富有成效的。
内存问题-如果您将所有数据存储在一个数组或10个数组中,两者占用的内存量基本相同,差异非常小),但是,如果您有10个阵列,那么管理可能会很困难,随着需求的增长,您可能会面临更大的复杂性。
我可以建议您使用单个阵列,这将非常适合管理。您也可以考虑LinkedList,这将非常有利于更快的搜索结果。