楼主: tigermlt
跳转到指定楼层
上一主题 下一主题
收起左侧

LinkedIn System&Infra 两轮电面

🔗
 楼主| tigermlt 2017-12-1 14:47:21 | 只看该作者
全局:
xinxinzhenbang 发表于 2017-12-1 13:06
羡慕楼主可以做两个题,我只做一题真是凉凉。

我第一轮也只做了一道题,感觉对面印度小哥全程装傻。不管我怎么解释都说不懂,然后跑了两个test case还再不停地写test case,感觉就是想找一个让我的代码不work。然后各种浪费时间。遇到这样的人我也很无奈。。。
回复

使用道具 举报

🔗
tomdarling 2017-12-3 22:57:08 | 只看该作者
全局:
请问楼主 lc漆撕溜 是哪个题呀?
回复

使用道具 举报

🔗
asdwb 2017-12-3 23:37:44 | 只看该作者
全局:
wxl3691 发表于 2017-12-1 13:29
其实collabedit真的是好东西,代码不管对错都可以上,以后skype集成codepad成功后,就是对着视频看脸写代码 ...

fb 面试 用的codepad也是不能编译的
回复

使用道具 举报

🔗
wxl3691 2017-12-4 02:40:12 | 只看该作者
全局:
asdwb 发表于 2017-12-3 23:37
fb 面试 用的codepad也是不能编译的

那个codepad感觉面试官那边是可以测的,codepad有这功能。。。。。。。
回复

使用道具 举报

🔗
asdwb 2017-12-4 03:48:11 | 只看该作者
全局:
wxl3691 发表于 2017-12-4 02:40
那个codepad感觉面试官那边是可以测的,codepad有这功能。。。。。。。

进fb的那个界面第一句话就是不能编译只是share的文档,面的时候很随意, 随便给了个函数的接口,给样例都不打注释,想到啥直接写就好。
回复

使用道具 举报

🔗
magicsets 2017-12-4 06:54:42 | 只看该作者
全局:
1024 block的这道题目其实是一个比较简化的buffer manager组件,其中用来标记各个block有没有使用过的那部分数据一般称为meta data。

meta data使用什么数据结构其实可以比较灵活,但是最关键的一点是meta data本身也需要作为file的一部分能够被存储到disk上 —— 否则你下次读取那个文件就不知道哪些block被用过了。

很多(数据库)系统中,出于性能考虑,meta data都是直接映射到block上的,也就是使用block的memory定义数据结构——这需要手动进行内存管理——也就是你不能用malloc/new或是std::vector/std::list之类的去定义meta data。

另一个选项就是使用C++标准库中的数据结构(Java类同),然后在save/load的时候serialize/deserialize meta data。

这里贴一份样例代码,都是使用block memory进行手动内存管理的,有三种实现:
(1) bool 数组
(2) bit map
(3) 用一个recycle数组记录未被使用的block

其中(1)和(2)的allocate都是O(n)时间,(2)由于使用了builtin_clz所以会比(1)快很多——但是因为只有1024个blocks,所以也无所谓了...

