首页 文章 精选 留言 我的

精选列表

搜索[深度集成],共10000篇文章
优秀的个人博客,低调大师

深度学习入门:用MNIST完成Autoencoder

Autoencoder基本是Deep Learning最经典的东西,也是入门的必经之路。Autoencoder是一种数据的压缩算法,其中数据的压缩和解压缩函数必须是数据相关的,有损的,从样本中自动学习的。在大部分提到自动编码器的场合,压缩和解压缩的函数是通过神经网络实现的。 在这里,我来给大家完成一个MNIST数据集的Autoencoder 首先下载MNIST数据,在这里友情提醒一下,MNIST的数据集因为某些原因,下载速度非常的慢,在这里推荐去THE MNIST DATABASE下载。下载完成后建一个MNIST_data的文件夹,放进去。 在这里提一下,为什么我们要将图片设置为28*28? 28*28的特征图大小可以防止输入的连接掉到边界之外,不导致梯度损失。 大家觉得自编码器可以在没有标签的时候学习到数据的有用表达。但是,自编码器并不是

优秀的个人博客,低调大师

Unity加载模块深度解析(纹理篇)

资源加载 资源加载是加载模块中最为耗时的部分,其CPU开销在Unity引擎中主要体现在Loading.UpdatePreloading和Loading.ReadObject两项中,相信经常查看Profiler的朋友对这两项肯定毫不陌生了。 Loading.UpdatePreloading,这一项仅在调用类似LoadLevel(Async)的接口处出现,主要负责卸载当前场景的资源,并且加载下一场景中的相关资源和序列化信息等。下一场景中,自身所拥有的GameObject和资源越多,其加载开销越大。 在很多项目中,存在另外一种加载方式,即场景为空场景,绝大部分资源和GameObject都是通过OnLevelWasLoaded回调函数中进行加载、实例化和拼合的。对于这种情况,Loading.UpdatePreloading的加载开销会很小。 Loading.ReadObject,这一项记录的则是资源加载时的真正资源读取性能开销,基本上引擎的主流资源(纹理资源、网格资源、动画片段等等)读取均是通过该项来进行体现。可以说,这一项很大程度上决定了项目场景的切换效率。正因如此,我们就当前项目中所用的主流资源进行了大量的测试和分析,下面我们将分析结果与大家一起分享,希望可以帮到正在进行开发的你。 注意事项:本篇文章的资源性能分析主要是针对移动项目而言,因为目前UWA所测评的项目中,移动游戏/应用占比在90%以上。所以,我们选择首先在移动设备上针对每种资源的加载性能进行分析和总结。 资源加载性能测试代码 以下为我们测试时所使用的测试代码,我们将每种资源均制作成一定大小的AssetBundle文件,并逐一通过以下代码在不同设备上进行加载,以期得到不同硬件设备上的资源加载性能比较。 测试环境 引擎版本:Unity 5.2版本 测试设备:五台不同档次的移动设备(Android:红米2、红米Note2和三星S6,iOS:iPhone 5 和 iPhone 6) 纹理资源 纹理资源是项目加载过程中开销占用最大的资源之一,其加载效率由其自身大小决定。目前,决定纹理资源大小的因素主要有三种:分辨率、格式和Mipmap是否开启。 1. 分辨率 & 格式 分辨率和格式是影响纹理资源加载效率的重要因素,因为这两项的设置对纹理资源的大小影响很大。因此,我们对这两种因素进行了详细的测试: 测试1:相同格式、不同分辨率的加载效率测试 我们选取了两张分辨率为2048x2048的普通纹理资源,并在打成AssetBundle时,将其分辨率最大值分别设置为512x512、1024x1024和2048x20248,纹理格式均设置为ETC1(Android)和PVRTC(iOS)、且关闭Mipmap功能。所以,三组纹理的内存占用分别为256KB、1MB和4MB,其对应AssetBundle大小为156KB、531KB和1.92MB(对于Android平台)、175KB、628KB和2.4MB(对于iOS平台)。Unity 版本为5.2,压缩格式为默认的LZMA压缩。 Android平台测试纹理: 我们在五种不同档次的机型上加载这些纹理资源,为降低偶然性,每台设备上重复进行十次加载操作并将取其平均值作为最终性能开销。具体测试结果如下表所示。 通过上述测试,我们可以得到以下结论: 1、纹理资源的分辨率对加载性能影响较大,分辨率越高,其加载越为耗时。设备性能越差,其耗时差别越为明显; 2、设备越好,加载效率确实越高。但是,对于硬件支持纹理(ETC1/PVRTC)来说,中高端设备的加载效率差别已经很小,比如图中的红米Note2和三星S6设备,差别已经很不明显。 测试2:不同格式、相同分辨率的加载效率测试 我们选取了两张分辨率为1024x1024的普通纹理资源,并在打成AssetBundle时,根据不同平台将其纹理格式分别设置不同格式用于打包。对于Android平台,我们使用ETC1、ETC2、RGBA16和RGBA32四种格式,对于iOS平台,我们使用PVRTC 4BPP、RGBA16和RGBA32三种格式,同时,对于每张纹理均关闭Mipmap功能。所以,三组纹理的内存占用分别为1MB、1MB、4MB 和 8MB(Android平台)/1MB、4MB 和 8MB(iOS平台)。 Android平台测试纹理: 与测试1相同,我们在五种不同档次的机型上重复进行十次加载操作并将取其平均值作为最终性能开销。具体测试结果如下图所示。Android设备:iOS设备: 通过上述测试,我们可以得到以下结论: 1、纹理资源的格式对加载性能影响同样较大,Android平台上,ETC1和ETC2的加载效率最高。同样,iOS平台上,PVRTC 4BPP的加载效率最高。 2、RGBA16格式纹理的加载效率同样很高,与RGBA32格式相比,其加载效率与ETC1/PVRTC非常接近,并且设备越好,加载开销差别越不明显; 3、RGBA32格式纹理的加载效率受硬件设备的性能影响较大,ETC/PVRTC/RGBA16受硬件设备的影响较低。 注意事项:这里需要指出的是测试中所使用的ETC1和ETC2纹理均为RGB 4Bit格式,所以对于半透明纹理贴图,需要两张ETC1格式的纹理进行支持(一张RGB通道,一张Alpha通道)。逐一加载两张ETC1格式的纹理,其加载效率要低于RGBA16格式,但可以通过加载方式来进行弥补。这一点我们将在后续文章中进行详细说明。 2. 开启Mipmap功能 开启Mipmap功能同样会增大一部分纹理大小,一般来说,其内存会增加至原始大小的1.33倍。因此,我们对开启Mipmap功能前后的加载性能进行了详细的测试: 测试3:开启/关闭Mipmap功能的加载效率测试 我们仍然使用两张分辨率为1024x1024的普通纹理资源,分别使用ETC1格式、PVRTC格式、RGBA16格式和RGBA32格式(测试所用纹理与测试2相同),并在打成AssetBundle时,一组开启Mipmap功能,一组关闭Mipmap功能。 与测试1相同,我们在五种不同档次的机型上重复进行十次加载操作并将取其平均值作为最终性能开销。具体测试结果如下图所示。Android平台:iOS平台: 通过上述测试,我们可以看出:开启Mipmap功能会导致资源加载更为耗时,且设备性能越差,其加载效率影响越大。 通过以上性能测试,我们对于纹理资源的加载建议如下: 1、严格控制RGBA32和ARGB32纹理的使用,在保证视觉效果的前提下,尽可能采用“够用就好”的原则,降低纹理资源的分辨率,以及使用硬件支持的纹理格式。 2、在硬件格式(ETC、PVRTC)无法满足视觉效果时,RGBA16格式是一种较为理想的折中选择,既可以增加视觉效果,又可以保持较低的加载耗时。 3、严格检查纹理资源的Mipmap功能,特别注意UI纹理的Mipmap是否开启。在UWA测评过的项目中,有不少项目的UI纹理均开启了Mipmap功能,不仅造成了内存占用上的浪费,同时也增加了不小的加载时间。 4、ETC2对于支持OpenGL ES3.0的Android移动设备来说,是一个很好的处理半透明的纹理格式。但是,如果你的游戏需要在大量OpenGL ES2.0的设备上进行运行,那么我们不建议使用ETC2格式纹理。因为不仅会造成大量的内存占用(ETC2转成RGBA32),同时也增加一定的加载时间。下图为测试2中所用的测试纹理在三星S3和S4设备上加载性能表现。可以看出,在OpenGL ES2.0设备上,ETC2格式纹理的加载要明显高于ETC1格式,且略高于RGBA16格式纹理。因此,建议研发团队在项目中谨慎使用ETC2格式纹理。 正是由于以上加载效率问题,我们在UWA测评报告中加入了对每个检测到的纹理资源参数的详细展示,以方便开发团队可以快速查看资源的使用情况,只需对相关信息列进行排序,即可定位引发性能问题的具体资源。 说明:以上测试数据为我们所用的测试纹理加载数据,需要指出的是,不同纹理的加载效率是不相同的,因为其内容的不同会造成AssetBundle压缩包大小的不同,进而造成最终加载效率的不同。这里我们给出的具体性能比较,其本意是让大家通过数据直观了解到纹理格式、分辨率和Mipmap功能对加载性能的影响。另外,我们后续会进行更多的测试,以期为大家提供更为普遍的测试结果。 以上为纹理资源在加载时的性能测试。关于加载模块的性能问题,我们会不断推出网格、音频等其他资源的加载性能分析、资源卸载性能分析、资源实例化性能分析、不同加载方式的性能分析等一系列技术文章,并对目前UWA所检测过项目的共性问题进行总结,以期让大家对项目的加载效率有更加深入的认知,并提升对加载模块的掌控能力。 原文出处:侑虎科技 转载请与作者联系,同时请务必标明文章原始出处和原文链接及本声明。

