53.性能调优之使用 fastutil 优化数据格式
来源:互联网 发布:淘宝apass会员资格 编辑:程序博客网 时间:2024/06/04 23:30
本文为《Spark大型电商项目实战》 系列文章之一,主要介绍在实际项目中使用 fastutil 优化数据格式的方法。
fastutil 介绍
fastutil 是扩展了Java标准集合框架(Map、List、Set;HashMap、ArrayList、HashSet)的类库,提供了特殊类型的map、set、list和queue。
fastutil 能够提供更小的内存占用,更快的存取速度。我们使用fastutil提供的集合类,来替代自己平时使用的JDK的原生的Map、List、Set,好处在于:fastutil集合类,可以减小内存的占用,并且在进行集合的遍历、根据索引(或者key)获取元素的值和设置元素的值的时候,提供更快的存取速度。
fastutil也提供了64位的array、set 和 list 以及高性能快速的,以及实用的IO类来处理二进制和文本类型的文件。fastutil的每一种集合类型都实现了对应的 Java 中的标准接口(比如fastutil的map实现了Java的Map接口),因此可以直接放入已有系统的任何代码中。
fastutil 还提供了一些JDK标准类库中没有的额外功能(比如双向迭代器)。
fastutil 除了对象和原始类型为元素的集合,fastutil也提供引用类型的支持,但是对引用类型是使用等于号(=)进行比较的,而不是equals()方法。fastutil尽量提供了在任何场景下都是速度最快的集合类库。
Spark中应用fastutil的场景
如果算子函数使用了外部变量,那么第一,你可以使用Broadcast广播变量优化;第二,可以使用Kryo序列化类库,提升序列化性能和效率;第三,如果外部变量是某种比较大的集合,那么可以考虑使用 fastutil 改写外部变量,首先从源头上就减少内存的占用,通过广播变量进一步减少内存占用,再通过Kryo序列化类库进一步减少内存占用。
在你的算子函数里,也就是task要执行的计算逻辑里面,如果有逻辑中出现要创建比较大的 Map、List 等集合,可能会占用较大的内存空间,而且可能涉及到消耗性能的遍历、存取等集合操作,那么此时可以考虑将这些集合类型使用 fastutil 类库重写,使用了 fastutil 集合类以后,就可以在一定程度上减少task创建出来的集合类型的内存占用,避免 executor 内存频繁占满,频繁唤起GC,导致性能下降。
fastutil调优说明
fastutil 其实没有你想象中的那么强大,也不会跟官网上说的效果那么一鸣惊人。之前所说的广播变量、Kryo序列化类库、fastutil,对于性能来说类似于一种调味品。分配资源、并行度、RDD架构与持久化,这三个是性能提升最明显的,而broadcast、kryo、fastutil 等类似于调料的作用,起到部分加强提升的功能。
比如说你的spark作业,经过之前一些调优以后,大概30分钟运行完,现在加上broadcast、kryo、fastutil,也许就是优化到29分钟运行完,或者更好一点,也许就是28分钟或25分钟。如果使用shuffle调优或许会降到15分钟;groupByKey用reduceByKey改写,执行本地聚合后也许就10分钟;如果跟公司申请更多的资源,比如资源更大的YARN队列,可能1分钟就可以运行完。
代码实现
第一步:在 pom.xml 中引用 fastutil 的包
<dependency> <groupId>fastutil</groupId> <artifactId>fastutil</artifactId> <version>5.0.9</version></dependency>
(速度比较慢,可能是从国外的网去拉取jar包,可能要等待5分钟,甚至几十分钟不等)
然后修改代码,以“session随机抽取功能”中的List<Integer>
为例,在
final Broadcast<Map<String, Map<String, List<Integer>>>> dateHourExtractMapBroadcast = sc.broadcast(dateHourExtractMap);
之前加上
Map<String, Map<String, IntList>> fastutilDateHourExtractMap = new HashMap<String, Map<String, IntList>>(); for(Map.Entry<String, Map<String, List<Integer>>> dateHourExtractEntry : dateHourExtractMap.entrySet()) { String date = dateHourExtractEntry.getKey(); Map<String, List<Integer>> hourExtractMap = dateHourExtractEntry.getValue(); Map<String, IntList> fastutilHourExtractMap = new HashMap<String, IntList>(); for(Map.Entry<String, List<Integer>> hourExtractEntry : hourExtractMap.entrySet()) { String hour = hourExtractEntry.getKey(); List<Integer> extractList = hourExtractEntry.getValue(); IntList fastutilExtractList = new IntArrayList(); for(int i = 0; i < extractList.size(); i++) { fastutilExtractList.add(extractList.get(i)); } fastutilHourExtractMap.put(hour, fastutilExtractList); } fastutilDateHourExtractMap.put(date, fastutilHourExtractMap); }
然后将
final Broadcast<Map<String, Map<String, List<Integer>>>> dateHourExtractMapBroadcast = sc.broadcast(dateHourExtractMap);
改写为
final Broadcast<Map<String, Map<String, IntList>>> dateHourExtractMapBroadcast = sc.broadcast(fastutilDateHourExtractMap);
在之前改写的广播变量处将
final Broadcast<Map<String, Map<String, List<Integer>>>> dateHourExtractMapBroadcast = sc.broadcast(dateHourExtractMap);
改为
Map<String, Map<String, IntList>> dateHourExtractMap = dateHourExtractMapBroadcast.value();
最后记得在“构建Spark上下文”处的Kryo
中注册 IntList
SparkConf conf = new SparkConf() .setAppName(Constants.SPARK_APP_NAME_SESSION) .setMaster("local") .set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") .registerKryoClasses(new Class[]{ CategorySortKey.class, IntList.class});
至此,使用 fastutil 优化完成。
本文为《Spark大型电商项目实战》系列文章之一,
更多文章:Spark大型电商项目实战:http://blog.csdn.net/u012318074/article/category/6744423
- 53.性能调优之使用 fastutil 优化数据格式
- spark性能调优之使用fastutil优化数据格式
- Spark--性能调优之使用fastutil优化数据格式
- Spark性能调优之——在实际项目中,使用fastutil优化数据格式
- 性能优化-使用高性能的库fastutil
- fastutil介绍以及使用fastutil优化Spark作业
- Android性能优化之三 数据格式优化
- Java集合框架之fastutil
- Android性能优化之虚拟机调优
- Spark性能优化之开发调优
- Spark性能优化之资源调优
- web性能优化之javascript性能调优
- web性能优化之javascript性能调优
- Android性能优化之使用线程池
- Android性能优化之LINT使用总结
- Orcale 性能优化之索引使用
- 性能优化之Traceview工具的使用
- Android性能优化之StrictMode 的使用
- windows logstash cannot find log4j2.properties file
- python中的私有变量
- Protocol 协议
- Oracle数据库中字符串相关字段类型辨析
- call,apply与bind方法的区别
- 53.性能调优之使用 fastutil 优化数据格式
- 线程池ThreadPoolExecutor使用
- http状态码
- Java反射机制
- nslookup 使用方法简介
- linux用rpm命令安装jdk
- 树莓派--开坑
- [多项式] COGS 有标号的二分图计数系列
- Android 开机启动