-
2018-11-17 22:27:40
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow
也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!
产品部和业务部门是什么关系
“我们来自五湖四海,出身于不同的领域,我们拥有各自独到的技能,但我们为了同一个目的走到一起,为了创造出伟大的产品,这,就是我们,就是我们产品经理存在的意义。”
快12点的时候,亮仔突然站起来,说为了缓解一下大家工作的辛苦,为午饭开开胃,当然,最主要的还是为了对昨天的事情表示歉意,因此,即兴创造了一首小诗,反正也没等大家同意就把这首诗念了出来。
周扬听完后,笑着说:“亮仔,没想到你不但程序写得好,在文学造诣上还有两下子啊,是自己写的吗?”
亮仔得意地说:“扬哥,你说呢?大学时为了保证我知识上的平衡,实现文理通吃,我选修了近现代文学,还经常去蹭中文系的课,比如那个沈从文,老舍,艾青,朱自清等,他们的大作我都通读过的,个人感觉我还是有些造诣的……”他还故意把“的”字拉长音,自然是引来包括刘宇在内的一阵笑声。
虽然说昨天刘宇和亮仔闹了不愉快,但都是年轻人,哪有那么多疙瘩解不开。
“要说文学,我看咱们这五个人里,还只有小娟能拿得出来,毕竟是中文系毕业的,小娟,评论一下亮仔的诗!”周扬笑咪咪地看着小娟。
“亮仔的这个作品,想要表达的内容已经有了,所要体现的主旨也蕴含在内,就是在收尾的时候缺乏些气概,整体来说,就是因为朗诵者缺乏真情实感,本来应该是真情实意的一首诗,却弄巧成拙,成了无病呻吟。”
小娟说完,亮仔一下子就窜到了小娟面前:“娟子,要不你和周扬来个男女诗朗诵,郎才女貌,我看行,哈哈哈哈!”
小娟脸一下子就红了,追着亮仔就跑出去了。
周扬看看我们,意思是别听亮仔瞎说啊,我心想,你就别此地无银三百两了,看来你和小娟的关系早已是公开的秘密了。
“周扬,我想昨天你肯定是跟亮仔说什么了吧?”刘宇问周扬。
“也没说什么,就是要他顾全大局,他是公司的老员工,更应该知道和理解一个新建部门最需要的是团结,刘宇,他是我一手带起来的,他的脾气性格我知道,他就是那种有一说一的家伙,有时候韩总还得让着他,但是人很踏实,也喜欢帮助人,你别往心里去啊!”
刘宇笑笑:“你看我是那样的人吗。”
“那就好,呵呵!”
按照产品部的规矩,有新人入职,第一顿午饭一定是要由周扬来请的,但是亮仔的情况确实特殊,说是新人吧,事实上人家在公司已经待了5年了,说不是新人吧,又确实是在产品部第一天正式工作,周扬死活说亮仔不是新人,就不用按规矩来了吧,我和刘宇则不依不饶,这几天午饭尽凑合了,反正我是缺油水了,正好逮住这个机会狠狠宰周扬一顿。
亮仔倒是不参与是否需要请客的讨论,就是翻着菜谱,自言自语道:“嗯,要点就点几个硬菜,扬哥请客,难得!”
周扬最终还是请了客,看着他付账时一脸的痛苦,我知道周扬又得吃好几天方便面了。
“各位,咱们产品部增加了亮仔,算是如虎添翼,RA计划可以更好地完成了,我重新调整一下啊,I产品线交给亮仔负责,这样公司的四条产品线就各有其人了,希望接下来咱们再接再厉把RA计划完成得漂漂亮亮的。”
“接旨!”亮仔乐呵呵地应道,看样子他丝毫没觉得有压力。
不知道是亮仔的能力确实很强,还是他借助着两台超级电脑的优势,不到四点的时候,他就跳起来,嚷嚷道:“各位,我已经完成了I产品线三个产品的分析方案,咱们讨论一下啊!”
我,周扬,刘宇,包括小娟,四个人的头齐刷刷地抬起来,眼睛中难得一致地出现疑惑和惊奇的神情。
国庆结束到今天,我们三个做了两天,也仅仅完成个框架,你才不到三小时,就完成了方案,如果真是这样,四条产品线让你一个人负责就都搞定了。
“来,咱们看看亮仔的方案。”周扬招呼大家凑到亮仔的工位前。
亮仔有些得意,摇头晃脑地说道:
“我大致是从四个阶段来对每一个产品进行评估的。
第一阶段:规划阶段,主要的目的就是针对要评估的产品确定好相关的文档和规范,以及各种资料的准备。
第二阶段:评估阶段,根据第一阶段的准备就每一个产品在安装卸载、界面、操作流程、产品功能、产品性能和辅助应用这6个方面进行评估,并收集数据,得出结论。
第三阶段:修正阶段,根据第二阶段得出的结论提出改进建议,并基于建议完成对被评估产品的完善。
第四阶段:确认阶段,根据修改后的结果确认被评估产品是否达到了我们期望的目标。
嗯,大致就是这样,如果我这个方案可以,我马上就进入方案实施阶段。”
“稍等,稍等,我仔细想想。”周扬低着头琢磨起来。
过了一会儿,周扬抬起头说道:“亮仔,你忘了昨天我对你说的,我们要从市场、客户、竞争者和自身四个方面来做全面评估吗,你这个方案只涉及对自身产品的评估,并且还不全面,除了评估产品本身外,还要从市场占有率、销量和收入上来评估!”
“你昨天说的,我都记得呢,但是我总感觉这些数据应该是销售部门来完成的,咱们只做好产品本身的数据分析就可以了。”亮仔停了一下,“再说,咱们做产品还需要考虑这些吗?”
周扬笑笑,“我刚到产品部的时候也是这个想法,很正常,不过我现在知道了,研发所理解的产品和产品部要管理的产品还真有很大的不同,这样吧,亮仔,你和小娟去趟销售部,和他们沟通一下,看能给咱们些什么支持。”
亮仔一拍胸脯:“没问题,娟子,走!”
周扬,刘宇和我,对视一笑,又回到自己的座位上,继续工作。
大概过了一小时,就听见走廊里吵吵闹闹的,声音越来越近,很明显,是朝产品部来的,其中一个声音明显是亮仔的,还有一个男人的声音,其中还夹杂着一个小女生的声音,好像是在劝架。
我们正在纳闷,门一开,进来三个人,为首的是亮仔,后面跟着一个30来岁的胖子,戴眼镜,名牌商务衬衣,没打领带,皮鞋的亮度和亮仔的脑袋有一拼,最后面进来的是小娟,边走还边说:“何必呢,为这点事也吵,非要找你说个清楚。”说着,就看了一眼周扬,明白了,这是来找周扬告状的。
“哟,这不是王哥吗,难得,有事吗?”周扬赶忙站起来,边打招呼边让座。
“周扬,就算是叫老王来产品部,也至于让亮仔用这种方式吧?”这个自称老王的胖子看来来者不善,言语中处处都是不满。
周扬虽然知道了来者不善,却不明白为什么来者不善:“王哥,亮仔刚才去销售部怎么了?”
“你问他!”老王就抛出一句话,然后往口袋里伸,抽烟的人很熟悉这个动作,这是告诉你,我懒得回答,先抽支烟再说。
周扬当然不会陌生了,马上掏出自己的点8:“王哥,来,抽我的。”
姓王的胖子也不客气,抽出一支,点上,然后看着周扬。
“怎么回事,亮仔?”周扬故作生气地问道。
“你问小娟!”亮仔也不是吃素的,意思是我也懒得说,于是也从周扬的烟盒里抽出一支烟,歪着脑袋抽了起来。
周扬先把这两位气冲冲的大爷招呼坐下,然后问小娟:“小娟,怎么回事?”
小娟一看几大烟鬼都开始喷云吐雾了,连忙把窗户都打开,坐在周扬的位子上开始述说缘由。
“我和亮仔来到销售部,考虑到这件事情应该直接和销售部的总监说,因此就找到王总。”
哦,原来这个姓王的胖子是销售部的总监。
“我们把RA计划的情况跟王总介绍了一下,王总很支持这个计划,然后我们就提出需要销售部提供相关产品的销售数据来支持产品的评估,可是王总一听需要提供销售数据就说,销售数据是公司的商业机密,只有销售部有权管理,产品部把产品的功能什么的设计好就行了,考虑销售方面的事情做什么,退一万步讲,就算是把销售数据给了你们,你们看得懂吗?这时,亮仔就不高兴了,和王总争吵了起来,说产品经理是需要从整体来考虑产品的,自然需要销售层面的支持,你们销售部不提供支持,就是不支持产品部的工作。王总一听也生气了,说我就是不支持了,怎么地,你们产品部算什么,产品经理算什么,公司以前没产品部不也照样发展,但是没了销售部,公司这小500人都得去喝西北风!就这样,一来二去就吵起来了,最后王总非要找你说清楚,就是这么回事。”
明白了,是王胖子对产品部、产品经理不屑的言语刺激了亮仔,如果换作我,可能不会发生这样的事情,至少不会闹到周扬这里,但是现在是亮仔,这一切就很正常了。
“哦,就是这么回事呀,亮仔,你也是的,多大点事,至于和王哥闹成这样吗,咱们产品部刚成立不久,连人员都没配置齐呢,一个新部门,肯定有许多部门的同事不熟悉,不知道咱们产品部是干什么的,有些不理解也是正常的,亮仔,你和王哥说清楚不就行了,这也是宣传咱们产品部的一个机会嘛,可你竟然因为王哥的不了解就吵了起来,有没有一个做产品经理的素质?”
我心里暗笑,这哪是批亮仔呢,分明是批这个王胖子呢,尤其是最后一句话,言外之意是产品经理的素质应该比你这个销售总监的素质要高得多。
“王哥,既然你来了,正好借这个时机,咱们聊聊产品部的事情,你也帮哥们儿出出主意,看怎么能让产品部和销售部有效配合起来。”周扬在公司内的面子看来是真大,像销售部这样通常是很张扬的一个部门,尤其是销售部的总监更是气势压人,但是在听了周扬的要求后,“哼哈”了一会儿,也就同意了。
“王哥,我们产品部离不开你们销售部的大力支持,这一点是毋庸置疑的!”周扬先给王胖子戴了一顶高帽。
王胖子“哼”了一声,讽刺道:“抬举销售部了,谁不知道你们产品部是韩总眼里的宝贝,连你都被调到产品部了,可见你们在韩总心目中的地位。”
“我那是在研发部混不下去了,呵呵,王哥,说实话,真的,我想了解一下,你们销售部,或者就说你个人吧,是怎么理解产品部的工作的?”
“产品部还不简单,不就是为公司设计产品的吗,技术的东西我不懂,不过我就奇怪了,以前没产品部,咱们不也照样做好产品吗?”
“您还真问到关键点上了,产品部还真不是简单地设计产品的。”
“那是什么?”
“我举个例子,比如说公司要上一个新产品,全新的产品啊,按照以前的做法,就是有了想法,然后内部讨论一下,定下来然后就开始做了,至于产品最终做成什么样,咱们都是走一步看一步做一步,以前这种方式还行,但是现在你也看到了,市场竞争越来越激烈,咱们公司要想发展得更好,实现公司的愿景,怎么办,产品少的时候好办,韩总一个人就盯过来了,但是现在咱们公司上市的就10个产品,韩总再有精力,也不可能做到面面俱到。怎么办?通行的做法就是实施产品管理制度,每一个产品经理就如同韩总在某个产品上的代理人,通过产品经理的工作来实现公司产品的有序和良性发展,其实就是这么个简单道理。”
“那你的意思是,产品经理在公司内和韩总有一样的权力了?”王胖子首先想到了权力分配。
“这恰恰是产品经理和韩总最大的区别所在,韩总是老大,他想要公司什么数据都能拿到,是吧,但是产品经理就不是这样了,没权啊,那怎么开展工作呢?只能靠公司各部门的兄弟姐妹们多多理解,多多支持了,是不是?”周扬又递给王总一支烟,自己也点上了一支。
“这倒是,但是怎么支持呢?”王总深吸了一口,吐着烟圈问道。
“这就涉及产品部和其他部门的工作关系了”,周扬拿出一张纸,一支笔,“我来画个图说明一下啊。
我们知道,企业在商业运作过程中,其实就是围绕以下四类信息做出决策的。
1)II:industryinformation,产业信息。
2)MI:marketinformation,市场信息。
3)BI:businessinformation,商业信息。
4)RI:requirementsinformation,需求信息。
那好,以前的情况是什么呢?两种:
1)信息分割:无论是哪类信息,在商业决策的过程中都应该是完整的,但是以前我们因为企业结构的问题而使这些信息在流转过程中被分割了。当然,这种分割不是说是某个人故意这么做的,这样,结果就可想而知了,决策首先要的是信息的真实和完整,但现实是我们许多公司都在依赖分割的信息做决策,这能做出什么样的正确决策呢?是吧,王哥。
2)信息过滤:一个公司内有很多部门,每个部门只会关注和他有关的信息,把和他无关的信息过滤掉,这样造成的直接后果就是许多可能有助于做出决策的信息要么根本看不到,要么就是被缩小到不值一提,这对于做出正确的决策同样是非常不利的。
怎么办呢?通过一个专门的部门来负责这些信息的输入、处理和输出,哪个部门来做呢?不就是我这个产品部嘛。”
“你的意思是说,产品部就是一个公司内负责汇集各类和市场、产品、客户有关的信息,并基于这些信息做出评估和方案,为老大们提供决策建议的部门?”
周扬一拍王胖子的肩膀,乐呵呵地说道:“就是这个意思!但是,王哥,产品部要真正起到这个作用,离不开各个部门的支持,尤其是各位老大们的支持呀。”
“何以见得?”
“产品部要处理的信息从哪里来?靠自己去收集,你看看,咱们产品部一共就6个编制,连你们销售部的十分之一都不到,靠谁?只能靠各个部门给产品部输送弹药了。比方说吧,产品部要制订新产品的发展计划,第一步是什么,肯定是要知道市场上到底需要什么样的产品,是吧,就是要知道市场上有什么需求是我们可以满足的,对吧?”
“那是自然。”
“谁和市场接触得最多?谁和客户接触得最频繁?毫无疑问,就是咱们销售部呀,你们把客户反映出来的问题,提出的意见,提供的建议告诉我们,我们经过分析后知道客户有什么需求,当然这还不行,还要知道我们能不能做,能做到什么程度,就又得和研发部在技术上进行评估,还要根据客户的特点,设计价格策略、渠道策略什么的,最终上市的时候,我们还得配合你们进行产品销售、解答客户问题,是不是呢?”
王胖子点点头:“嗯,还真是这样。”
“归根结底,产品部和其他部门就好比鱼和水,产品部的生存离不开各个部门的支持,而产品部的工作则是为了让各个部门工作得更好,是互相支持,相辅相成的关系。”
“明白了,周扬,看来产品部的工作不轻松啊,刚才听亮仔说,你们这两天为RA计划累得够戗,注意身体啊,我还有些事,得先告辞了,至于配合的事情,我看咱们最好商量个流程和规范,别搞得乱七八糟的,我也不好交代。”
“那是当然,我这就考虑一下具体怎么接口。”
“对了,别搞得太复杂啊,我这人就喜欢简单利索!”王总走到门口,扭过头对周扬又嘱咐了一句:“周扬,知道你做事认真,但是也别太玩命了,我这里有一条客户送的中南海,红盒的,一会儿你过来拿一下,注意身体啊!”
我们几个差点晕掉!
APAO Say:
关于产品部和其他业务部门之间应该是一种什么样的关系,我看就不用说得那么复杂了,周扬已经总结得很到位了:
归根结底,产品部和其他部门就好比鱼和水,产品部的生存离不开各个部门的支持,而产品部的工作则是为了让各个部门工作的更好,是互相支持,相辅相成的关系。
如果哪位朋友还没有搞明白这种关系,请电联周扬,手机号找我要。
本文选自《YES!产品经理》一书。
图书详细信息:http://blog.csdn.net/broadview2006/article/details/6873929
给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
更多相关内容 -
jemalloc 内存分配器 是什么
2021-08-04 13:39:40jemalloc 内存分配器 是什么? 内存池 所谓内存池,是指应用程序向操作系统(或 JVM)申请一块内存,自己管理这一块内存,对象的创建和销毁都从这块内存中分配和回收,这么一块内存就可以称作内存池, 对应地,管理...jemalloc 内存分配器 是什么?
内存池
所谓内存池,是指应用程序向操作系统(或 JVM)申请一块内存,自己管理这一块内存,对象的创建和销毁都从这块内存中分配和回收,这么一块内存就可以称作内存池,对应地,管理这块内存的工具就称作内存分配器。
同时,对于申请对象的不同又可以分为堆内存池和直接内存池,
1 如果是向 JVM 申请的内存,那就是堆内存池,
2 如果是向操作系统申请的内存,那就是直接内存池。那么,有哪些内存分配器呢?
业界比较著名的有三个内存分配器:
1 ptmalloc,Doug Lea 编写的分配器,支持每个线程(per-thread,简称 pt)的 arena,glibc 的默认分配器。
Doug Lea 大神还有个分配器叫作 dlmalloc,dl 即其名之缩写。
2 tcmalloc,Google 的分配器,它加入了线程缓存(thread cache,简称 tc),Google 声称其比 ptmalloc 快 6 倍。3 jemalloc,Jason Evans 的分配器,je 即其名之缩写,借鉴了很多 tcmalloc 的优秀设计,声称比 tcmalloc 更快,且 CPU 核数越多优势越大,当然,算法也更复杂。
目前,jemalloc 已经广泛运用在 facebook、Mozilla、FreeBSD 等公司的产品上,那么,它有怎样的优势呢?
简单总结一下,主要有三大优势:
1 快速分配和回收
2 内存碎片少
3 支持性能分析当然了,以上说的都是原生的 jemalloc,我们今天要讲的是 Netty 中的 jemalloc,它是原生 jemalloc 在 Java 中的一种实现方式,并根据 Java 语言自身的特点做了一些删减和优化。
我们先从宏观方面对 Netty 中的内存池有个全面的了解,在 Netty 中,主要包含上面这些组件:PoolArena
PoolChunkList
PoolChunk
PoolSubpage
PoolThreadCachePoolArena
根据内存方式的不同,PoolArena 分成 HeapArena 和 DirectArena 两个子类,在创建 PooledByteBufAllocator 的时候会分别初始化这两种类型的 PoolArena 数组,数组默认大小为核数的 2 倍,同时也会根据可以使用的内存大小动态调整。
public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
private final PoolArena<byte[]>[] heapArenas;
private final PoolArena[] directArenas;
}核数也可以通过 JVM 启动参数 io.netty.availableProcessors 配置,因为如果使用低版本的 JDK 且部署在 docker 容器中,获取的是主机的核数,而不是 docker 容器分配的核数。
PoolArena 中存储着 2 种类型的数据结构,分别为 2 个 PoolSubPage [] 数组和 6 个 PoolChunkList:
abstract class PoolArena<T> implements PoolArenaMetric { private final PoolSubpage<T>[] tinySubpagePools; private final PoolSubpage<T>[] smallSubpagePools; private final PoolChunkList<T> q050; private final PoolChunkList<T> q025; private final PoolChunkList<T> q000; private final PoolChunkList<T> qInit; private final PoolChunkList<T> q075; private final PoolChunkList<T> q100; }
为什么这么复杂呢?一切都是为了更好地利用内存。
实际上,所有的数据都存储在叫作 PoolChunk 的对象中,默认每个 PoolChunk 可以存储 16MB 的数据(chunkSize),每个 PoolChunk 内部又使用伙伴算法将这 16MB 拆分成 2048 个 Page,每个 Page 的大小(pageSize)为 16MB/2048=8KB。
如果分配的内存(规范化后的内存)小于 8KB,则把 Page 拆分成更小的内存块,并使用 PoolSubpage 管理这些更小的内存,每个 Page 的拆分标准根据这个 Page 首次被分配时的请求的大小决定:
1 如果小于 512B,则按照 16B 规范化,比如请求的大小为 30B,则规范化到 32B,然后 PoolSubpage 中的元素大小就是 32B,那么,这个 Page 就被拆分成了 8KB/32B=256 个更小的内存块。
2 如果大于等于 512B,则按照 512B*(2^n) 规范化,比如请求的大小为 996B,那就规范化到 1024B,也就是 1KB,然后这个 Page 就被拆分成了 8KB/1KB=8 个更小的内存块。
如果分配的内存大于等于 8KB,且小于等于 16MB,则按照 Page 的大小,也就是 8KB,进行规范化,然后再根据伙伴算法的规则进行内存的分配,什么是伙伴算法呢?我们待会讲。
如果分配的内存大于 16MB,则按照非池化的方式分配内存。
所以,为了区分以上几种情况,Netty 中定义了一个 SizeClass 类型的枚举,把这几种情况分别叫作 Tiny、Small、Normal、Huge,其中 Huge 不在这个枚举中。
对于 Tiny 和 Small 类型,Netty 为了快速定位,定义了两个数组放在 PoolArena 中,分别是 tinySubpagePools 和 smallSubpagePools,它们的大小分别为 32 和 4,如果这两个数组对应的位置有值,说明之前出现过相同大小的内存块,那就快速定位到那个 PoolSubpage,使用它直接分配内存,而不用再从头查找,加快分配内存的速度。前面我们说了,实际上,所有的数据都位于 PoolChunk 中,为了更好地管理这些 PoolChunk,Netty 将它们以双向链表的形式存储在 PoolChunkList 中,同时 PoolChunkList 本身也以双向链表的形式呈现。
在 PoolArena 中,定义了 6 个 PoolChunkList,分别是 qInit、q000、q025、q050、q075、q100,Netty 根据 PoolChunk 的使用率将它们放到不同类型的 PoolChunkList 中,它们代表的使用率分别为:
qInit,内存使用率为 Integer.MIN_VALUE ~ 25%,当然不可能有负的使用率,所以最小应该是 0
q000,内存使用率为 0 ~ 50%
q025,内存使用率为 25% ~ 75%
q050,内存使用率为 50% ~ 100%
q075,内存使用率为 75% ~ 100%
q100,内存使用率为 100% ~ Integer.MAX_VALUE,当然不可能有超过 100% 的使用率,所以最大应该是 100%举个例子来说明,比如一个 Chunk 首次分配了大小为 512B 的内存,那么它的内存使用率就是 512B/16MB 不足 1%,向上取整为 1%,初始时放在 qInit 中,当其分配的总内存超过了 4MB 的时候,也就是达到 25% 了,这个 PoolChunk 就被移动到 q000 中,同样地,当其分配的内存超过 8MB 的时候,就移动到了 q025 中。反过来也是一样,当有对象释放内存时,这部分内存又会被回收到 PoolChunk 中待分配,这时候内存使用会降低,当降低到 4MB 时,也就是 q025 的下限,则会将这个 PoolChunk 移动到 q000 中。
PoolChunkList
正如前面所说,PoolChunkList 就是相近内存使用率的 PoolChunk 的集合,这些 PoolChunk 以双链表的形式存储在 PoolChunkList 中,而 PoolChunkList 本身也以双向链表的形式连在一起,为什么要以双向链表的形式存在呢?
其实,这包含两个问题:
1 PoolChunk 以双向链表的形式存在,是为了删除元素(移动 PoolChunk)的时候更快,比如,要删除 chunk2,只要把它的 prev 和 next 连一起就行了,时间复杂度更低;
2 PoolChunkList 以双向链表的形式存在,是为了让 PoolChunk 在 PoolChunkList 之间移动更快,比如,一个 PoolChunk 不管是从 q025 到 q050,还是从 q050 回到 q025,都很快,时间复杂度都很低;另外,在 Netty 中,当分配内存时,优先从 q050 中寻找合适的 PoolChunk 来分配内存,为什么先从 q050 开始呢?
private void allocateNormal(PooledByteBuf<T> buf, int reqCapacity, int normCapacity) { if (q050.allocate(buf, reqCapacity, normCapacity) || q025.allocate(buf, reqCapacity, normCapacity) || q000.allocate(buf, reqCapacity, normCapacity) || qInit.allocate(buf, reqCapacity, normCapacity) || q075.allocate(buf, reqCapacity, normCapacity)) { return; } // 省略其它代码 }
因为 q050 中的 PoolChunk 的内存使用率都比 50% 多一点,这样更容易找到符合条件的 PoolChunk,又不至于使 PoolChunk 的利用率偏低。
因为 q050 中的 PoolChunk 的内存使用率都比 50% 多一点,这样更容易找到符合条件的 PoolChunk,又不至于使 PoolChunk 的利用率偏低。
我们举个例子,假如从 q075 中先寻找,如果要分配 4M 以上的内存就无法找到合适的 PoolChunk;假如从 q025 中先寻找,可能正好有内存使用率在 25% 以上的 PoolChunk,这时候就直接使用了,那么 q050 中的 PoolChunk 就很难被利用起来,也就是 q050 中的 PoolChunk 的剩余空间很难被利用起来,进而导致整体的利用率偏低,也就是内存碎片会变高。
那么,如果先从 q050 寻找合适的 PoolChunk 呢?这时 q025 和 q075 中的 PoolChunk 可能永远都不会被使用到,不过没关系,对于 q025 中的 PoolChunk 的内存使用率变为 0 的时候,它们自然就被释放了,而 q075 中的 PoolChunk 本身内存使用率就已经很高了,不用到它们反而更好,等它们的内存使用率降低的时候就又回到 q050 中了,此时就又来很容易地被利用起来。
因此,从 q050 开始寻找,能很大程度上增大整体的内存使用率,降低内存碎片的存在。
PoolChunk
前面我们说了,默认地,一个 PoolChunk 可以存储 16MB 的数据,PoolChunk 是真正存储数据的地方,何以见得?final class PoolChunk<T> implements PoolChunkMetric { // 数据存储的地方 final T memory; // 满二叉树对应节点是否被分配,数组大小为4096 private final byte[] memoryMap; // 满二叉树原始节点高度,数组大小为4096 private final byte[] depthMap; // 管理更小的内存,数组大小为2048 private final PoolSubpage<T>[] subpages; // 剩余的内存 private int freeBytes; PoolChunk<T> prev; PoolChunk<T> next; }
PoolChunk 本身是一个泛型类型,内部保存了一个叫作 memory 的变量,这个 memory 会根据分配的是堆内存还是直接内存而变换类型:
对于堆内存,memory 的类型为 byte []
对于直接内存,memory 的类型为 ByteBuffer,实际上为 DirectByteBuffer。所有的数据都存储在 memory 中,至于更小粒度的划分,比如 PoolSubpage,它们使用各种偏移量对 memory 进行分段处理,数据本身并不会复制到这些细粒度的类中。
在 Netty 中,并没有 PoolPage 或者 Page 这个类,Page 是一种抽象的说法, 它表示的是 PoolChunk 中每 8KB 的数据块,它同样使用 PoolSubpage 来表示。
默认地,Netty 使用伙伴算法将 PoolChunk 分成 2048 个 Page,这些 Page 又向上形成一颗满二叉树:
结合上图,我们先来简单介绍一下 PoolChunk 中的几个变量:depthMap,保存着满二叉树原始的高度信息,比如 depthMap [1024]=10
memoryMap,初始值等于 depthMap,随着节点的被分配,它的值会不断变化,更新子节点的值时,会同时更新其父节点的值,其父节点的值等于两个子节点值中的最小者。
subpages,对应于上图中的 Page0、Page1、…、Page2047,在 Netty 中并没有 Page 的具体代码实现,它同样使用 PoolSubpage 来表示。只有分配的内存小于 8KB,才会使用 PoolSubpage 进行管理,在 PoolSubpage 创建之后,会加入到 PoolArena 中 tinySubpagePools [] 或 smallSubpagePools [] 对应位置的链表中,同时,在 PoolSubpage 代表的内存被分配完之后,会从对应的链表中删除,也就是说,在同一时刻,head 最多只会与一个 PoolSubpage 形成双向链表。
freeBytes,PoolChunk 中剩余的内存,即可被使用的内存。
如果分配的内存大于等于 8KB,由 PoolChunk 自己管理。
为了更好地理解伙伴分配算法,我们来假想一种分配内存的情况,如果分配内存的顺序分别为 8KB、16KB、8KB,则会按以下顺序进行:
8KB,符合一个 Page 大小,所以从第 11 层(12-8KB/8KB)寻找节点,这里找到了 2048 这个节点,发现其 memoryMap [2048]=11=depthMap [2048],可以被分配,然后到其对应的 Page [0] 中分配内存,分配之后将其 memoryMap [2048]=12,memoryMap [1024]=11=(2048 和 2049 中的最小者 11),memoryMap [512]=10=(1024 和 1025 中的最小者 10),…,memoryMap [1]=1;
16KB,符合两个 Page 大小,所以从第 10 层寻找节点(12-16KB/8KB),找到 1024 节点,发现其 memoryMap [1024]=11!=depthMap [1024],不符合条件,继续寻找到 1025 节点,发现其 memoryMap [1025]=10=depthMap [1025],符合条件,所以,到其对应的叶子节点 2050/2051 对应的 Page [2]/Page [3] 中分配内存,分配之后 memoryMap [2050]=12,memoryMap [2051]=12,memoryMap [1025]=12=(2050 和 2051 中的最小值 12),memoryMap [512]=11=(1024 和 1025 中的最小者 11),…,memoryMap [1]=1;
8KB,符合一个 Page 大小,所以从第 11 层(12-8KB/8KB)寻找节点,2048 已经不符合条件了,所以找到了 2049 这个节点,到其对应的 Page [1] 中分配内存,然后更新 memoryMap [2049]=12,memoryMap [1024]=12=(2048 和 2049 中的最小者 12),memoryMap [512]=12=(1024 和 1025 中的最小者 12),…,memoryMap [1]=1;
至此,三次内存都分配完毕,总共分配了 Page0~Page3 共 4 个 Page,从分配结果也可以看出,使用伙伴分配算法,能极大地保证分配连续的内存空间,并减少内存碎片的诞生。
PoolSubpage
前面我们说过,只有当分配的内存小于一个 Page 大小,即 8KB 时,才会使用 PoolSubpage 来进行管理,那么它是怎么管理的呢?让我们先来看看它的几个关键字段:
final class PoolSubpage<T> implements PoolSubpageMetric { // 对应满二叉树中的哪个节点 private final int memoryMapIdx; // 在PoolChunk的memory中的偏移量 private final int runOffset; // 表示每个小块的状态 private final long[] bitmap; // 每个小块(元素)的大小 int elemSize; // 最大的元素个数=8KB/elemSize private int maxNumElems; // 需要使用到几个long private int bitmapLength; // 可用的元素个数 private int numAvail; // 双向链表的指针 // 与PoolArena中的tinySubpagePoos或smallSubpagePools中的元素形成双向链表 PoolSubpage<T> prev; PoolSubpage<T> next; }
elemSize 表示每个元素的大小,这个大小是根据这个 Page 接收到的第一个请求的大小决定的。
比如,首次分配 30B 的内存,则会经历以下几个步骤:1判断小于 512B,按 16B 向上规范化到 32B;
2 在满二叉树的第 11 层寻找一个可用的节点,假如是 2049,即 memoryMapIdx=2049,它代表的是 Page1,Page1 这个节点在 PoolChunk 中对应到 memory 上的偏移量就是 8192(前面有个 Page0),所以,runOffset=8192;
3 此时,会把 Page0 按 32B 分成(8KB/32B=256)个小块,所以,elemSize=32B,maxNumElems=256,numAvail=256;
4 同时,这 256 个小块就需要 256 个 bit(位)来表示其每个小块的状态,也就是需要(256/64=4)个 long 类型来表示,所以,bitmapLength=4;
5 然后,把这个 PoolSubpage 与 PoolArena 的 tinySubpagePools [1](相当于 head)形成双向链表,因为 tinySubpagePools [0] 代表的是 16B 的内存,tinySubpagePools [1] 代表的是 32B 的内存;
6 当分配完这 32B 之后,可用节点数减一,所以,numAvail=255;当再次分配规范为 32B 内存的时候,就看 PoolArena 的 tinySubpagePools [1] 的 next 中有没有值,有值,就直接使用其分配内存了,而不用再重新走一遍上面的过程,从而加快分配内存的速度。
PoolThreadCache
前面讲了这么多,分配内存的速度已经足够快了,但是,还可以更快,那就是加入线程缓存 PoolThreadCache,那么,PoolThreadCache 在何时使用呢?其实,这要结合回收内存一起使用,当回收内存时,先不还给 PoolChunk,而是使用本地线程缓存起来,当下一次再分配同样大小(规范化后的大小)的内存时,先尝试从本地线程缓存里面取,如果取到了就可以直接使用了。
那么,PoolThreadCache 可以缓存哪些类型的缓存呢?
在 Netty 中,除了 Huge,其它类型的内存都可以缓存,即 Tiny、Small、Normal,当然,根据堆内存和直接内存的不同,PoolThreadCache 中又分成了两大类:
final class PoolThreadCache { // 堆内存的缓存 private final MemoryRegionCache<byte[]>[] tinySubPageHeapCaches; private final MemoryRegionCache<byte[]>[] smallSubPageHeapCaches; private final MemoryRegionCache<byte[]>[] normalHeapCaches; // 直接内存的缓存 private final MemoryRegionCache<ByteBuffer>[] tinySubPageDirectCaches; private final MemoryRegionCache<ByteBuffer>[] smallSubPageDirectCaches; private final MemoryRegionCache<ByteBuffer>[] normalDirectCaches; }
PoolThreadCache 中使用了一个叫作 MemoryRegionCache 的类来做缓存,它内部维护了一个队列,当回收内存时,这块内存进入到这个队列中,当下次再分配同样大小(规范化后的大小)的内存时,从这个队列中取,关于 PoolThreadCache 的使用,我们下一节结合代码一起学习。
-
【整理】TAC码是什么?TAC码和IMEI有什么关系?
2022-04-02 17:35:58本文整理自多篇互联网文章。 一、TAC是什么? TAC是型号分配码,也是IMEI(国际移动设备识别码)的号头。 TAC可识别设备型号、商标所有者和生产厂商...二、TAC码和IMEI有什么关系? IMEI(International Mobile Equipme本文整理自多篇互联网文章。
一、TAC是什么?
- TAC是型号分配码,也是IMEI(国际移动设备识别码)的号头。
- TAC可识别设备型号、商标所有者和生产厂商
- TAC核发给商标所有者的特定型号产品使用
- 一个TAC仅分配给一个产品型号使用
- 每一款产品型号都应申请新的TAC
- TAC是IMEI的前八位
- 一个TAC可生成100万个IMEI
- 100万个IMEI使用完后,须申请新的TAC
- 仅可使用GSMA核发的TAC
二、TAC码和IMEI有什么关系?
IMEI(International Mobile Equipment Identity)
是国际移动设备身份码的缩写。国际移动装备辨识码,是由15位数字组成的"电子串号",它与每台移动电话机一一对应,而且该码是全世界唯一的。每一只移动电话机在组装完成后都将被赋予一个全球唯一的一组号码,这个号码从生产到交付使用都将被制造生产的厂商所记录。
手机IMEI码由15-17位数字组成。
-
第一部分
TAC
,Type Allocation Code,类型分配码,由8位数字组成(早期是6位),是区分手机品牌和型号的编码,该代码由GSMA及其授权机构分配。其中TAC码前两位又是分配机构标识(Reporting Body Identifier),是授权IMEI码分配机构的代码,如01为美国CTIA,35为英国BABT,86为中国TAF。 -
第二部分
FAC
,Final Assembly Code,最终装配地代码,由2位数字构成,仅在早期TAC码为6位的手机中存在,所以TAC和FAC码合计一共8位数字。FAC码用于生产商内部区分生产地代码。 -
第三部分
SNR
,Serial Number,序列号,由第9位开始的6位数字组成,区分每部手机的生产序列号。 -
第四部分
CD
,Check Digit,验证码,由前14位数字通过Luhn算法计算得出。 -
第五部分
SVN
,Software Version Number,软件版本号,区分同型号手机出厂时使用的不同软件版本,仅在部分品牌的部分机型中存在。
下面是IMEI的组成结构:
三、哪些移动设备需要 TAC?
涉及到无线移动通信的设备均需要申请TAC号。
包含物联网设备、内置式无线数据终端、可穿戴设备、功能手机、智能手机、平板电
脑、外置式无线数据终端、WLAN路由器
四、在其他设备安装物联网内置式无内置式无线数据终端 / 模块时 ,由谁申请 TAC?
内置式无线数据终端/模块生产商均可申请TAC码。
五、物联网设备要何时需要TAC ?
当物联网设备接入蜂窝网络时需要TAC码。
参考链接
-
产品售前与产品经理的关系
2020-09-12 23:50:07所以为了达成这个目标,两个岗位需要做的事情的大块相同,均覆盖产品全链路,不同在于2个岗位精力分配在各个环节是不同的。 一般来说,产品孵化中或还未规模化前,都是不需要产品售前的,其职责均由产品经理承接即可...在一些较大的公司,会设有产品售前的岗位,其不少职责和产品经理是重叠的,那他们2者有何种区别?
维度相同,侧重不同
可以说,产品经理和产品售前,两者的目标是一致的,促成产品的商业目标达成。
所以为了达成这个目标,两个岗位需要做的事情的大块相同,均覆盖产品全链路,不同在于2个岗位精力分配在各个环节是不同的。一般来说,产品孵化中或还未规模化前,都是不需要产品售前的,其职责均由产品经理承接即可。
当产品规模化后,产品经理需要更加聚焦在如下图蓝色的环节,把产品打磨的更有竞争力,巩固市场地位。
而偏市场的工作,则需要专业的产品售前来承接。
总的来说,产品规模化后,需要产品售前、产品经理分工协作,来提升效率。
欢迎关注作者公众号~
-
ATP 和产品分配的用户出口的先后关系列表
2014-09-25 11:32:36最近由于公司希望能用一个灵活而简便的产品分配的方法,我们就不得不考虑用户出口,现将有关的出口做了一个列表供大家参考。表中列出了出口的调用,以及他们的先后关系。 -
什么是C端 什么是B端 这里告诉你
2022-06-02 14:49:09一、C端和B端的定义 先了解一下什么是C端产品和B端产品: C端:Consumer(也可理解为Customer),通常为消费者、个人终端用户使用的客户端。如:微信、淘宝、网易云音乐等。 B端:Business,通常为企业内部或商家... -
EDID是什么,跟显示器有什么关系?
2018-11-07 19:50:25跟显示器有什么关系? EDID名叫扩展显示标识数据,是一种VESA标准数据格式,它包含了关于制造商以及与运行相关的数据,比如供应商信息、最大图像大小、颜色设置、厂商预设置、频率范围的限制以及显示器名和序列号... -
成本归集与分配
2019-04-23 20:32:42一、归集与分配概念 1、成本归集:通过一定的会计制度以有序的方式进行成本数据的收集或汇总。例如制造费用按车间归集。 2、成本分配:将归集的间接成本分配给成本对象,也叫间接费用的分摊。 3、成本的核算... -
灰度测试是什么意思
2021-09-08 07:43:07本文章,百度+论坛+知乎等处查询,了解灰度测试,方便学习。本文章只限学习。文章可能内容多,我进行了网上查询终结,还需细看整理,如有重复内容请见谅,我...灰度测试就是将自己的产品首先拿出来给一部分目标人群使用 -
什么是SoC?什么是IP核?它们有什么关系?
2017-12-19 20:23:121. 什么是SoC SoC(System on a Chip )中文名是系统级芯片。20世纪90年代中期,因使用ASIC实现芯片组受到启发,萌生应该将完整计算机所有不同的功能块一次直接集成于一颗硅片上的想法。SoC应由可设计重用的IP核... -
① 数据库介绍 及 关系型数据库的关系代数表达式
2020-12-20 22:54:51数据库基础数据库介绍数据模型概念模型逻辑模型关系型数据库 写下博客用于自我复习、自我总结。 如有错误之处,请各位指出。 本数据库系列专栏,文章的重心将会是总结SQL语句的使用,而不会涉及到太多数据库本身或... -
信贷系统学习总结(3)——现金贷之产品架构和信审系统
2019-07-10 11:12:26一、产品架构 现金贷前端产品的流程与界面通常比较简单,后端体系与逻辑相对前端会复杂很多,一个相对成熟的现金贷业务的产品架构如下: 从上到下,大致可分为五个模块,模块之间部分重合: 1. 前端产品 产品... -
运营商网络IP地址分配原则
2019-09-25 15:52:26相关文章:你的宽带被运营商偷偷分配了内网IP怎么办?! 不过也可能有人不知道自己到底是不是被分配到了内网IP,我还给大家准备了一个查询 方法: 1、进入IP138网站查询你的IP地址(进入后自动检测,无需操作)... -
关系型数据库与非关系型数据库的对比分析(优缺点,应用,区别等)
2018-08-08 20:57:56当前主流的关系型数据库有Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL等。 非关系型数据库有 NoSql、Cloudant。 ==========================优缺点分析如下================================... -
CRM是什么?CRM客户管理系统主要的功能,作用,特点分别有哪些?
2020-11-11 18:25:19一、CRM是什么? CRM客户关系管理是指企业为提高核心竞争力,利用相应的信息技术以及互联网技术协调企业与顾客间在销售、营销和服务上的交互,从而提升其管理方式,向客户提供创新式的个性化的客户交互和服务的过程... -
商业模式的定义——做产品到底是做什么
2018-10-24 10:30:24商业模式的定义——做产品到底是做什么 商业模式描述了企业如何创造价值、传递价值和获取价值的基本原理。本文将从商业模式的角度出发,探讨做产品到底是做什么这个话题。 产品经理到底是在干什么呢? 这... -
什么是项目管理?怎么管?(一)
2020-04-25 19:43:33前言 项目管理是团队建立共同语言的需要、保证每个项目结果的需要、积累企业过程资产必要,同时还是打造企业...为什么会有项目? 项目就是为进行达到目标的一系列活动的综合概述,即对实现某个目标所要做的事情... -
供应链,产业链,价值链及其之间的关系-商业模式名词解释12-14
2021-04-10 06:20:57是操作层面的概念,对象是服务和产品,是企业在价值链和产业链已经确定的基础之上,对服务和产品的研究。 013 产业链 产业链是产业经济学的范畴,是产业分析领域里的常用术语。是各个产业部门之间基于一定的技术... -
STM32中断优先级的分配以及中断原则
2020-07-08 10:43:25STM32d的中断优先级由NVIC_IPRx寄存器来配置,IPR的宽度为8bit所以原则上每个中断可配置的优先级为0~255,数值越小优先级越高,但对于大部分的 Cortex-M3芯片都会精简设计,导致实际上支持的优先级数量更少。... -
NoSQL与关系型数据库全面对比
2020-09-01 09:56:17我们总在说各种数据库的使用,以及各个数据库的优缺点,每个数据库都有自己的所擅长的领域,但选择什么样的数据库才是重点,那么问题来了,数据库到底是怎么划分的,有什么讲究呢? 数据库大致分为两大类:关系型... -
产品可靠性指标预计
2021-07-23 06:13:49如何达到这一目标值,这就关系到可靠性预计和分配。开展可靠性预计和分配工作,是确保设计、生产“好”产品的指导性和基础性工作。首先将产品可靠性指标自上而下逐级地分配到产品的各个层次,借此落实相应层次的可靠... -
合伙人股权分配,你必须知道的三大要点!
2020-12-24 14:41:51原标题:合伙人股权分配,你必须知道的三大要点!随着社会的发展,越来越多的年轻人选择创业,也有很多人选择...什么是合伙人,谁可以参与初创股权分配?合伙人,通俗的理解就是一起做事的人,在创业层面,理解应... -
一张图讲清楚产品架构,手把手教你画产品框架图
2017-09-17 23:10:50什么是产品架构图 产品架构图是产品经理用来表达自己产品设计机制的一张概念图: 它将可视化的具象产品功能,抽象成信息化、模块化、层次清晰的架构,并通过不同分层的交互关系、功能模块的组合、数据和信息... -
UML各种关系,图的介绍(附加案例)
2019-04-10 21:07:59本篇文章系我总结了网上好多片文章外加自己做图编辑而成,留作自用。...UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现 类与类图 1)类(Class)封装了数据和行为,是面向对象的重要组成部分,它是具有相... -
非关系型数据库 之 图数据库Neo4j的使用(Python3)
2019-06-21 12:04:57文章目录1、Neo4j 简介1.1、简述1.2、应用场景1.3、优点1.4、缺点2、CentOS 操作 Neo4j2.1、安装启动2.1.1、下载2.1.2、修改配置文件2.1.3、查看是否启动2.2、web访问3、Python3 操作Neo4j...在2010年发布,产品的... -
西方经济学中AVC是什么意识?
2021-01-26 16:39:18展开全部平均e68a84e8a2ad3231313335323631343130323136353331333431336135可变成本(Average variable cost)是厂商在短期内平均每生产一单位产品所消耗的可变成本,即平均可变成本是总可变成本除以产量。字母表示为... -
产品读书《B端产品经理必修课:从业务逻辑到产品构建全攻略》
2019-03-28 22:06:441 B 端产品经理 如何理解B端产品? B端产品主要分为两大类: 为公司的管理服务,如:HR系统、OA系统; 为公司的运营服务,如:供应链系统、ERP系统的。 B端产品即要符合商业组织的战略要求,能够满足商业用户... -
常见的几个非关系型数据库(NoSQL)、非关系型和关系型的区别
2018-07-03 09:43:33非关系型数据库的特点 ………………………………………………………………………………….1.关系型数据库 ………………………………………………………………………………………………2. 关系型数据库瓶颈 …………... -
解析:区块链的本质是伴随信息社会产生的一种新型生产关系
2019-08-29 11:02:11最近看了不少关于区块链本质的讨论,大家对区块链本质的理解仁者见仁智者见智。有的说区块链的本质是个不可篡改的数据库,有的说就是个分布式账本,还有的...我们先看百度对生产关系的定义:生产关系是人们在物质资...