Updates from 六月, 2014 Toggle Comment Threads | 键盘快捷键

  • Roger 7:28 pm on June 5, 2014 固定链接 | 回复
    Tags:   

    关于 Apple Metal API 的一些想法 

    在看完 Metal 的开发文档后,除了官方所宣称的一些优点外(比如说更容易理解和使用的 API,更直接和精细的硬件控制,减少 GPU 使用过程中的 CPU 额外开销等等),从我有限的 GLES 开发经验看来,以下一些方面更让人兴奋。

     

    更方便和友好的多线程 GPU 渲染支持

     

    GLES 的设计,所有东西都必须跟一个 GL Context 绑定,由 GL Context 内部所控制的状态机驱使,而 GL Context 又跟单个线程本身紧密绑定在一起,导致很难支持构建一个良好的多线程 GPU 渲染架构,Chrome 的解决办法是在 GL 之上构建了一套 GL Context 的 Proxy 机制,Proxy GL Context 允许多个线程创建不同的实例,而每个 Proxy GL Context 内部使用一个 Command Buffer 跟真正的 GL Context 进行通讯和保持同步。

     

    而 Metal 在设计时就考虑了如何更好地支持多 CPU 线程同时“使用“ GPU,它的 Command Queue/Command Buffer 的模型虽然有点类似 Chrome 的 Proxy 机制,不同的 CPU 线程可以 Encode Commands 到不同的 Command Buffer,然后放入同一个 Queue 里面等待 GPU 的真正执行。但是 Metal 的这种内建的支持当然比 Chrome 在 GL 上面的封装来的更方便,易用和高效,也没有那么多限制。

     

     

     

    GPU 渲染和计算的无缝整合(Rendering and Compute)

     

    虽然 GLES 未来也会支持 Compute Shader,但是能否做到 Metal 这样无缝的衔接(包括 Command 的执行和资源的共享)就比较难说了。

     

    统一的资源内存管理模型,允许 CPU 直接访问 Metal Resource (Buffer/Texture) 的存储内存,并设定了明确的 CPU/GPU 同步时机

     

    虽然 GLES 3 可以通过 Pixel Buffer Object 支持一块 GPU 控制的内存可供 CPU 直接访问,但是毕竟限制太多,用途有限(另外也由于 GLES 本身缺少良好的多线程支持)。而 Android 的 GraphicsBuffer 系统/硬件兼容性问题成堆,性能参差不齐,没有明确的 CPU/GPU 同步时机,也只能用于特定场景。

     

    简而言之,Metal 让 CPU/GPU 之间的协作更紧密和高效,允许 CPU 通过更多方式,更灵活地使用 GPU,把更多的任务交由 GPU 来完成。

     
    • 韩国女装品牌网站 8:51 下午 on 七月 2, 2016 固定链接 | 回复

      小心你的思想,它们会转为言辞;小心你的言辞,它们会转为行动;小心你的行动,它们会转为习惯;小心你的习惯,它们会转为个性;小心你的个性,它们会成为你的命运。

  • Roger 2:28 pm on March 26, 2014 固定链接 | 回复
    Tags: , meminfo, memtrack   

    Android 4.4 meminfo 实现分析 

    Android提供了一个名为meminfo的小工具帮助应用分析自身的内存占用,并且在4.4还新增了memtrack HAL模块,SoC厂商通过实现memtrack模块,让meminfo可以获取GPU相关的一些内存分配状况。了解meminfo的实现,对我们更深入了解应用的内存占用状况是很有帮助的。而这篇文章的目的就是分析Android 4.4 meminfo的内部实现源码,让开发者通过这些信息可以更了解自己应用的内存占用状况。

    在控制台输入命令”adb shell dumpsys meminfo YOUR-PACKAGE-NAME”,可以看到类似下图的结果:

    <pre><code>
    ** MEMINFO in pid 14120 [com.UCMobile.test] **
    Pss Private Private Swapped Heap Heap Heap
    Total Dirty Clean Dirty Size Alloc Free
    —— —— —— —— —— —— ——
    Native Heap 187886 187872 0 0 325232 174093 38594
    Dalvik Heap 24801 24444 0 0 41476 35899 5577
    Dalvik Other 700 700 0 0
    Stack 508 508 0 0
    Other dev 33564 32600 4 0
    .so mmap 9019 1244 7268 0
    .apk mmap 101 0 16 0
    .ttf mmap 1330 0 696 0
    .dex mmap 2248 0 2248 0
    code mmap 985 0 188 0
    image mmap 1182 908 12 0
    Other mmap 130 4 108 0
    Graphics 25504 25504 0 0
    GL 2196 2196 0 0
    Unknown 32476 32476 0 0
    TOTAL 322630 308456 10540 0 366708 209992 44171
    </code></pre>

    实际的调用代码入口在android.os.Debug.java和对应的CPP文件android_os_Debug.cpp,Debug.java的getMeminfo方法实际上调用了android_os_Debug.cpp的android_os_Debug_getDirtyPagesPid方法。

    <pre><code>
    static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
    jint pid, jobject object)
    {
    stats_t stats[_NUM_HEAP];
    memset(&stats, 0, sizeof(stats));

    load_maps(pid, stats);

    struct graphics_memory_pss graphics_mem;
    if (read_memtrack_memory(pid, &graphics_mem) == 0) {

    }


    }

    static void load_maps(int pid, stats_t* stats)
    {
    char tmp[128];
    FILE *fp;

    sprintf(tmp, “/proc/%d/smaps”, pid);
    fp = fopen(tmp, “r”);
    if (fp == 0) return;

    read_mapinfo(fp, stats);
    fclose(fp);
    }
    </code></pre>

    从上面的代码可以看到,android_os_Debug_getDirtyPagesPid方法先调用了load_maps方法,而load_maps方法要做的事情也很简单,它打开/proc/PID/smaps虚拟文件,读取里面的信息,在已ROOT的设备上,我们可以通过“adb shell cat /proce/PID/smaps”直接将这个虚拟文件的信息打印在控制台上。

    <pre><code>
    80ff5000-810f2000 rw-p 00000000 00:00 0 [stack:12211]
    Size: 1012 kB
    Rss: 4 kB
    Pss: 4 kB

    81100000-811a4000 rw-s 000f4000 00:0b 6285 /dev/kgsl-3d0
    Size: 656 kB
    Rss: 652 kB
    Pss: 352 kB

    811d1000-811e0000 rw-p 00000000 00:00 0 [anon:libc_malloc]
    Size: 60 kB
    Rss: 60 kB
    Pss: 60 kB

    Name: [anon:libc_malloc]
    </code></pre>

    “adb shell cat /proce/PID/smaps”输出的信息如上图所示,它实际上是应用的userspace地址空间的内存分配表,记录了应用分配的每一块内存的地址,类别,大小等信息,而load_maps方法调用read_mapinfo方法从这个表里面读出每一块内存的分配信息,分类进行累加,得出Native Heap,Dalvik Heap等各个类别的内存占用。

    但是应用所使用的全部内存里面,有一些内存块是不映射到进程的userspace地址空间的(主要是GPU所使用的内存),这些内存块的信息在smaps里面无法找到,所以在Android 4.4里面新增了一个memtrack的HAL模块由SoC厂商实现,如果SoC厂商实现了memtrack模块,meminfo则可以通过libmemtrack的调用获取一些跟GPU相关的内存使用信息。所以我们看到android_os_Debug_getDirtyPagesPid方法通过调用read_memtrack_memory方法来读取Graphics,GL这两项的内存使用信息。

    <pre><code>
    /*
    * Uses libmemtrack to retrieve graphics memory that the process is using.
    * Any graphics memory reported in /proc/pid/smaps is not included here.
    */
    static int read_memtrack_memory(struct memtrack_proc* p, int pid,
    struct graphics_memory_pss* graphics_mem)
    {
    int err = memtrack_proc_get(p, pid);

    ssize_t pss = memtrack_proc_graphics_pss(p);

    graphics_mem->graphics = pss / 1024;

    pss = memtrack_proc_gl_pss(p);

    graphics_mem->gl = pss / 1024;

    pss = memtrack_proc_other_pss(p);

    graphics_mem->other = pss / 1024;

    return 0;
    }
    </code></pre>

    read_memtrack_memory方法的实现如上图所示,它读取了Graphics,GL,Other这三类内存信息,而这三个类别的定义在hardware/memtrack.h里面。

    <pre><code>
    /*
    * The Memory Tracker HAL is designed to return information about device-specific
    * memory usage. The primary goal is to be able to track memory that is not
    * trackable in any other way, for example texture memory that is allocated by
    * a process, but not mapped in to that process’ address space.
    * A secondary goal is to be able to categorize memory used by a process into
    * GL, graphics, etc. All memory sizes should be in real memory usage,
    * accounting for stride, bit depth, rounding up to page size, etc.
    *
    * A process collecting memory statistics will call getMemory for each
    * combination of pid and memory type. For each memory type that it recognizes
    * the HAL should fill out an array of memtrack_record structures breaking
    * down the statistics of that memory type as much as possible. For example,
    * getMemory(<pid>, MEMTRACK_TYPE_GL) might return:
    * { { 4096, ACCOUNTED | PRIVATE | SYSTEM },
    * { 40960, UNACCOUNTED | PRIVATE | SYSTEM },
    * { 8192, ACCOUNTED | PRIVATE | DEDICATED },
    * { 8192, UNACCOUNTED | PRIVATE | DEDICATED } }
    * If the HAL could not differentiate between SYSTEM and DEDICATED memory, it
    * could return:
    * { { 12288, ACCOUNTED | PRIVATE },
    * { 49152, UNACCOUNTED | PRIVATE } }
    *
    * Memory should not overlap between types. For example, a graphics buffer
    * that has been mapped into the GPU as a surface should show up when
    * MEMTRACK_TYPE_GRAPHICS is requested, and not when MEMTRACK_TYPE_GL
    * is requested.
    */

    enum memtrack_type {
    MEMTRACK_TYPE_OTHER = 0,
    MEMTRACK_TYPE_GL = 1,
    MEMTRACK_TYPE_GRAPHICS = 2,
    MEMTRACK_TYPE_MULTIMEDIA = 3,
    MEMTRACK_TYPE_CAMERA = 4,
    MEMTRACK_NUM_TYPES,
    };
    </code></pre>

    Graphics对应了MEMTRACK_TYPE_GRAPHICS,GL对应了MEMTRACK_TYPE_GL,而Other实际上是MEMTRACK_TYPE_OTHER,MEMTRACK_TYPE_MULTIMEDIA,MEMTRACK_TYPE_CAMERA这三项之和。memtrack是由SoC厂商实现的,在AOSP的源码里面我们可以找到高通的实现源码,在msm8974/libmemtrack/kgsl.c里面。

    <pre><code>
    int kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type,
    struct memtrack_record *records,
    size_t *num_records)
    {

    sprintf(tmp, “/d/kgsl/proc/%d/mem”, pid);
    fp = fopen(tmp, “r”);

    if (type == MEMTRACK_TYPE_GL) {
    sprintf(tmp, “/proc/%d/smaps”, pid);
    smaps_fp = fopen(tmp, “r”);

    }

    while (1) {
    unsigned long uaddr;
    unsigned long size;
    char line_type[7];
    int ret;

    if (fgets(line, sizeof(line), fp) == NULL) {
    break;
    }

    /* Format:
    * gpuaddr useraddr size id flags type usage sglen
    * 545ba000 545ba000 4096 1 —-p gpumem arraybuffer 1
    */
    ret = sscanf(line, “%*x %lx %lu %*d %*s %6s %*s %*d\n”,
    &uaddr, &size, line_type);
    if (ret != 3) {
    continue;
    }

    if (type == MEMTRACK_TYPE_GL && strcmp(line_type, “gpumem”) == 0) {
    bool accounted = false;
    /*
    * We need to cross reference the user address against smaps,
    * luckily both are sorted.
    */
    while (smaps_addr <= uaddr) {
    unsigned long start;
    unsigned long end;
    unsigned long smaps_size;

    if (fgets(line, sizeof(line), smaps_fp) == NULL) {
    break;
    }

    if (sscanf(line, “%8lx-%8lx”, &start, &end) == 2) {
    smaps_addr = start;
    continue;
    }

    if (smaps_addr != uaddr) {
    continue;
    }

    if (sscanf(line, “Rss: %lu kB”, &smaps_size) == 1) {
    if (smaps_size) {
    accounted = true;
    accounted_size += size;
    break;
    }
    }
    }
    if (!accounted) {
    unaccounted_size += size;
    }
    } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, “ion”) == 0) {
    unaccounted_size += size;
    }
    }


    }
    </code></pre>

    kgsl_memtrack_get_memory是memtrack的getMemory方法的具体实现,我们可以看到它实际上是读取一张内部的GPU内存分配表的信息(虚拟文件/d/kgsl/proc/PID/mem),在已ROOT的设备上,我们可以通过“adb shell cat /d/kgsl/proc/PID/mem”将这张内存分配表的信息打印到控制台上,如下图所示:

    <pre><code>
    gpuaddr useraddr size id flags type usage sglen
    7565e000 00000000 4096 1 —-p gpumem arraybuffer 1
    756bc000 00000000 65536 2 -r–p gpumem command 16
    756cd000 00000000 65536 3 -r–p gpumem command 16
    756de000 00000000 65536 4 -r–p gpumem command 16
    756fb000 00000000 4096 5 —-p gpumem gl 1
    75fe2000 00000000 262144 6 —-p gpumem gl 64
    76023000 00000000 8192 7 —-p gpumem gl 2
    76026000 00000000 8192 8 —-p gpumem gl 2
    76029000 00000000 4096 9 —-p gpumem texture 1

    94d71000 00000000 131072 362 —-p gpumem vertexarraybuff 32
    94da0000 00000000 667648 176 –l-p gpumem texture 163
    94e44000 00000000 131072 363 —-p gpumem any(0) 32
    94e65000 00000000 131072 364 —-p gpumem any(0) 32
    c0000000 00000000 17268736 31 –L– ion egl_image 4216
    c1100000 00000000 8257536 36 –L– ion egl_surface 21
    c1900000 00000000 8257536 164 –L– ion egl_surface 21
    c2100000 00000000 8257536 175 –L– ion egl_surface 21
    </code></pre>

    其中ion类型(由ION内存分配器分配的内存)的内存块统计到Graphics类别里面,从上图我们可以看到有三块egl_surface,它们对应应用所使用的窗口的三个Buffer,还有一个egl_image暂时不清楚用途(这块17M的egl_image,在不同进程里面的地址和ID号都是一样的,所以猜测实际是Android在不同应用之间分享的Assert Atlas,Android 4.4开始,把系统的图片资源拼接成一大块纹理,然后通过GraphicBuffer + EGLImage在不同的应用之间共享),这些都是应用启动后Android自动分配的。gpumem类型的内存块统计到GL类别里面,包括GL里面的纹理(texture),各种shader,vertex buffer等等。另外,因为有些内存块映射到了userspace,有些则没有映射,所以映射到userspace的内存块会被标记为accounted,避免meminfo重复计数,meminfo最终显示的Graphics和GL的内存值是哪些没有映射到userspace的内存块的大小之和。

     
    • Luke 2:40 下午 on 三月 26, 2014 固定链接 | 回复

      看起来亮点主要在gpu的内存信息。期待实时连线的图形化工具能做的更好。

  • Roger 8:27 pm on December 29, 2013 固定链接 | 回复
    Tags: , , , ,   

    我的2013 – 年终总结 + 浏览器渲染发展的一些思考 

    又到一年的年末,秉承传统,继续为这一年写一篇总结的文章。今年依旧延续了进入公司后每年都更换不同小组的传统,下半年调到了内核渲染组,不过之前在技术研究组的工作也一直是专注于浏览器渲染相关的技术研究,所以这次调动也算是顺理成章了,工作内容基本上没有任何变化。

     
    今年一年以来的工作都跟硬件加速渲染有关,除了在不断完善和优化原有的硬件加速/图层混合加速的渲染架构,保证UC加速版的顺利发布外,另外最主要的工作就是设计和实现2D Canvas的加速渲染架构,从年初的初始实现版本到UC9.4加速版的版本,其间一共更替了三套不同的架构,而且每一次基本上都是完全推倒重来,但也解决了前一版本无法克服的一些内在缺陷,当前最新的架构基本上已经没有什么性能上明显的瓶颈,也足够灵活地根据不同的设备动态调整自己的行为,在兼容性,资源占用,性能这三者之间取得一个较好的平衡。
     
    回顾自己这一年的收获,通过研究Android图形子系统的底层实现,研究GPU和其它各种硬件的工作原理,自己对渲染架构和性能的理解也越来越深刻。“物尽其用,要事优先”是自己对高性能渲染架构的总结,一个高性能的渲染架构,设计者需要对硬件有相当的认识,知道如何将一个完整的渲染任务合理地进行分解,然后调度不同的硬件尽可能并发地完成它;要了解哪里是性能的瓶颈,哪部分是关键的任务,要保证关键任务优先获得资源的分配,尽可能降低瓶颈的影响。
     
    下半年开始,在和主管的工作总结中,还有职业等级评定的答辩会议上,都不断地被问到下面这两个问题,同时自己也在不断地进行思考。
    • 浏览器的渲染架构还有没有可能有更大的性能突破?
    • 浏览器能不能够成为一个承载游戏运行的良好平台,使得H5游戏能够跟原生游戏在同一层面竞争?
     
    浏览器的渲染架构还有没有可能有更大的性能突破?
     
    目前基于WebKit或者Blink内核浏览器的渲染架构,虽然各自的实现不太一样,但是整体架构设计都是由Apple奠定的,Apple当时把自己在MacOS上的那套Layer Rendering的渲染架构引入WebKit,率先在Safari上实现了Accelerated Compositing(图层混合加速),Chrome接着完成了自己的图层混合加速实现,而Android直到3.x的系统浏览器才开始支持,到了4.1才算是比较完善。虽然我不太了解Firefox的渲染架构实现,不过之前看过的一些文章介绍,思路总体上应该跟WebKit差不多。
     
    图层混合加速将渲染任务分解为Paint(绘制)和Composite(混合),绘制由WebKit内核自身使用CPU在一个独立的线程完成,绘制或者光栅化后的结果Layer Buffer(图层缓存)被发送到混合线程,由GPU来进行混合,而Blit(缓存的混合)则是GPU最擅长的工作,甚至可能不需要动用GPU的3D加速单元,使用2D Blitter就够了。
     
    这种架构主要的缺陷在于:
    1. 为了保证渲染性能和效果,浏览器需要大量的图层缓存,尤其对于是一些图层非常复杂,数量非常多的网页,这个问题在移动设备上更加明显;
    2. 由于绘制仍然使用CPU,对于普通的网页,绘制任务主要由图片,文本,各种不同图形的填充(使用纯色,渐变或者纹理)组成,CPU在大部份情况下的确做的比GPU更好,而且资源消耗更少,另外也有助于让GPU更专注于混合任务;但是对一些复杂的动态特效,像是CSS Filter的使用,单纯靠CPU会很困难,并且这种先绘制再混合的方式对于这些动态特效来说反而会造成性能上的损失,并且需要更多缓存;
    第一个问题,如果GPU能够支持一种无损压缩的纹理作为图层缓存,并且压缩可以高效实时的完成(甚至可以使用GPU,在纹理上传的同时完成压缩),就能够得到极大的缓解(对于网页这种大部份以文本和图形为主的位图,压缩率应该非常高,使用ZIP压缩1/10都是很正常的),不过在了解了一些纹理压缩相关的知识后,发现这一点的确不太可能,GPU主要还是为了游戏设计的,而游戏使用的都是事先生成的压缩纹理,并且GPU为了读取压缩纹理时的速度考虑,不可能支持可变压缩率,所以也无法支持无损压缩。
     
    第二个问题,可能的答案是将一部分绘制任务丢到混合线程直接由GPU来完成。不过困难在于两个方面:首先是否能够对绘制任务进行合理的分解,将其中一部分适合GPU完成的任务由GPU在混合线程直接进行绘制,而剩下的仍然保持原有的方式,简单说就是实现一种Hybrid Rendering架构;另一方面是使用GPU做缓存的混合是比较简单的,但是要直接完成复杂的绘制则比较困难,如果使用OpenGL,意味着要实现各种不同绘制的Shader,如果使用OpenVG这样的矢量图绘制API,貌似硬件兼容性和系统支持程度又有很多问题(Android系统本身是不支持OpenVG的,即使大部份GPU硬件上都支持)。除此之外使用RenderScript或者OpenCL这样的异构计算API来进行GPU加速绘制也是一种可能的方式。
     
    浏览器能不能够成为一个承载游戏运行的良好平台,使得H5游戏能够跟原生游戏在同一层面竞争?
     
    回答这个问题之前,先看一下现状,浏览器目前是通过2D Canvas和3D Canvas(WebGL)来支持2D/3D的即时绘图,这也是目前H5游戏的基础。在Android平台上,Chrome和UC都比较完整实现了2D Canvas的GPU加速,并且Chrome已经支持WebGL,UC接下来也会提供WebGL的支持,而WebGL本来就是对应到GLES。使用2D/3D Canvas开发H5游戏,存在的一些性能问题是:
    1. Canvas元素只是网页中所有元素的其中一个,所以它的绘制必须先绘制到一个单独的缓存中,仍然再跟其它元素的图层缓存进行混合输出,这个会带来一些额外的开销,导致性能损耗。不过这个问题还好,对PC来说这个额外开销不算高,而移动设备GPU的性能也越来越好(不过分辨率飙升过快也是一个问题…)
    2. 2D Canvas只提供了最基础的绘图API,难以通过这些API高效实现各种复杂的特效,比如说要实现一个粒子效果,不得不调用几十次甚至上百次drawRect或者drawBitmap,这样的效率非常低。而WebGL还好,可以允许游戏自己直接控制Buffer,自己编写Shader实现各种特效,直接交由GPU运行,从这点看,长远来说WebGL对游戏还是更有前途一些,不过相对来说,它的开发难度就要高不少(即使是使用2D Canvas开发的游戏,很多游戏也会在一些静态不需要太高性能的场景改成使用CSS+DIV来降低开发难度);
    3. 无论是2D Canvas也好,WebGL也好,它们都只提供了绘图API,离一个完整的游戏引擎相去甚远,而要依靠JS实现一个高性能的大型游戏引擎(包括物理运动引擎等)用来支撑一个大型游戏,受限于JS本身的性能,并且缺少底层硬件的直接控制能力,这点不得不说是最大的困难;
    对于第三点,Firefox和Chrome的解决思路完全不同:
    • Chrome通过Native Client允许原生代码直接在浏览器提供的一个受限环境里面运行;
    • Firefox通过ASM.js + WebGL的方式,遵循ASM.js语法的代码仍然是标准的JS代码,但是特殊的语法使得JS虚拟机可以直接将它们翻译成机器码,高效地运行;
    这两种方式先不谈技术本身的成熟度,共同存在的问题就是它们都太过复杂,游戏开发者不直接使用Cocos2D或者Unity3D这样成熟的游戏引擎开发原生游戏而使用Native Client或者ASM.js +WebGL,那简直就是脱裤子放屁,多此一举。
     
    有没有第三种解决问题的思路,我个人认为,浏览器自带游戏引擎(自行开发或者整合第三方的游戏引擎),然后通过一套标准的游戏引擎API供JS调用是一种可行的方式,这样JS就基本上变成像Lua这样的场景控制脚本,这种方式能够同时解决性能的问题和游戏开发难度的问题,当然它的问题是这样的游戏引擎标准API的制定和浏览器的实现还是相当虚无缥缈的事情……
     
    除了性能问题,H5游戏还有打包,发行等问题,不过这些可以通过打包应用(Packaged App)和Web App Store来解决。
     
    最后是我这一年写的比较满意的一些文章:
    1. Why Your Android Apps Suck https://plus.google.com/104793567654398886385/posts/TEr9MYV7tVy
    2. Android GraphicBuffer Introduction and Its Usage in Rendering https://plus.google.com/104793567654398886385/posts/j1LcfHAr5BS
    3. High Performance Canvas Game for Android(高性能Android Canvas游戏开发) http://tech.uc.cn/?p=2414
     
    • Luin 8:49 下午 on 十二月 29, 2013 固定链接 | 回复

      收获很多,多谢

    • Luke 12:42 上午 on 十二月 30, 2013 固定链接 | 回复

      好习惯啊,而且都是干货。
      游戏是一种对浏览器App较高强度的考验,而且前景不错,以游戏的性能来作为评价指标也不失为一个好办法。
      顺着你的思路,我觉得优化空间应该还是有的:
      1. 纹理方面: a. 元素很多的页面是否做到了纹理拼接和压缩?(但对应的缓存应该还是需要的吧)
      b. 纹理压缩算法本身可以优化。一方面可以考虑并行运算的优化,另外一方面各种算法在内存消耗和运算消耗方面可以做trade-off。
      2. 更多元素使用GPU绘制,包括css3的效果等。理论上好像基于加速的skia就好?
      3. js引擎的继续优化。
      针对游戏开发,我觉得使用游戏开发套件或者引擎来开发肯定会是主流了,基于WebGL作为图形引擎的应该会成为主流,不用过分担心2D游戏的效率问题。
      Native Client技术很好,但暂时来说我觉得和Android NDK之于SDK一样,作为辅助或者完成一部分关键功能比较合适,主流的开发环境还是JS+HTML5。不过谁知道以后会不会有NaCL的游戏引擎?再说了Js后端也可能用PNacl/LLVM啊。
      从实用的角度来说,UC还可以发布一个基于浏览器的游戏引擎。

    • 艾楠 3:11 下午 on 三月 31, 2014 固定链接 | 回复

      好习惯!~

    • 韩国女装品牌网站 12:32 下午 on 三月 25, 2016 固定链接 | 回复

      世间有许多事功亏一篑的主要原因就是意志不坚定,不能坚持到底。现实生活中,如果没有坚定意志,我们就不能享受成功的幸福。

    • 韩国食品网上商城 12:36 下午 on 三月 25, 2016 固定链接 | 回复

      成功的人,是在无数次投资失败后站起来的。

    • 韩国时尚购物起义 1:08 下午 on 三月 25, 2016 固定链接 | 回复

      对投资而言,欲速则不达

    • 韩国创意设计用品网站 8:36 上午 on 六月 29, 2016 固定链接 | 回复

      像采金一样追求知识。

  • Roger 4:11 pm on January 2, 2013 固定链接 | 回复  

    “不明觉厉”的“远景战略规划” 

    6597394122587065910

     

     

    以前一直觉得公司高层所谓的“远景战略规划”是一个相当“不明觉厉”的东西,可是去年年会老总的两艘航母与一群护卫舰的理论言犹在耳,不到年底,护卫舰就已经沉得七七八八,两艘航母也只剩下一艘(还好另外一艘还算康健),再往前追溯,直到2011年公司还认为塞班平台仍然大有作为,一个重量级的产品到了第三季度还把研发的重心放在塞班,直到第四季度才皤然醒悟,从这就可以知道所谓高层的“远景战略规划”其实也是一个相当不靠谱的东西,决策失误把一个诺大的公司在短期内直接玩死的例子比比皆是。就像我的上一家公司,花了5年的时间建设了一个还算完备的研发中心,发展到接近500人的规模,也培养出不少能力不错的工程师,人员的梯队建设,团队的建设还算良好,结果没两年时间就已经人走的走,散的散,离最后卷铺盖关门也就一步之遥,这就是所谓的“远景战略规划”了。

    不过今年的三大重心理论还算比较靠谱,毕竟在国内,流量变现的最佳途径一直以来都是非游戏莫属。

     
    • cmxz 8:55 下午 on 一月 2, 2013 固定链接 | 回复

      意思是UC要把重心放在游戏了?

    • Roger 7:05 下午 on 一月 3, 2013 固定链接 | 回复

      除了浏览器外吧

    • chen 9:32 上午 on 一月 4, 2013 固定链接 | 回复

      老板最喜欢搞什么什么理论的了,尤其是非技术出身的。哎。所有的什么理论在快速的技术更新中成了一坨屎

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
回复
e
编辑
o
Show/Hide comments
t
返回顶部
l
Go to login
h
Show/Hide help
shift + esc
取消