(3)的allocate是O(1)时间,但是meta data耗用的空间会大一点(3个blocks)

  1. #include <array>
  2. #include <cstddef>
  3. #include <cstdint>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <iostream>
  7. #include <memory>
  8. #include <stdexcept>

  9. constexpr std::size_t kBlockSize = 1024;
  10. constexpr std::size_t kNumBlocks = 1024;

  11. using BlockID = std::size_t;
  12. using Block = std::array<char, kBlockSize>;

  13. // abstract class
  14. class StorageManagerInterface {
  15. public:
  16.   virtual BlockID allocateNewBlock() = 0;

  17.   virtual void writeData(const BlockID block_id, const void *data) = 0;

  18.   virtual void deleteBlock(const BlockID block_id) = 0;
  19. };


  20. // 三种实现: bool array, bit map, free list

  21. // -----------------------------------------------------------------------------
  22. // 1. bool array
  23. // -----------------------------------------------------------------------------
  24. class ByteArrayMetaData {
  25. public:
  26.   ByteArrayMetaData(void *memory)
  27.       : status_(static_cast<bool*>(memory)),
  28.         capacity_(kNumBlocks - 1) {
  29.   }

  30.   std::size_t getNumOfBlocksUsed() const {
  31.     return 1;
  32.   }

  33.   BlockID alloc() {
  34.     for (std::size_t i = 0; i < capacity_; ++i) {
  35.       if (!status_[i]) {
  36.         status_[i] = true;
  37.         return i;
  38.       }
  39.     }
  40.     throw std::runtime_error("Out of blocks");
  41.   }

  42.   void free(const BlockID block_id) {
  43.     status_[block_id] = false;
  44.   }

  45. private:
  46.   bool *status_;
  47.   const std::size_t capacity_;
  48. };


  49. // 给bit map使用的一个辅助函数
  50. template <typename T>
  51. inline int LeadingZeroCount(T word);

  52. template <>
  53. inline int LeadingZeroCount<unsigned>(unsigned word) {
  54.   return __builtin_clz(word);
  55. }
  56. template <>
  57. inline int LeadingZeroCount<unsigned long>(unsigned long word) {
  58.   return __builtin_clzl(word);
  59. }
  60. template <>
  61. inline int LeadingZeroCount<unsigned long long>(unsigned long long word) {
  62.   return __builtin_clzll(word);
  63. }

  64. // -----------------------------------------------------------------------------
  65. // 2. bit map
  66. // -----------------------------------------------------------------------------
  67. class BitVectorMetaData {
  68. public:
  69.   BitVectorMetaData(void *memory)
  70.       : num_bits_(kNumBlocks - 1),
  71.         data_(static_cast<std::size_t*>(memory)),
  72.         data_size_((num_bits_ >> kHigherOrderShift) +
  73.                    (num_bits_ & kLowerOrderMask ? 1 : 0)) {
  74.   }

  75.   std::size_t getNumOfBlocksUsed() const {
  76.     return 1;
  77.   }

  78.   BlockID alloc() {
  79.     BlockID ret = num_bits_;
  80.     for (std::size_t i = 0; i < data_size_; ++i) {
  81.       const std::size_t code = ~data_[i];
  82.       if (code) {
  83.         const std::size_t offset = LeadingZeroCount<std::size_t>(code);
  84.         data_[i] |= kTopBit >> offset;
  85.         ret = (i << kHigherOrderShift) | offset;
  86.         break;
  87.       }
  88.     }
  89.     if (ret < num_bits_) {
  90.       return ret;
  91.     }
  92.     throw std::runtime_error("Out of blocks");
  93.   }

  94.   void free(const BlockID block_id) {
  95.     data_[block_id >> kHigherOrderShift] &= ~(kTopBit >> (block_id & kLowerOrderMask));
  96.   }

  97. private:
  98.   static constexpr std::size_t kLowerOrderMask = (sizeof(std::size_t) << 3) - 1;
  99.   static constexpr std::size_t kHigherOrderShift = sizeof(std::size_t) == 4 ? 5 : 6;
  100.   static constexpr std::size_t kTopBit = static_cast<std::size_t>(1) << kLowerOrderMask;

  101.   const std::size_t num_bits_;
  102.   std::size_t *data_;
  103.   const std::size_t data_size_;
  104. };


  105. // 3. free list
  106. class FreeListMetaData {
  107. public:
  108.   FreeListMetaData(void *memory)
  109.       : capacity_(kNumBlocks - CalculateNumBlocksUsed()) {
  110.     alloc_size_ = reinterpret_cast<std::uint16_t*>(memory);
  111.     recycle_size_ = alloc_size_ + 1;
  112.     recycle_list_ = recycle_size_ + 1;
  113.   }

  114.   std::size_t getNumOfBlocksUsed() const {
  115.     return CalculateNumBlocksUsed();
  116.   }

  117.   BlockID alloc() {
  118.     if (*recycle_size_ > 0) {
  119.       return recycle_list_[--(*recycle_size_)];
  120.     }
  121.     if (*alloc_size_ < capacity_) {
  122.       return (*alloc_size_)++;
  123.     }
  124.     throw std::runtime_error("Out of blocks");
  125.   }

  126.   void free(const BlockID block_id) {
  127.     recycle_list_[(*recycle_size_)++] = block_id;
  128.   }

  129. private:
  130.   static inline std::size_t CalculateNumBlocksUsed() {
  131.     const std::size_t total_bytes =
  132.         sizeof(std::uint16_t) +              // alloc_size_
  133.         sizeof(std::uint16_t) +              // recycle_size_
  134.         sizeof(std::uint16_t) * kNumBlocks;  // recycle_list_
  135.     return (total_bytes + kBlockSize - 1) / kBlockSize;
  136.   }

  137.   std::uint16_t *alloc_size_;
  138.   std::uint16_t *recycle_size_;
  139.   std::uint16_t *recycle_list_;
  140.   const std::size_t capacity_;
  141. };


  142. template <typename MetaData>
  143. class StorageManager : public StorageManagerInterface {
  144. public:
  145.   StorageManager() {
  146.     // 读取文件 -- 这里简化为malloc + 置0
  147.     stream_ = std::malloc(sizeof(Block) * kNumBlocks);
  148.     std::memset(stream_, 0, kNumBlocks * kBlockSize);

  149.     // 初始化meta data
  150.     meta_data_ = std::make_unique<MetaData>(stream_);

  151.     // 定位到数据区域
  152.     blocks_ = static_cast<Block*>(stream_) + meta_data_->getNumOfBlocksUsed();
  153.   }

  154.   BlockID allocateNewBlock() override {
  155.     return meta_data_->alloc();
  156.   }

  157.   void writeData(const BlockID block_id, const void *data) override {
  158.     std::memcpy(blocks_ + block_id, data, kBlockSize);
  159.   }

  160.   void deleteBlock(const BlockID block_id) override {
  161.     meta_data_->free(block_id);
  162.   }

  163. private:
  164.   void *stream_;
  165.   std::unique_ptr<MetaData> meta_data_;
  166.   Block *blocks_;
  167. };


  168. int main(int argc, char *argv[]) {
  169.   std::unique_ptr<StorageManagerInterface> storage_manager;

  170.   storage_manager = std::make_unique<StorageManager<ByteArrayMetaData>>();
  171. //  storage_manager = std::make_unique<StorageManager<BitVectorMetaData>>();
  172. //  storage_manager = std::make_unique<StorageManager<FreeListMetaData>>();

  173.   BlockID b1 = storage_manager->allocateNewBlock();
  174.   std::cout << "alloc b1 = " << b1 << "\n";

  175.   BlockID b2 = storage_manager->allocateNewBlock();
  176.   std::cout << "alloc b2 = " << b2 << "\n";

  177.   BlockID b3 = storage_manager->allocateNewBlock();
  178.   std::cout << "alloc b3 = " << b3 << "\n";

  179.   storage_manager->deleteBlock(b2);
  180.   std::cout << "delete b2\n";

  181.   BlockID b4 = storage_manager->allocateNewBlock();
  182.   std::cout << "alloc b4 = " << b4 << "\n";

  183.   BlockID b5 = storage_manager->allocateNewBlock();
  184.   std::cout << "alloc b5 = " << b5 << "\n";

  185.   return 0;
  186. }
复制代码



评分

参与人数 2大米 +11 收起 理由
AnthonyNeu + 10 给你点个赞!
xinxinzhenbang + 1 写的真是好

查看全部评分

回复

使用道具 举报

🔗
123的树 2017-12-4 09:24:48 | 只看该作者
全局:
楼主,746是哪一题呀?还有这个岗位有问一些os之类的问题吗
回复

使用道具 举报

全局:
老哥能不能分享下timeline啊
回复

使用道具 举报

🔗
zhangxiangyu7 2017-12-8 06:05:55 | 只看该作者
全局:
123的树 发表于 2017-12-4 09:24
楼主,746是哪一题呀?还有这个岗位有问一些os之类的问题吗

笑了 楼主指的是期食溜 我一上来也蒙住了
回复

使用道具 举报

🔗
yikehongxin 2017-12-8 06:53:23 | 只看该作者
全局:
楼主,请问有总结好的面经么?如果有,能开个帖子发出来么?我给你加米
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表