Onelong

分享知识,与你一起进步......
RSS icon Home icon
  • Android 优化

    post by onelong / 2016-12-4 16:44 Sunday [android]
    一直以来都没怎么做android方面的优化,使用的时候时候不卡就算了,也没有一些指标。或者是因为过往项目的缘故吧,总是没有一群专业的人员去测试,甚至只有靠自己去测试。每次面对性能优化的问题,都是没有很明确的指标,随着硬件的升级,其实出现卡顿的时候也会越来越少了,甚至有人去推测,原生迟早被h5替代的,哈哈,这个就是其他问题了。市场需求是多样化的,就像我们常常觉得一个卖二手机平台为什么要自己做,反正目标是卖出更多的手机而已,平台是啥都不重要,例如淘宝,微信等,普遍认为这种二手机平台是没有用户粘性的,买完之后可能一年内都不会再买了,用完即走的意思。可是我在评论上缺看到很多回头客,甚至有人买了8台。无论技术怎样发展,品牌是才是最重要的。技术只是一个工具,工具是否要变革,是市场需求决定的,当手机还在拼命增量的时候,我们就去推断移动互联网已经过去了,大数据来了。其实我们的终端还是在增量,而且没有被替代趋向,我们怎么会觉得Android和iOS就会死掉呢?从过往的我有个想法就差一个程序员,到现在细分,深度垂直发展。我相信对于技术和市场需求的挖掘都是不够的。洗牌之前,我们或许可以看到很多赚快钱的企业,洗牌之后我们只能看到一堆真枪实干的企业。开发者过剩的问题也是同样,由于以前要求过低,入门门槛低,涌入大量开发者,当市场需求趋向饱和的时候,优胜劣汰就来了。
     对于技术,始终要相信“科技是第一生产力”,一个不注重技术或不注重技术变革的企业是走不远的。Google,苹果等就不说了,国内看看阿里,华为。大数据,云平台,人工智能最终展现给用户的是终端,而市场需求总是多样化的。除了工作,我基本不会用到pc,以前有事没事都是大卡pc,二手机浏览器呢,也是同样,在需要百度查资料的时候才会用,而平时都是app。微信和网页是在app基础上多了一种方式而已,并不能说它们是未来,我相信任何人都是一样的,不喜欢只靠着一个大企业而生存,这样没有安全感。所以没有必要去担忧微信未来替代啥啥的,看重大厂app的主要是流量,例如罗一笑事件,就可以理解为什么那么多想赚快钱的人那么喜欢微信了。就像以前经常说的,php弄死了java,可以SOA,微服务又让java火起来了,技术是重要的,也是不重要的。技术作为基础平台,很多时候它的价值是不明显的,也就是这样大家就觉得平台能用就行了。好了,扯了那么多,入正题吧。
    说到android方面的优化,每次我都无奈了,gc优化,内存优化,网络优化,布局渲染优化,动画优化,自定义View优化,电量优化
    等的优化,内存嘛,OOM,对象池,内存泄漏等,通常都会扯到BItmap那一块去的。有时候觉得这方面的东西没什么可说的,java本身有垃圾回收,优化无非就是改变一些不良的习惯,别动不动就用静态,我经常看到静态的Context,Bitmap,甚至是一个集合。我更喜欢用单例,的确单例本质也是静态的,封装成一个对象比例零散的静态变量,在管理上比较方便,生命周期控制上也是会比较方便。经常造成内存泄漏的肯定是我们很熟悉的handler,这个就不用多说了,好的习惯就是在onDestroy时,handler.removeMessageAndCallback(null)。容易出现内存泄漏地方:
    1、静态
    2、
    handler的延时调用
    3、线程
    对应的优化方案就是:少用静态,
    handler.removeMessageAndCallback(null),取消线程,为了加速垃圾回收,我们还可以在onDestroy设置xxObj=null,减少gc,用ArrayMap,对象池,重用,StringBuilder,避免在onDraw方法里面执行对象的创建等主要减少对象数。
    电量用优化主要是在网络,传感器,蓝牙方面,蜂窝数据很费电的,当手机进入后台时,批量操作,延迟操作,为什么呢,启动的过程总是很费电的。传感器的频率调低,甚至关闭。优化关键次:JobScheduler,AlarmManager,网络请求队列,预加载,数据压缩,按场景加载等。充电时操作,用户点亮屏幕时操作,有Wi-Fi时操作,甚至在WiFi,4G,3G等不同的网络下设计不同大小的预取数据量。
    布局渲染优化:布局加载也是需要耗时的,虽然是二进制的xml,说白了就是简化布局,选择合适的布局,简单从效率上来看线性布局和帧布局会比较高效,但是要衡量可读性和可维护性,控制overdraw,overdraw上面大多数减少不必要的背景。建议关键次:Fragment,include,megre,ViewStub。这一块的优化内容很多,也很无奈。我们不能在非主线程上布局和渲染,也不像iOS那样可以监听Runloop推出的事件做后台渲染,android的消息机制和UI无关,所以很难做到平滑16ms,总会加载一个页面时,GPU耗时猛增,我对比了一下淘宝,qq,qq空间等app,都做不到很平滑。overdraw基本都是蓝色,所以我优化的目标也是overdraw蓝色,无色确实比较难做到了,而且也容易出现兼容性问题。至于动画的话,PropertyAnimation,ViewAnimation性能会好些。自定义View的优化,我就不说了,这方面的经验比较少。

    View -> GPU能识别的格式->cache as Display List->GPU Render

    阅读全文>>

  • android找靓机二手手机2.3.0

    post by onelong / 2016-11-20 22:06 Sunday [工作]

    据运维的说已经有50w装机了,不到一年时间。

    点击查看原图点击查看原图点击查看原图点击查看原图点击查看原图

    阅读全文>>

  • 找靓机2.3.0上线

    post by onelong / 2016-11-20 21:41 Sunday [工作]

    折腾了一个月,iOS和android版本,昨天提交审核了。这个改版主要是首页和增加分期支付功能,这期改变比较有意思的是h5拍照上传和选择图库上传。具体也没什么可说的。留几个截屏作为纪念。iOS图

    阅读全文>>

  • iOS和Android事件派发

    post by onelong / 2016-11-20 15:08 Sunday [工作]
    1、点击一下iOS设备的屏幕,硬件产生一个电平变化信号操作系统内核驱动捕捉,通过Event Queue传递到用户态,UIKit就会生成一个事件对象UIEvent
    2、UIKit把这个Event分发给当前活动的app。
    3、当前活动的app有事件之后,UIApplication 单例就会从事件队列中去取最新的事件,然后分发给能够处理该事件的对象。
    4、UIApplication 获取到Event之后,Application就纠结于到底要把这个事件传递给谁,这时候就要依靠HitTest来决定了。
    5、iOS中,hit-Testing的作用就是找出这个触摸点下面的View是什么,HitTest会检测这个点击的点是不是发生在这个View上,如果是的话,就会去遍历这个View的subviews,直到找到最小的能够处理事件的view,如果整了一圈没找到能够处理的view,则返回自身。
    事件传递链如下图:
     点击查看原图
    例如UI显示列表如下:
    <RootView>
        <ViewA>
            
    <ViewC></ViewC>
            <ViewD></ViewD>
        </ViewA>
        
    <ViewB></ViewB>
    </RootView> 
    点击ViewC 打印日志如下:

    RootView hitTest before
    RootView pointInside before
    RootView pointInside return
    VIewB hitTest before
    VIewB pointInside before
    VIewB pointInside return false
    VIewB hitTest return
    ViewA hitTest before
    ViewA pointInside before
    ViewA pointInside return true
    ViewD hitTest before
    ViewD pointInside before
    ViewD pointInside return false
    ViewD hitTest return
    ViewC hitTest before
    ViewC pointInside before
    ViewC pointInside return true
    ViewC hitTest return
    ViewA hitTest return

    RootView hitTest return
    RootView hitTest before
    RootView pointInside before
    RootView pointInside return
    VIewB hitTest before
    VIewB pointInside before
    VIewB pointInside return false
    VIewB hitTest return
    ViewA hitTest before
    ViewA pointInside before
    ViewA pointInside return true
    ViewD hitTest before
    ViewD pointInside before
    ViewD pointInside return false
    ViewD hitTest return

    ViewC hitTest before
    ViewC pointInside before
    ViewC pointInside return true
    ViewC hitTest return
    ViewA hitTest return
    RootView hitTest return

    ViewC touchesBegan before
    ViewA touchesBegan before
    RootView touchesBegan before
    ViewController touchesBegan before
    ViewController touchesBegan return
    RootView touchesBegan return
    ViewA touchesBegan return
    ViewC touchesBegan return

    阅读全文>>

  • golang基础

    post by onelong / 2016-11-18 18:59 Friday [工作]
    1、支持类型推导,不支持继承,重载 ,使用非正式接口,只要实体类实现了接口方法,都是接口的实现类。接口只是作为描述文件。支持struct内嵌。
    2、必任何函数定义必须花括号跟在函数声明后面而不能换行 如 func  name(a int)(int,err){},在Go语言中,函数也是一种类型 可以被推导,使用支持匿名函数和闭包。 函数的返回值支持多重返回 , 如果不赋值,整数类型默认 0,浮点数类型默认0.0,error类型 默认是nil。
    3、不用的包一定不要引入, unused 变量都会被编译器所报错。
    4、package作为引入包用,import "a"  调用包内部的函数 a.xx() 。
    6、CGo是Go语言的一个特性,可方便快速的在Go中调用C。 
    7、go通过goroutine 进行协程优化提高并发性能, 动态线程调整。
    8、6g和6l是64位版本的Go编译器和链接器,对应的32位版本工具为8g和8l。Go还有另外一个 GCC版本的编译器,名为 gccgo。
    9、多个go文件可用同一个包名字, package main的func main()是入口包。
    10、可以var声明变量如var i = 0,局部可用v := 2,但必须赋值。多变量赋值如 x,y int := 1,2 
    11、用struct声明类型,struct里面还可以声明匿名的struct,struct的字段大写开通可认为是public,小写开头是包内访问,方法也是如此。类方法定义: func (*structName) name(a int)(int,err){}
    12、支持指针,支持gc,但不支持指针计算。
    13、常量和枚举都是用const定义,const是预编译是处理,不可取地址。枚举:const(a = iota; b ; c )
    14、不允许循环依赖
    15、数组是值类型,gc认为是一个对象,在传递中copy。函数的实参都会复制,不管啥类型。
    16、Golang 中无需使用 break 语句来跳出 switch, switch可认为是if的扩展,支持if的所有功能。
    17、new只分配指针内存,make才是正确的对象指针初始化。
    18、不同的类型需要显示转化 如var i= int(byte);
    19、 struct初始化可以 如 &xx{x,y},new(Type) 和 &Type{}
    20、函数可以返回指针,但是可能会导致对象有heap到堆的拷贝,延长其生命周期。
    21、interface{}相当于java的object 
    22、string支持+=操作,Go语言的字符串是用UTF-8编码的变宽字符序列,每个字符都用一个或多个字节表示
    23、支持range,用_表示忽略类型
    24、defer延迟调用,相当于java的finally
    25、go 有数组(array)、切片(slice)和map
     

    接口:

    阅读全文>>

  • spark java demo

    post by onelong / 2016-11-18 18:57 Friday [工作]

    import java.text.SimpleDateFormat;
    import java.util.*;

    import org.apache.spark.SparkConf;
    import org.apache.spark.api.java.JavaPairRDD;
    import org.apache.spark.api.java.JavaRDD;
    import org.apache.spark.api.java.JavaSparkContext;
    import org.apache.spark.api.java.function.*;

    import scala.Tuple2;

    public class SparkDemo {
     
        static final String USER = "huanglong";
     
        public static void main(String[] args) throws Exception {
            
           
            SparkConf conf =new SparkConf().setAppName("Spark Log").setMaster("local[4]");
            JavaSparkContext sc = new JavaSparkContext(conf); //其底层就是scala的sparkcontext


            //JavaSparkContext sc = new JavaSparkContext("local[4]", "Spark Log", "/user/huanglong/spark", new String[0], envs);
     
           
            String file="file:///Users/huanglong/access_05_30.log";
            JavaRDD<String> data = sc.textFile(file, 4).cache();

            //日志格式
            //27.19.74.143 - - [30/May/2013:17:38:20 +0800] "GET /static/image/common/faq.gif HTTP/1.1" 200 1127;

            JavaRDD<String> filter =  data.filter(new org.apache.spark.api.java.function.Function<String, Boolean>() {
                @Override
                public Boolean call(String s) throws Exception {
                    //过滤合法和非静态的资源的日志
                    return (s.contains("POST")||s.contains("GET"))&& !s.contains("/static/");
                }
            });

            final  SimpleDateFormat tf = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z",
                    Locale.ENGLISH);
            //只有一天的记录,不需要年月日了,时间精度到分钟
            final SimpleDateFormat tf1 = new SimpleDateFormat("HH:mm");

            JavaRDD<Map<String,String>> lines = filter.flatMap(new FlatMapFunction<String,Map<String,String>>(){

                @Override
                public Iterator<Map<String,String>> call(String s) throws Exception {
                    List<Map<String,String>> list = new ArrayList<Map<String,String>>(1);
                    Map<String,String> map = new HashMap<String, String>();
                    list.add(map);
                    String ip = s.substring(0,s.indexOf(" - - "));
                    map.put("ip",ip);

                    String t = s.substring(s.indexOf("[")+1,s.indexOf("]"));
                    Date date =  tf.parse(t);
                    map.put("time",tf1.format(date));

                    String http = s.substring(s.indexOf("\"")+1,s.indexOf("\" "));
                    String[] h= http.split(" ");

                    if(h.length>1){

                        if(h[1]!=null&&h[1].indexOf("?")!=-1)
                        {
                            map.put("url",h[1].substring(0,h[1].indexOf("?")));
                        }else {
                            map.put("url",h[1]);
                        }
                    }

                    if(h.length>2)
                    {
                        map.put("version",h[2]);
                    }

                    if(map.get("version")!=null&&map.get("version").contains("1.1"))
                    {
                        String state = s.substring(s.indexOf("1.1\" ")+5,s.length());
                        String[] strings = state.split(" ");
                        if(strings.length>0) {
                            map.put("state", strings[0]);
                        }
                    }else if(map.get("version")!=null&&map.get("version").contains("1.0"))
                    {
                        String state = s.substring(s.indexOf("1.0\" ")+5,s.length());
                        String[] strings = state.split(" ");
                        if(strings.length>0) {
                            map.put("state", strings[0]);
                        }
                    }else {
                        //System.out.println(s);
                    }

                    return list.iterator();
                }
            });

            System.out.println("总记录数:"+lines.count());
            // 统计ip
                ipsHandle(lines);
            System.out.println("--------------------------------------------------");
            // 统计分时页面访问量
                timeHandle(lines);
            System.out.println("--------------------------------------------------");
            // 统计分时ip访问量
                timeHandle2(lines);
            System.out.println("--------------------------------------------------");
            // 统计状态 400,300 200 各有多少,计算失败率
                stateHandle(lines);
            System.out.println("--------------------------------------------------");
            // 统计http版本 1.1、1.0
                versionHandle(lines);
            // 页面热度
            System.out.println("--------------------------------------------------");
                pageHandle(lines);
     
           sc.close();

        }


        private static void pageHandle(JavaRDD<Map<String, String>> lines) {

            JavaRDD<Map<String, String>> filterData =  lines.filter(new Function<Map<String, String>, Boolean>() {
                @Override
                public Boolean call(Map<String, String> map) throws Exception {
                    String url = map.get("url");
                    return "200".equals(map.get("state"))&&url.endsWith(".php");
                }
            });


            JavaPairRDD<String,Integer> versionPairs = filterData.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("url"),1);
                }
            });

            JavaPairRDD<String,Integer> versionCount = versionPairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });


            versionCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("URL->PV:"+pairs._1+" : " +pairs._2);
                }
            });
        }


        private static void versionHandle(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Integer> versionPairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("version"),1);
                }
            });

            JavaPairRDD<String,Integer> versionCount = versionPairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });


            versionCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("VERSION->PV:"+pairs._1+" : " +pairs._2);
                }
            });
        }

        private static void stateHandle(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Integer> statePairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("state"),1);
                }
            });

            JavaPairRDD<String,Integer> stateCount = statePairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });

            stateCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("STATE->PV:"+pairs._1+" : " +pairs._2);

                }
            });
        }

        private static void ipsHandle(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Integer> ipPairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("ip"),1);
                }
            });

            JavaPairRDD<String,Integer> ipCount = ipPairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });

            System.out.println("总ip数:"+ipCount.count());


            ipCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("IP->PV:"+pairs._1+" : " +pairs._2);
                }
            });
        }

        private static void timeHandle2(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Map<String,Boolean>> timePairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Map<String,Boolean>>() {
                @Override
                public Tuple2<String,Map<String,Boolean>> call(Map<String, String> stringStringMap) throws Exception {
                    Map<String,Boolean> m = new HashMap<String, Boolean>();
                    m.put(stringStringMap.get("ip"),Boolean.TRUE);
                    return new Tuple2<String, Map<String,Boolean>>(stringStringMap.get("time"),m);
                }
            });

            JavaPairRDD<String,Map<String,Boolean>> timeCount = timePairs.reduceByKey(new Function2<Map<String,Boolean>, Map<String,Boolean>,Map<String,Boolean>>() {
                @Override
                public Map<String,Boolean> call(Map<String,Boolean> v1, Map<String,Boolean> v2) throws Exception {
                    HashMap<String, Boolean> m = new HashMap<String, Boolean>();
                    m.putAll(v1);
                    m.putAll(v2);
                    return m;
                }
            });


            timeCount.foreach(new VoidFunction<Tuple2<String,Map<String,Boolean>>>() {
                @Override
                public void call(Tuple2<String, Map<String,Boolean>> pairs) throws Exception {

                    System.out.println("TIME->IP:"+pairs._1+" : " +pairs._2.size());

                }
            });

        }

        private static void timeHandle(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Integer> timePairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("time"),1);
                }
            });

            JavaPairRDD<String,Integer> timeCount = timePairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });

            timeCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("TIME->PV:"+pairs._1+" : " +pairs._2);

                }
            });

        }

    }

    阅读全文>>

  • Hadoop科普

    post by onelong / 2016-11-18 18:56 Friday [工作]

    Hive是一个构建在Hadoop基础设施之上的数据仓库。通过Hive可以使用HQL语言查询存放在HDFS上的数据。HQL是一种类SQL语言,这种语言最终被转化为Map/Reduce. 虽然Hive提供了SQL查询功能,但是Hive不能够进行交互查询--因为它只能够在Haoop上批量的执行Hadoop。 Hive帮助熟悉SQL的人运行MapReduce任务,Hive目前不支持更新操作,Hive适合用来对一段时间内的数据进行分析查询,Hive必须提供预先定义好的schema将文件和目录映射到列。
    HBase是一种Key/Value系统,它运行在HDFS之上, Hbase非常适合用来进行大数据的实时查询。Facebook用Hbase进行消息和实时的分析。它也可以用来统计Facebook的连接数。
    Hive和Hbase是两种基于Hadoop的不同技术--Hive是一种类SQL的引擎,并且运行MapReduce任务,Hbase是一种在Hadoop之上的NoSQL 的Key/vale数据库。当然,这两种工具是可以同时使用的。就像用Google来搜索,用FaceBook进行社交一样,Hive可以用来进行统计查询,HBase可以用来进行实时查询,数据也可以从Hive写到Hbase,设置再从Hbase写回Hive。 

    阅读全文>>

  • 过一段感动自己的日子

    post by onelong / 2016-11-18 18:54 Friday [工作]

    记得曾经看到这样一句话:“只有度过了一段连自己都被感动了的日子,才会变成那个最好的自己”,稻盛和夫还有一句话“当你感到不行了,事情才刚刚开始”。中国老话,置之死地而后生。很多时候人成长是孤单的,甚至是寂寞的,需要莫大的勇气才走过泥泞,面朝大海,春暖花开。今天在朋友圈又分享一篇文章,其中有段话是这样的:“真正的努力,不是比谁把自己虐得更惨,不是比谁花的时间更多,也不是比谁能进行更多的项目,而是找到合适的方法,抛下杂念,全身心地投入去做一件事情,多思考,多总结。”,或许鸡汤喝多了,容易长胖,然后什么都干不动了。之前,很多人和我说,我们不像你,那么喜欢技术,我们能过生活就好了。当危机发生的时候,不曾努力或许能生活都过不好。如逆水行舟,你不前进,别人在前进,你就是变相的后腿,人是逼出来的,没有人天生喜欢哪些伤脑筋的事情,只是没有更好的选择。然而在没有更好的选择是应该珍惜当下,不轻易浪费生命,每一个不求上进的时刻,都是对生命的辜负。成长就是强迫自己做自己害怕的事情,强迫自己做不曾想过的事情,过程肯定是痛苦难耐。所以人生中总要有那么几段连自己都被感动的日子,这样才不枉此生。
    作为一个非计算机专业的人,全凭自己的毅力和坚持走到今天,过程是很辛苦的,当然也是快乐的,因为每天都忘记时间是流逝的,每个眼干的深夜却异常的兴奋,那一刻问题得到解决。从前端到移动端到服务端,一直记得师兄那句玩笑“有些东西你不懂,永远都不会懂的拉”,也是这样一股不服的心坚持到现在。IT,并不是我最喜欢的,在没上大学之前,我最喜欢物理电子,在初中的时候,我就很喜欢看职高的物理书了,后来因为希望留在工作室上网“叹 ”空调,强迫自己学好前端通过重重考验,成为页面部部长。而今天看来,大家都是觉得我喜欢技术才这样折腾这个,折腾那个,其实没有更好的选择了。无论是学历还是背景都没有亮点,只是通过自己努力坚强的走下去了,久而久之就觉得IT这个世界很刺激,每天都是新鲜感,也就喜欢了。说到喜欢,其实每个男人心中都是喜欢极限挑战,征服世界。在征服世界之前,需要走过每个关卡。男人最怕就是退休,因为退休了就意味着老了,不行了,夕阳西下了,再也无法征服世界了。
    在技术领域里面,很多东西都是反复折腾的,就像最近了解的SQL一样 ,在学校看过几本书,出来工作了折腾过一点时间,还是没搞懂,糊里糊涂的过去了,因为不懂,所以一直很抗拒SQL,总想着很多很复杂的东西,但是当某一刻你突然明白了,其实并没有那没那么复杂,以前觉得几个表连起来查询好像要变天一样,而今天用起来确实自然而然了,量变到质变的过程,总是无声无息的。以前看师弟们做的网址,当时看他们写了很多关键词的过滤函数,主要是为了防止SQL注入,而今天我发现其实java也好,php也好其实框架都内置防注入的方案,很多事情突然间就没那么恐怖了,以前自己写函数过滤,得多了解各种坑呀,所以觉得很复杂。一直以来喜欢做服务开发,不喜欢web开发,服务开发一般在内网运行,基本不做安全措施,绝大部分的安全问题由防火墙来搞定。随着时间的推移,阅历的丰富,其实javaweb并没有想象中那么复杂,想起两年前在珠海移动的时候,死活都看不懂spring用来干嘛的,用eclipse折腾maven项目要死要死的,配个tomcat调试还弄了几次不行,最后叫人帮我弄,弄好了,换一下就不行了,最后放弃了。而今年弄idea,还爱上了maven,一切都用得很顺手,现在看到哪些不是maven的java项目,我就觉得烦。当开始了解spring的时候,就会发现它很神奇,依赖注入,反向调用。很神奇的地方就是你可以注入一个数据源对象和SQL的配置文件,就可以使用各种驱动去访问数据库了,甚至支持读写分类,分库分表。在java的生态里面,你会感叹什么才是真正的组件化开发,spring是何等伟大的东西。我给javaweb来了总结:javaWeb=UI+sql,然后好多人笑话我的肤浅,至少我深层理解过,web这个东西依赖关系型数据做逻辑太重了。
    最近为什么要学SQL呢,其实就是因为Hive和spark sql,突然意识到SQL是一切数据技术的基础,过去忽视它是一种缺失。再说让我管理整个产品线,我至少应该会做web吧,大部分技术能折腾一下吧,于是就学了SQL。从SOA到微服务再到大数据,都hello world了一会,感性认识了一遍,发现前面路好像变宽了,之前看完dobbu的源代码,其实对服务治理有了一定的了解,对现有产品的技术框架也有了初步粗暴评价。 往后希望有合适场景让我hello world一下机器学习和深度学习。
    也许这一切并没有什么卵用,不能当作实际的经验,但是至少了解了原理,路走起来会更顺。 以前面试吹水这些,心里会很不踏实,万一真的让我干岂不是完蛋了,现在完全不会脸红了。怕毛呀,干就干。。。。。

  • AES Demo

    post by onelong / 2016-11-11 20:09 Friday [apple]

    #import "ViewController.h"

    #import <CommonCrypto/CommonDigest.h>

    #import <CommonCrypto/CommonCryptor.h>

    阅读全文>>

  • Hadoop,Spark,JStrom

    post by onelong / 2016-10-24 23:47 Monday [工作]

    这两天了解了一下大数据处理框架,网上浏览了一番,看得眼花撩乱,Hadoop,HBase,Hive,Spark,JStrom等等,既然花了时间去了解,当然要做一下总结吧:
    Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。后面发展产生了很多子项目,HDFS(分布式文件系统),MapReduce(并行计算框架),HBase(分布式NoSQL列数据库),Hive(数据仓库工具),pig,zk等。对于Hadoop的MapReduce要自己写Map和Reduce,各个方便比较繁琐,门槛比较高。Hadoop通常用超大规模静态数据分析,中间结果写入HDFS,时延比较高,但不能说慢,快和慢就看堆多少硬件的。只适用Batch数据处理,对于交互式数据处理,实时数据处理的支持不够,对于迭代式数据处理性能比较差。
    Spark是新出来的,用于替代MapReduce的并行计算框架,主要特点是提供了一个集群的分布式内存抽象,以支持需要工作集的应用,RDD就是一个不可变的带分区的记录集合,RDD也是Spark中的编程模型。Spark提供了RDD上的两类操作,转换和动作。转换是用来定义一个新的RDD,包括map, flatMap, filter, union, sample, join, groupByKey, cogroup, ReduceByKey, cros, sortByKey, mapValues等,动作是返回一个结果,包括collect, reduce, count, save, lookupKey,也即是说Spark更易用了。Spark为迭代式数据处理提供更好的支持。每次迭代的数据可以保存在内存中,而不是写入文件,Spark的性能相比Hadoop有很大提升。Spark框架为批处理(Spark Core),交互式(Spark SQL),流式(Spark Streaming),机器学习(MLlib),图计算(GraphX)提供一个统一的数据处理平台。

    Batch Layer,HDFS+Spark Core,将实时的增量数据追加到HDFS中,使用Spark Core批量处理全量数据,生成全量数据的视图
    Speed Layer,Spark Streaming来处理实时的增量数据,以较低的时延生成实时数据的视图
    Serving Layer,HDFS+Spark SQL,存储Batch Layer和Speed Layer输出的视图,提供低时延的即席查询功能,将批量数据的视图与实时数据的视图合并。

    无论是Hadoop还是Spark,都是比较适合做批量处理全量数据,不适合做增量数据分析。Spark比较方便的结合HDFS,HBase和mysql,例如将计算结果导到Mysql等。

     
    Spark Streaming和JStorm(Storm)都是分布式流处理框架,通常和消息队列一起使用,如Kafka。用于增量处理数据。JStorm比Spark Streaming更高性能。通常是用法:日志--》消息队列--》JStorm--》写入数据库和展示。例如双11实时统计成交金额。

    一般的用法:
    1、Hadoop 独立使用,离线数据分析,感觉
    Spark比较火,但是Hadoop是基础。
    2、HDFS+Spark,文件+ 
    Spark,HBase+ Spark,Spark+MySql 等
    3、 Kafka(消息队列)+ (J)Storm或Spark Streaming+ HBase(数据库)
    4、2和3结合用,日志存储+流处理。因为流处理是不可重复的,你可能需要把日志存储下来,以备下次离线分析。 

  • android找靓机二手手机2.2

    post by onelong / 2016-10-18 14:26 Tuesday [工作]

    8月份的时候发布了2.2版本,现在准备发布2.3版本了,8月份统计的时候,装机量30多万台,现在估计将近40w了,感觉不错。

    点击查看原图点击查看原图点击查看原图点击查看原图点击查看原图

    阅读全文>>

  • iOS内存泄漏排查

    post by onelong / 2016-10-17 15:18 Monday [工作]

    现在iOS开发中大部分都是用了自动引用计数器的,内存管理基本上是编译器帮我们处理了,唯一要自己的处理的就是循环引用。在网上有很多教程告诉我们该如何避免循环引用。如代理用weak修饰,block要类似__weak ViewController *weakSelf = self这样处理。我知道这些,大部分开发者都是懂的。但是很时候会忘记,或者想的不够多。例如 某ViewController持有AView和BView,而且AView是加在BView上的,这种情况很多时候是很难发现的,所以我们需要工具帮助我们排查。上次在Android上用了LeakCanary之后,查找内存泄漏,修复bug的效率高多了,这次还是一样,介绍一下iOS上面的工具-MLeaksFinder这个工具的介绍有很多,我就不多说了,我更关心的是如何用起来,最近一个项目,我小试牛刀,效果立竿见影。如果内存泄漏,会在控制台打印如下的信息
    *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Possibly Memory Leak.In case that MyTableViewCell should not be dealloced, override -willDealloc in MyTableViewCell by returning NO.
    View-ViewController stack: (
    MyTableViewController,
    UITableView,
    UITableViewWrapperView,
    MyTableViewCell
    )'
    那该怎样处理呢? 其实控制台的信息已经告诉我们了 MyTableViewCell should not be dealloced, override -willDealloc in MyTableViewCell by returning NO,重写MyTableViewCell的-(void)willDealloc方法,将里面引用外面的东西置为nil就好了。处理之后重新运行就不会再提示了。是不是很简单呢?工具帮助我们提高效率。
    还有一种情况是block的循环引用,这个是无法列出堆栈的。只能靠自己观察,在block使用weakSelf,还有一个值得主要的是例如某属性:
    @property (nonatomic,strongUILabel *titleLabel;
    而你在block里面这样使用了
    _titleLabel.text=xx
    这样也是不行的。但是这个我们很容易忽略。
    我觉得一个好的习惯就是在每个对象了里面都重写-(void)willDealloc,将全部属性都置为nil,这样就可以防范于未然了。虽然这个工具只能帮助我们检测ViewController上面的内存泄漏,但是通过修复bug可以更好的规范我们的代码。