优秀的个人博客,低调大师

iOS开发之Alamofire源码深度解析

一.Alamofire核心模块概述 我们先整体上来看一下AlamoFire这个框架关系,概述一些核心模块。该部分我们先来看一下AlamoFire的文件组织结构,然后在给出这些文件组织结构中类的关系。所以在本部分类图是少不了的。废话少说,进入该部分的主题。 1.Alamofire的目录结构解析 首先我们来看一下AlamoFire的目录结构,从整体上来把控一下AlamoFire。下方截图是AlamoFire框架的所有文件,文件不算多,Alamofire框架的源代码并不算多,所有理清Alamofire的框架结构还是不难的。下方截图中是AlamoFire中的所有文件,Core文件夹下是Alamofire的核心文件,Features主要是对核心文件的扩展。今天我们就以核心文件为主,Feature文件为辅来窥探一下AlamoFire框架的源码。 下方是对Core文件夹下的各个文件的功能简述: Alamofire.swift---- 该文件中主要是给用户提供一些便利的调用方法,用户可以直接调用该文件中的便利方法来使用Alamofire相关功能。 Manager.swift---- Manager中定义了Session对象,Session相关的Delegate,以及Delegate执行的队列等相关信息,在Manager中创建Request对象发起请求。Manager管理的就是各种请求,Manager对象是以单例的形式对外开放的。 Request.swift---- 该文件如其名,就是负责创建Session的各种task的,并执行相关的SessionTask,并调用相关书籍解析的功能模块对数据进行解析并通过回调返回给用户。 ParameterEncoding.swift---- 负责请求参数的各种编码(URL、URLEncodedInURL、JSON、PropertyList等编码),并将编码后的数据与URLRequest结合后的结果进行返回。 Result.swift---- 对解析后的数据封装成Result对象。 Response.swift----负责将服务器相应的数据进行封装生成Response对象,该对象中就包括上述的Result对象,用户最终会通过闭包回调的形式获取到该Response的对象。 Notifications.swift---- 其中是一个Notification结构体,该结构体中定义了一些字符串,这些字符串就是所需通知的Key,当网络请求DidResume、DidSuspend、DidCancel、DidComplete都会发出通知。 Error.swift---- 其中是一个Error的结构体,其中封装的是各种错误状态。 Features文件夹下各个文件的功能简述: Download.swift----- 对Manager和Request类进行扩展,使其支持Down Task,其中封装了NSURLSessionDownloadDelegate相关代理方法。 Upload.swift---- 在该文件中也是对Manager和Request类进行的扩展,使其支持Upload Task,其中封装了NSURLSessionDataDelegate中获取上传数据进度的代理方法,也就是taskDidSendBodyData代理方法。 MultipartFormData.swift---- 该文件从名字就可以看出是为了组织多表单数据上传的数据的,在Upload Task中就使用到了MultipartFormData。 Stream.swift---- 和Download和Upload文件相似,该文件中也是对Manager和Rquest做延展,主要使其支持数据流的传输,其中主要封装和实现了NSURLSessionStreamDelegate相关的代理方法。 ResponseSerialization.swift---- 该文件中主要是对Request类进行数据解析的延展的。其中封装了各种对响应数据的解析方式,其中包括Data、String、JSON、PropertyList等解析方式。 NetworkReachabilityManager.swift---- 该文件主要是对SystemConfiguration.framework中的SCNetworkReachability相关的东西进行封装的,主要用来管理和监听网络状态的变化。 ServerTrustPolicy.swift---- 这个文件主要是对NSURLSession做的延展,其中定义了各种网络请求的认证策略,主要证书认证相关东西。 Timeline.swift---- 该文件是为了方便调试而生的,其中记录了相关操作的时间点,并且对其进行记录,便于在Debug时使用到。 Validation.swift---- 主要是用来验证请求是否成功,如果出错了就做相应的处理。 上面是AlamoFire中所有文件的概述,上面这些算是对AlamoFire框架有大概的了解吧。结合上方的概述,来研读AlamoFire源码还是比较清晰的。下方就是AlamoFire 3.4中相关文件的木头结构,如下所示: 2.核心类间的结构 上面简单的介绍了Alamofire框架的目录结构以及每个文件所负责的内容。接下来我们进入到各个文件的内部,来整体的看一下核心类之间的关系。下方是核心类的“类图”,当然下方只是核心类的。接下来来概述一下下方的类图,因为下图太大,在此看起来不太清楚,如果你感兴趣,你可以另存为,然后放大查看。 下方黑框中的部分对应的就是Alamofire.swift中的内容。其中主要是一些URL转换字符串的延展以及URLRequst转换成MutableURLRequest的延展,还有一些用户使用的便利方法。 黄框中就是我们Manager.swift中的内容了,Manager类的对象是以单例的形式对外展现的,上述黑框中的便利方法,主要是获取Manager类的单例,然后调用相应的方法。 绿框中所对应的主要是Request.Swift和Features文件夹中的内容,主要是Request类及其延展,当然还有对Manager和NSURLSession的延展。 红框中的就是网络请求会话的各种任务的回调方法的封装了,在这些回调方法中提供了默认实现,并对外留有回调块,以便让用户来自己实现这些回调方法。 二、Alamofire.swift源码解析 第一部分算是概览了一下Alamofire框架中的各个组成部分,接下来该进入到上述的各个模块中来进一步来窥探其实现和组织方式了。还是“顺藤摸瓜”,先从用户看的到的地方着手,然后层层深入,直到你看不见的地方。所以第二部分我们先来看一下Alamofire.swift中的内容,因为该文件是Alamofire框架的入口。 1.Alamofire.swft中的类图结构 下方的类图就是第一部分类图中黑框的放大版,根据Alamofire.swift这个文件我们不难画出下方这个类图。有一点要说明的就是在类图中省略了一些遍历方法,只写了一些主要的,不过核心的功能还是有的。下方的URLStringConvertible和URLRequestConvertible是负责类型转换的接口,具体的请看下方的介绍。该文件中除了类型转换的方法外就是一些调用Manager的单例的便利方法了。 2.Alamofire.swift技术细节 下方就是URLStringConvertible协议以及相关延展的具体实现,主要功能就是将String、NSURL、NSURLComponents、NSURLRequest中的URL转换成字符串类型。将要转换的类型要遵循URLStringConvertible协议,并在计算变量URLString中返回转换后的字符串。具体做法如下所示,这中类型转换方式在开发中经常会使用到,下方会给出其他实例。URLRequestConvertible协议的功能与URLStringConvertible大同小异,URLRequestConvertible协议的实现者负责将NSURLRequest转换成NSMutableURLRequest类型。在此就不做过多的赘述了。 下方截图是Alamofire.swift中的一个便利方法,其他几个便利方法与此相似,都是调用Manager单例中相应的方法,便利方法为了链式调用Request类中的相关方法,所以所有的便利方法都会返回当前Manager单例使用的Request对象。具体如下所示: 3.扩展用例 学以致用,举一反三。上面那种“面向协议”开发的思想值得我们学习,之前在设计模式相关的系列博客中不止一次的提到过要“面向接口编程”,此处的协议就是接口。虽然上面只是使用协议来进行简单的类型转换,这种思想是非常值得我们学习的。通过上面类型转换的方式,我们可以写出下方代码。下方代码不是Alamofire框架中的代码,是我根据上述的类型转换的实例所实现的,下方定义了一个类型转换的协议,需要转换的类型要遵循这个协议,下方以String为例,具体做法如下所示。 三、Manager.swift源码解析 因为便利方法主要是调用的Manager类的单例,所以接下来我们来看Manager.swift中的东西。Manager类中主要负责Session和Request的初始化,并且提供SessionDelegate代理方法的默认实现。在实现代理方法时留出了相应的闭包已提供给用户使用该闭包来回调相应的代理方法。在Manager中的SessionDelegate类就是NSURLSessionDelegate以及相关子协议的代理类,其中就给出了各个代理方法的默认实现,在实现时并定义了一系列的Closure回调变量,当这些闭包变量不为空时就会执行闭包块中的内容,而不会执行提供的默认实现。 1.Manager.swift相关类图 下方类图就是黄色部分的放大版,主要是Manager类与SessionDelegate的关系。从下方类图中不难看出,SessionDelegate类遵循了NSURLSessionDelegate协议以及子协议,并给出了代理相应的实现方法。下方的代码会给出代理的具体封装和实现方式。 2.Manager类的相关属性 开门见山,因为Manager类对外是以单例的形式对外使用的,所以我们先来看看Manager类的单例实现。下方截图中的sharedInstance计算属性就是Manager的单例,其中存储的就是一个Manager对象,在创建Manager对象时我们为Manager对象中存储的NSURLSession对象指定了一个defaultSessionConfiguration和一个defaultHTTPHeaders。 上面是Manager类中单例的实现,接下来我们来解析类中核心的属性,下方是一些核心属性的解析: defaultHTTPHeaders属性:defaultHTTPHeaders是Manager类中的一个计算属性,负责组织默认的请求Header中的内容。 session属性:该属性的类型是NSURLSession类型的,负责请求会话,并创建各种会话任务。 queue属性:该属性是一个串行队列,该队列负责执行session创建Session Task的任务。 delegate属性:该属性是SessionDelegate类型的,而SessionDelegate类遵循了NSURLSessionDelegate及其子协议,并给出了相应的实现,在下方会着重介绍SessionDelegate。而此处的delegate属性负责调用SessionDelegate类中相应的回调方法。 3.Manager类的request方法 在Manager.swift源文件中给出了request方法的实现,Manager类的单例所调用的upload、download等方法是在其他源文件中做的延展。那些延展中的方法稍后在聊,本部分中就先对request方法进行解析。下方的方法就是我们在便利方法中使用Manager类的单例所调用的方法。method参数表示请求方式(GET, POST, PUT等),URLString参数是请求地址,parameter就是请求参数了。encoding参数就是请求参数的编码方式,此处默认是URL编码。headers字典参数就是请求头信息了,默认为nil。下方代码主要是创建NSMutableURLRequest对象,然后将参数进行相应的编码后添加进NSMutableURLRequest对象中,然后调用request()方法发起请求。 下方代码段是上述函数中所调用的request()方法,下方的request()方法负责通过Session创建dataTask,也就是负责执行Data Task任务。然后在初始化Request类的对象时,将创建的Data Task对象传给Request对象。然后将Request对象的 Task Delegate对象存入Manager类的delegate属性中。因为在delegate属性中的代理方法是调用相应的Task Delegate的方法,所以在此有必要进行存储。然后调用Request对象的resume()方法发起数据的网络请求。为了链式调用Request对象的其他方法,所以将Request类的对象进行返回。代码如下所示: 4. Manager中SessionDelegate解析 SessionDelegate可以说是代理的代理,因为在SessionDelegate中有一个subdelegates字典属性,该属性负责存储Request对象中的各个Task Delegate。而SessionDelegate在相应的代理方法中会通过存储的Task Delegate来调用Task Delegate中的方法,所以SessionDelegate说是代理的代理。 下方代码段是SessionDelegate类中部分代码的截图,其中的subdelegates字典属性中存储的就是Request中的TaskDelegate,subdelegateQueue是一个并行队列用来同步执行获取和设置字典中的Task Delegate对象。然后就是为SessionDelegate类定义了一个下标,该下标的功能是以Session Task为下标的形式向subdelegates中添加和获取相应的Task Delegate。该自定义下标就可以让类的对象使用下标的形式来设置和获取属性的值,稍后会给出扩展的Demo。 关于SessionDelegate中所实现的代理方法,在此我们就一执行Data Task请求的didReceiveData代理方法为例。下方截图就是SessionDelegate中的didReceiveData代理方法。代码比较简单,首先判断该代理方法对象的Closure回调变量是否有值,如果有就执行该闭包回调块,如果没有值就获取我们存储的Data Task Delegate, 然后去执行Data Task Delegate中的didReciveData方法。其他方法也于此类似,所以就以点代面,在此就不做过多的赘述了。 5.知识点扩展 接下来有到了举一反三,扩展知识点的时刻了。接下来我们单独来创建一个小实例来看一下Swift中自定义下标是怎么回事。大道至简,接下来我们将上述下标的使用进行简化,创建一个Demo, 然后通过这个Demo来介绍一下下标的使用。 下方代码段就是我们创建的简化版的下标示例,在Swift的类中是支持自定义下标的,自定下标可以让你以下标的形式来访问和设置属性。下方就自定义了一个下标,在下标中设置和返回value属性的值。用法如下所示: 四、Request.swift源码解析 逐渐深入,我们现在来到了Request.swift这个类,因为上面的Manager中的请求最终走到了Request类的位置,所以接下来我们要分析的就是Request.swift源文件中的内容。Request.swift源文件中主要是执行的Data Task请求,并且实现了相应的Data Task Delegate中的方法。其他的任务例如Download Task, Upload Task,Stream Task等会在其他文件中对Request做延展时执行上述这些任务。我们在此就以Data Task为例。Request类中说白了就是负责通过会话创建相应的Task,并实现相应Task的代理方法。 1. Request相关类图 下方类图就是Request相关类图了,Request类及其延展中就是创建各种类型的Task,然后给出相应的Task Delegate。下方类图还给出个各种Task Delegate间的继承关系。Request相关源文件在给出TaskDelegate的代理方法的实现时,也封装了闭包状态下的回调方法。这中做法与SessionDelegate中做法一致。下方会给出具体的介绍。 2.Request类的初始化方法 下方就是Request类的初始化方法,方法需要两个参数,第一个参数是NSURLSession的对象,该对象也就是Manager单例中创建的Session的对象。而第二个参数虽然是Manager传过来的,但是初始化task的任务还得交给Request类来做,Manager来只不过是定义了一个NSURLSessionTask的类型传到了Request中,例如在Manager的request()方法中task是NSURLSessionDataTask,Manager的upload()方法中的task是NSURLSessionUploadTask类型。 在Request的初始化方法中根据Manager单例提供的task的类型来确定是创建DataTaskDelegate、UploadTaskDelegate等。在相应的Task Delegate中会创建相应的Task。我们还以上述的DataTask为例,如果你调用Manager单例中的request()方法就会执行下方的DataTaskDelegate()的初始化。如下所示: 上面的delegate是TaskDelegate类型的,因为UploadTaskDelegate、DownloadTaskDelegate以及DataTaskDelegate都是TaskDelegate的子类,所以此处用到了面向对象的“多态性”。下方两个属性就是Request类中的delegate和task属性,delegate的初始化在上述Requset的初始化方法中,而此处的task是一个存储属性,task的初始化是放在相应的TaskDelegate中的,在TaskDelegate中创建完task对象后再赋值给Request类中的task属性,如下所示: 3. Requset类中的Progress闭包 在使用Request类的对象时,我们可以链式的调用Request中的方法,最常用的就是获取相应任务执行的进度,也就是平时我使用的progress()方法。下方截图中的代码段就是progress()方法的实现。通过Task Delegate的类型来判断目前执行的哪种任务,然后将传过来的progress的闭包赋值给相应的Task Delegate,在这些Task的Delegate中会在相应的回调方法中获取任务执行进度,然后执行下方传入的Closure。 4.Request的resume()方法 下方就是Request类中的resume()方法,其中的代码比较简单。主要是用来记录startTime,然后调用task的resume方法开始执行任务。当然在开始执行任务后要发起相应的通知,此处发出的是DidResume通知。所有的通知类型都在Notifications.swift文件中的Notifications结构体中存储着。Request类中的其他方法,比如suspend()、cancel()方法的实现方式与resume()类似,并且都会发出相应的通知,在此就不做过多的赘述了。 5.Request类中的相关代理类 从第一部分中的类图中我们能看出与Request类相关的代理类,TaskDelegate是所有代理类的基类。在该代理类中其实就是定义了一下必要的属性和NSURLSessionTaskDelegate中对应的回调方法,并且为这些回调方法提供相应的闭包回调的形式。此处就以TaskDelegate代理类为例。下方就是TaskDelegate代理类为NSURLSessionTaskDelegate中相应的代理方法提供的Closure方式。其他的代理类如DataTaskDelegate、DownloadTaskDelegate等与此类似。而相应的代理方法中就是对回调进行了处理,不过在处理之前会判断相应的Closure是否为nil, 如果不为nil的话就执行Closure闭包块中的内容。如果为nil,就执行提供的默认处理。 事无巨细,至此Alamofire中的核心类就已经介绍完毕,因为篇幅有限,其他类在此就不做过多赘述了。其他类以及其他文件中的内容在第一部分中做了概述,其内部的实现细节就不做过多赘述了,在Github上分享的代码对这些类的关键技术细节给出了注释。 在Alamofire框架中大量的使用了延展、闭包以及枚举关联值。特别是在解析网络请求的数据时,将闭包类型作为函数的参数,然后通过闭包变量来提供相应的解析方案,在此就不做过多的赘述了,其他技术细节“仁者见仁,智者见智”。听我说再多,看再多的技术博客如果不亲自的去了解一下,说再多也是没用的,实践出真知。 本文转自zsdnr 51CTO博客,原文链接:http://blog.51cto.com/12942149/1929665,如需转载请自行联系原作者

