




























这是一个创建于 2411 天前的主题,其中的信息可能已经有所发展或是发生改变。
在一个面试被问到一个问题:在一个核心入口函数处统计每一个调用方的调用次数,入口函数知道每一个调用方的函数名(NSString *),问题是要怎么统计。
我回答构建一个 NSMutableDictionary<NSString *, NSNumber *>的 static 对象应该就可以解决问题了,用 dispatch_once 保证初始化的线程安全。但是被追问这样的话 NSMutableDictionary 的内存会撑爆,调用量会非常大,怎么优化?
我没答上来,事后也没想明白。内存增大应该是 NSString 的原因,NSNumber 毕竟只是值的变化,能占多少内存。NSMutableDictionary 确实会对 key 进行 copy,我在想什么量级的 NSString 会撑爆内存。
有想法?
1 w99wen 2019 年 11 月 7 日你这个有两个问题, 你的错误想法: 推荐: 现在还有问这个的。有意思。 |
2 w99wen 2019 年 11 月 7 日如果问你的人就只能反问成这样,他水平也一般啊。 |
3 ai277014717 2019 年 11 月 7 日感觉 NSNumber 拆装箱应该也考虑进去 |
4 kera0a 2019 年 11 月 7 日 via iPhone是我没看明白吗? |
5 wutiantong 2019 年 11 月 7 日不懂为啥会撑爆内存,怀疑面试官的水平。 |
6 xingheng 2019 年 11 月 7 日@w99wen 确实想过串行的方法,把初始化和 dict 的操作都挪到串行队列里面去。主要问题还是内存,以我的理解,NSMutableDictionary 在 setValue:forKey:的时候确实会对 NSString \*key 进行 copy,但是这个 copy 不会产生新的内存分配(假定是 inmutable string ),只是把原有的 imutable string's retain count 加 1。上面说 NSMutableDictionary 的撑爆内存其实是指 NSMutableDictionary 持有的 NSString 把内存撑爆了。 这个理解有错误吗?请指正。 写 io 的话也想过,一旦 NSMutableDictionary 的数量级到了某个设定量就写文件,这样的话就还需要再次汇总结果了,可能不符合对方的预期。 这个问题来自蚂蚁金服的面试官。 |
7 xingheng 2019 年 11 月 7 日@kera0a 对方明确说明了调用方数量确实会有很大,我猜测还是 NSString 作为 key 的内存占用量会很大。 也不排除因为他们的 app 在正常运行的时候其他需求上已经占用大量内存了,只是针对或者设计了这样一个问题来优化这个统计结果。 |
8 xingheng 2019 年 11 月 7 日@ai277014717 NSNumber 拆装箱过程中可能会产生局部变量,内存会在每次退出函数的时候就被释放了,我觉得不至于影响 NSMutableDictionary 所持有的内存。 |
9 kera0a 2019 年 11 月 7 日 via iPhone@xingheng 我觉得出题者没考虑实际情况啊 |
10 w99wen 2019 年 11 月 7 日api 的数量会很大的,内存占用就不能小看了。 举个例子,你见过 6000 个会话的用户吗? |
11 w99wen 2019 年 11 月 7 日比如说,你 hook 的 objc_msgsend,统计整个 app 的 api 调用,包括系统底层的调用。那你这个 api 的数量,肯定不能在存内存了。也不能在当前线程操作。 |
14 luopengfei14 2019 年 11 月 7 日 via iPhone大佬好多,曾经的菜鸡 iOSer 觉得 iOS 开发已经配不上这么深入的研究了。不喜勿喷… |
15 hoyixi 2019 年 11 月 7 日这玩意的统计,难道不该实时传给服务器 or 缓存到本地到了一定条件同步给服务器吗,难道要常驻在内存里? |
16 xingheng 2019 年 11 月 7 日简单写一下目前我能想的代码结构再讨论吧 ``` void core_func(NSString *caller) dispatch_async(serialQueue, ^{ if (dict.count > 1000) { url = [url stringByAppendingPathComponent:filename]; if ([dict writeToFile:url atomically:YES]) { ``` |
17 xingheng 2019 年 11 月 7 日@ai277014717 以我的理解,只有给对象发送了 autorelease 消息的对象才会在 autoreleasepool 闭合的时候 release,其他对象还是一直存在的。ARC 下,上面的 url, filename 可以算是 autorelease 对象。 请指正。 |
18 xingheng 2019 年 11 月 7 日@hoyixi 那种存服务器的统计以前我还真写过,就是先写内存然后批量发到服务器,发送失败就临时写文件。但是我觉得面试官在这里应该不是问的一个设计上的问题,还是语言级的内存管理问题。 |
19 samlee123 2019 年 11 月 8 日确实会造成内存暴增,他问的就是 hook msgsend 然后做统计吧 ,调用方法需要开辟方法栈,评论里居然还有人质疑面试官水平。。。。。。🐶 |
20 xingheng 2019 年 11 月 8 日@samlee123 抱歉,是我没有描述清楚。确定不是 hook msgsend,面试官明确说了被调用方知道是谁调用了自己,参见#16 的示例代码。 |
21 ai277014717 2019 年 11 月 8 日@xingheng 除了个别 init copy new 等方法外一般默认都是 autorelease 对象 例如 numberWithInt: |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。