谷歌面试问题

Google Interview Question

本文关键字:问题 面试 谷歌      更新时间:2023-10-16

这是谷歌面试中的一个问题。

如果哈希表增长超过30gb,可能会出现什么问题(忽略坏哈希函数等问题)

我不知道。什么才是令人满意的答案?

谢谢

答案部分取决于他们谈论的是经典的哈希表实现(如Java中的hashtable/HashMap)还是更复杂的东西。最后,按照今天的标准,30 GB的内存对于一台机器/虚拟机来说仍然是相当大的。

想想下面是什么:

  1. 它必须在一些大数组的任意位置读写。
  2. 如果它被填满超过一定程度,它就必须增长;参见Java实现中的"load factor"。
  3. 在垃圾回收语言/实现中,存储在哈希表中的所有对象都需要由垃圾回收器检查

这会导致以下问题:

  1. 目前还不清楚,即使是今天的操作系统也能很好地分配几十gb的内存块
  2. 为简单起见,假设表本身实际使用了表的一半(不包括键和值对象)。所以里面有一个15gb的数组。因此,每当表增长时,您需要至少分配另一个 15gb
  3. 即使分配了几十GB的数组,操作系统也会对其中的一些内存进行分页。因为我们假设一个很好的哈希函数,如果我们使用数组中的大部分数据,我们将中断页面缓存。会有很多页面错误。
  4. 假设我们使用所有的数据。有些键经常使用,有些则不常用。为了说明这一点,假设每个键值都很小——128字节。为了简单起见,假设我们将哈希表中的所有内容都存储为值。所以30G/128 = ~ 250M个条目。但是假设25000个常用钥匙。(25k/250M = 0.01%)。但如果有一个好的哈希函数,这些会均匀地分散在庞大的数组中。即使是较小的页面大小——比如4kb, 25K(条目)* 128字节(条目大小)= ~3.5Mb的常用数据也需要花费25K(条目)* 4K(页面大小)= ~ 100Mb的内存来保持分页……高达3.5%的效率!
  5. 在Java世界中,从业者不建议堆大小大于4 - 8Gb。当然有像Azul这样的东西,但这只是证明了一点——典型的垃圾收集器不能很好地扩展到这些大小。

我同意其他海报,谷歌正在寻找分布式作为一个解决方案。但我认为,从本质上讲,一个简单的哈希表会在超出某一点时停止扩展。在上面,

  1. 如果所有条目都被相对均匀地访问,则必须分配
  2. 如果大多数时间访问一些地图,使用两张地图(最常用的一张)可以买到很多。
  3. 在Java世界中,使用专门的映射来存储堆外的数据也可以提高性能;请看Peter Lawrey的作品。
  4. 即使简单地剥离哈希表中的底层数组(如Java的ConcurrentHashMap所做的)也可以在必须增长哈希表时为您带来重大改进。

我认为面试官期待的是分布式哈希表之类的东西,因为30GB的哈希表不能存储在一台机器上(至少在当前的64位世界中);从我个人的经验来看,相当多的google问答都是围绕着分布式计算、map-reduce等展开的,

一些问题:

  1. 哈希冲突可能是主要问题之一。
  2. 当数据以哈希表的形式存储在磁盘中时,频繁地读取磁盘也是低效的。