优秀的个人博客,低调大师

深度解密:人机大战——网红脸识别

雷锋网按:本文作者为Slyvia,ARC增强现实(微信ID:arinchina)文章详细的分析了1)机器和人类在人脸识别方面的不同点;2)人机大战结果的原因分析。 继「围棋」人机大战——以李世石为代表的人类,输给了阿尔法狗代表的计算机后,人类又发起了「人脸识别」之人机大战。这一次是诞生于杭州的人脸识别机器人蚂可,对战「鬼才之眼」王昱珩。 王昱珩是谁? 15 年「最强大脑」中,在同质同量同源的 520 杯水中,他成功指出评审选中的那杯,并精准说出水杯旋转了 15 度,中间经人手,从此,「水哥」一战成名。 这次,对上「万变不离其宗」的网红脸,人类可以一雪前耻么? 结果揭露前,先了解计算机「看人」的套路。 人眼和计算机,都喜欢瞄「点」。只不过,人眼在辨别物体时,往往通过不同点来判断。而计算机则相反,它找的是相同点。 通过摄像头「观察」目标,计算机将拍

优秀的个人博客,低调大师

深度解读 OpenStack Liberty 国内代码贡献

又到了 OpenStack 新版本发布的季节,虽然秋意寒寒,但是仍然挡不住 OpenStack 再次掀起全球关注的热点。这是 OpenStack 第12个版本,与之前的沉稳低调相比,这次的 Release 中一口气多了 5 个新模块,也创下了 OpenStack 项目创建以来的最高纪录。由于天然的架构优势,让 OpenStack 在云计算横行天下的年代游刃有余,已经逐步成为了云平台的即成标准,从 OpenStack 对待 AWS 的 API 兼容的态度就能看出,OpenStack 变得越来越自信。 OpenStack Liberty 完整版本的翻译可见:https://wiki.openstack.org/wiki/ReleaseNotes/Liberty/zh-hans 本次 OpenStack Liberty 更新日志中文版本的翻译工作是由孙琦完成的。 社区贡献分析 本次统计,并没有采用 Review 的数量为依据,而直接采用 commits 的方式,也就是代码实际 merge 入库的数量。 我们仍然要先看一下模块的贡献情况: 与之前Release的特点相似,OpenStack早期的核心模块Nova, Keystone代码commits数量出现明显下滑状态,而Neutron, Heat, Trove, Ceilometer, Cinder等模块都保持着稳中有升的态势。值得关注的是,在排名前20名的项目中,出现了两个直接与Docker有关的项目Kolla和Magnum,一个与docker间接有关的项目Murano。可以预见,OpenStack下一步发展的热点就是在与Docker之间的勾勾搭搭。 特别需要注意的是,在stackalytics.com统计的模块中,在Kilo中是259个,而到了Liberty到了389个,当然有一些项目并非完全是OpenStack的项目,但是也从一个侧面反映出OpenStack以及周边项目的蓬勃发展。 从更新日志中我们也能看到,本次Release的正式项目中,变动较大的是Neutron和Heat两个模块。在经历不断锤炼后,Neutron逐渐走向成熟,但是从生产级别角度看,Neutron的确还有很长的路要走。 国内社区贡献分析 从全球企业的贡献排名来看,排名状况基本变化不大,仍然是HP, Redhat, Mirantis, IBM, Rackspace, Intel, Cisco,但是非常欣喜的,国内的IT的航空母舰华为已经成功杀入前十名,这无疑是振奋人心的事情,希望华为未来能多一些对OpenStack社区的主导力,提高中国在OpenStack社区的地位,当然最好也能扶植一下国内的OpenStack创业公司,实现共同发展、共同进步。华为的主要代码贡献集中在dragonflow,magnum,heat等模块,特别是在dragonflow上,几乎全部是华为贡献的,magnum上也将近有五分之一的代码。 华为社区贡献统计 记得在OpenStack五周年的庆祝活动上,Intel的陈绪博士说过,国内OpenStack贡献企业,就是一朵大云,四朵小云,下面让我们来看看这几朵小云在这个版本的表现。 99cloud社区贡献统计 排名第16位的是99cloud,99cloud自上一个版本排名四朵小云之首后,本次继续强劲来袭,排名创造历史新高,第16名。通过对贡献模块的分析,我们能看出99cloud最大的贡献来自于社区文档,而在项目方面的贡献则主要来自murano-dashboard,horizon,neutron等项目上,从中可以看出99cloud对murano这个applicaton catalog的项目关注程度比较高,可能会在将来的产品中有所体现。从贡献中,我们隐约看到了九州云的副总裁李开总的提交,由此可见九州云为社区贡献的积极程度。 UnitedStack社区贡献统计 排在第30位的是UnitedStack,经过了上一个版本的短暂沉寂后,这个版本卷土重来,杀回前30。从代码贡献来看,UnitedStack的主要贡献来自python-openstackclient以及部署用到的puppet相关代码,当然对neutron、trove、kolla、heat等也有一定数量的贡献。 Kylin Cloud社区贡献统计 排名第38位的是麒麟云,其实麒麟云每次Release中总是有她的身影,但好像总是被忽略的。麒麟云最大的贡献来自Horizon项目,其他模块也有一定数量的贡献。总之,我们想到OpenStack企业的时候,的确应该时常提起麒麟云。 Easystack社区贡献统计 排名第70位的是Easystack,Easystack也属于OpenStack早期创业的公司,对于OpenStack的贡献也是持续的。Easystack最大的贡献来自nova,虽然数量不是很多,但是在国内企业里应该算名列前茅的啦。Easystack对Nova的贡献主要来自对libvirt层的bug修复。 Awcloud社区贡献统计 排名第75位的是海云捷迅,海云应该算是在国内发展比较迅猛的一家OpenStack早期创业公司。他们的贡献主要来自Neutron相关的项目,看起来应该是为了解决项目中出现的实际问题所做的努力。海云的马力应该是公司内部贡献排名第一的,尤其是前一段时间发布的两篇关于”Neutron & OpenStack漫谈”,非常值得一读。 LeTV社区贡献统计 Netease社区贡献统计 排名第94和95位的分别是两家互联网企业,乐视和网易,乐视是最近互联网中使用OpenStack动静最大的一家了,应该能在大规模应用中发现OpenStack很多问题吧。 Huron社区贡献统计 排名第122位的是北京休伦科技有限公司,北京休伦科技有限公司也算是国内最早一批从事OpenStack创业的公司,早在2013年的时候就已经开始投入OpenStack私有云产品相关的研发。北京休伦科技有限公司贡献的代码主要来自Nova和Murano两个模块中,都是北京休伦科技有限公司在开发和项目使用中发现的问题,修复后回馈给社区的,希望北京休伦科技有限公司能在下一个版本Release中贡献更多的力量。 China Mobile社区贡献统计 排名第133位的是中国移动,之前并没有在哪一个排名上看到过中国移动在OpenStack贡献。中国移动应该算是国内运营商领域技术实力较强的一家,也是运营商里开始从事OpenStack预研较早的一家。中国移动有大量的IT资源和设备,理应像AT&T一样在OpenStack领域大有所为。纵观中国移动的社区贡献,主要来自Neutron和Ceilometer两个项目,几个Bug修复都是与Volume相关。 Lenovo社区贡献统计 排名第135位的是联想。不评论了。 排名第139位的是清华大学医学院附属医院,这个有点意思。但是stackalytics.com有Bug,他们的具体统计显示不出来。 H3C社区贡献统计 排名第143位的是H3C。贡献是Nova中的关于VMware的Bug Fix。 由于stackalytics并没有按照区域统计的功能,所以本次统计完全是全自动统计(全靠作者自己手动),所以难免遗漏了为OpenStack贡献的国内企业,如果发生该情况请及时告知。 社区贡献内容分析 从贡献的commits的类型来区分,国内贡献出的代码主要还是以bug为主,这可能也与我们使用的都是OpenStack较成熟的模块有关,本身这些模块成熟程度较高,所以想做blueprint很难。另外一个很重要的原因是和OpenStack管理流程有关的,现在像Nova, Cinder等项目都是需要先Review Specs的,其实就是所谓的设计文档,语言成为国内很多工程师贡献的最大障碍,所以这也导致了Blueprint的贡献度在国内并不高。 Huawei社区贡献——完成Blueprint 纵观整个Blueprint的完成统计情况,华为作为国内最有实力的企业,高居全球第五名,完成最多的模块为cinder和mistral。 之后能完成Blueprint的企业还包括UnitedStack、中国移动、麒麟云、海云捷迅和九州云,但是相比来说数量较少,都是个位数字。 OpenStack在国内发展已经超过了四年的时间,但是遗憾的一点,尽管我们拥有世界上最多的开发人员,但是我们对社区仍然没有话语权,国内的用户的需求无法对社区上游形成影响,导致很多本地化定制的需求无法真正的在社区版本代码得到体现。所以如何让中国的声音出现在社区,是我们所有OpenStack人需要思考的问题。欣喜的一点,本土的巨头华为已经身先士卒,投入很大的力量搞OpenStack的社区贡献,我们更希望越来越多的国内传统IT巨头能够意识到这个问题,投身于开源的事业中,否则我们又在起跑线上输给了别人。 以上仅代表作者个人观点,如有任何异议,欢迎批评指正。 文章转载自 开源中国社区[https://www.oschina.net]

优秀的个人博客,低调大师

Cortex-M3启动深度解析

Cortex-Mx启动,备忘,以免将来忘记。 中断向量表不用说,从重置中断开始吧 LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 这里一共就执行了两个函数,SystemInit和__main。 我们一般在SystemInit里面配置系统时钟,这里跳过。 __main是我们今天的重点。 __main: 0x080000C0 4804 LDR r0,[pc,#16] ; @0x080000D4 0x080000C2 4685 MOV sp,r0 #设置栈顶 _main_scatterload: 0x080000C4 F000F956 BL.W __scatterload (0x08000374) #分散加载(拷贝初始值、清零变量) __main_after_scatterload: 0x080000C8 F000F8D4 BL.W __cpp_initialize__aeabi_ (0x08000274) #C++初始化(全局对象构造函数执行) _main_cpp_init: 0x080000CC 4800 LDR r0,[pc,#0] ; @0x080000D0 0x080000CE 4700 BX r0 #进入C++的main函数 分散加载这里将会初始化我们的全局静态变量 .text:00000000 __scatterload_rt2 .text:00000000 LDR R4, =Region$Table$Base .text:00000002 MOVS R5, #1 .text:00000004 LDR R6, =Region$Table$Limit .text:00000006 B loc_14 .text:00000008 ; --------------------------------------------------------------------------- .text:00000008 .text:00000008 loc_8 ; CODE XREF: __scatterload_rt2+16j .text:00000008 LDR R3, [R4,#0xC] .text:0000000A LDMIA R4!, {R0-R2} .text:0000000C ORRS R3, R5 .text:0000000E SUBS R4, #0xC .text:00000010 BLX R3 .text:00000012 ADDS R4, #0x10 .text:00000014 .text:00000014 loc_14 ; CODE XREF: __scatterload_rt2+6j .text:00000014 CMP R4, R6 .text:00000016 BCC loc_8 .text:00000018 BL __main_after_scatterload 可能汇编看起来不是很直观,我们配合看F5得到的反编译C代码 void _scatterload_rt2() { _DWORD *i; // r4@1 for ( i = &Region__Table__Base; (_UNKNOWN *)i < &Region__Table__Limit; i += 4 ) ((void (__fastcall *)(_DWORD, _DWORD, _DWORD))(i[3] | 1))(*i, i[1], i[2]); _main_after_scatterload(); JUMPOUT(&Region__Table__Base); } 从上面看出,有一张区域表,每4个int作为一段,每一段前三个为参数,第四个为函数指针。 经过调试得知: 第一个函数是__scatterload_copy,从某个Flash地址把数据拷贝给RAM里面的变量,也就是带有初始值的全局变量; 第二个函数是__scatterload_zeroinit,顾名思义,就是全局变量清零,只要没有初始值的全局变量,都清零,堆空间和栈空间一块清。 而在汇编文件里面我们有AREAHEAP,NOINIT, READWRITE, ALIGN=3。显然其中的NOINIT并没有生效 ER_IROM1:0800D704 Region$Table$Base DCD 0x800D72C ; #要拷贝的初始值来源,紧跟在固件源代码后面 DATA XREF: ER_IROM1:__scatterload_rt2o ER_IROM1:0800D704 ; ER_IROM1:off_8000390o ER_IROM1:0800D708 DCD 0x20000000 #要复制初始值的起始地址 ER_IROM1:0800D70C DCD 0xCC #带有初始值的区域大小 ER_IROM1:0800D710 DCD __scatterload_copy ER_IROM1:0800D714 DCD 0x800D7F8 ER_IROM1:0800D718 DCD 0x200000CC #要清零的变量起始地址 ER_IROM1:0800D71C DCD 0x132C #要清零的变量大小 ER_IROM1:0800D720 DCD __scatterload_zeroinit ER_IROM1:0800D724 EXPORT SHT$INIT_ARRAY$Base 因此,针对__scatterload_zeroinit而言,为了加快启动速度,建议堆空间设得尽量小,然后在SmartOS系统初始化的时候再重新设置堆空间 我不相信神话,我只相信汗水!我不相信命运,我只相信双手! 分类: 物联网 本文转自大石头博客园博客,原文链接:http://www.cnblogs.com/nnhy/p/cortex_m3_boot.html,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册