2016年5月21日 星期六

[C++] chromium WeakPtr implementation

C++11 provide weak_ptr for NOT sharing shared_ptr with other ref-counted pointer. Here is basic idea about how to implement it:




          +-------------->  T object  <-----------------------+
          +                                                   +
       T*ptr                                                T*ptr
+---------------+  ref   +-----------------+  ref  +---------------------+
| WeakReference | +----> | Flag (ref count)| <-----+ WeakReferenceOwner  |
+---+-----------+        +----------+------+       +------+--------------+
    |                               ^                     |
    |                               +---------------------+ 
    |                               |    Invalidate: when last WeakReferenceOwner 
    |                               |      deleted or owner want to invalidate object.
    |                               |
    +-------------------------------+

 Check Flag validate before access object

The basic idea is we create class (WeakReference/WeakReferenceOwner) which share a ref-count flag which will indicate whether the reference object is still valid. Whenever you want to access the T* object, WeakReference will first check flag first, and return NULL if flag is invalid. This method could prevent leak large memory usage if the real T* object is large because only a small flag is shared.

2015年6月28日 星期日

[Note] Fighting spam with Haskell

Some note after reading

https://code.facebook.com/posts/745068642270222/fighting-spam-with-haskell/

其中application do-notation


do
  x <- a
  y <- b
  return (f x y)

will translate to

(\x y -> f x y) <$> a <*> b

if x and y are independent!

所以如果沒有dependant關係的operation, 就可以自動dispatch (ex: network resource fetching)! 雖然這更改了預設do-notation的語義, 不過對於developer而言, 可讀性應該大大提高了.

Reference:
HAXL haskell lib

2014年6月22日 星期日

Skia debugger

Skia is 2D graphics library, they provide a debugger to provide step-by-step drawing command.

Sync skia

https://sites.google.com/site/skiadocs/developer-documentation/contributing-code/downloading

Build skia

https://sites.google.com/site/skiadocs/user-documentation/quick-start-guides/linux
https://sites.google.com/site/skiadocs/developer-documentation/skia-debugger


git log to find out the match commit whose PICTURE_VERSION match android/chromium skia
PICTURE_VERSION = 10 --> 2cf444f7040614b43af67e368f3aa636ebeaa45a

# sync to specific revision
# edit .gclient
modify "safesync_url": "rev",

# create file rev and copy sha2 hash to this file
# sync
$ gclient sync
$ ./gyp_skia
# then you can build debugger & tools

Generate .skp file which is used for skia debugger

   SkPicture *pict = new SkPicture;
   SkCanvas *picCanvas = pict->beginRecording(width, height, 0);
   // do your skia drawing ...
   pict->endRecording();
   SkString path(".skp file path");
   SkFILEWStream stream(path.c_str());
   pict->serialize(&stream);
   delete pict;

Note

Make sure SkPicture.h PICTURE_VERSION is match Skia debugger

Android touch event system

Overview

Touch event start from top to bottom (each view can decide whether to intercept event), then back up from bottom to top until some view consumed it!

Overview Flow

Activity.dispatchTouchEvent -> Root View. dispatchTouchEvent
                                                       -> .... -> bottom view.dispatchTouchEvent
   (back up) -> ... -> Root View.onTouchEvent -> Activity.onTouchEvent


Detail flow inside UI view

ViewGroup.dispatchTouchEvent()

  • onInterceptTouchEvent()
    • Check if it should supersede children
    • Return true once consumes all subsequent events
  • For each child view, in reverse order they were added
    • If touch is relevant (inside view), child.dispatchTouchEvent()
    • If not handled by previous, dispatch to next view
  • If no children handle event, listener gets a chance
    • OnTouchListener.onTouch()
  • If no listener, or not handled by child
    • OnTouchEvent

Intercept touch event


  • Override ViewGropu.onInterceptHoverEvent and return true
  • After return true, all subsequent events for the current gesture will come to your onTouchEvent() directly
  • onInterceptHoverEvent  will not be called for input event of current gesture  
  • Current target view will receive ACTION_CANCEL
  • Intercept cannot be reversed until the next gesture

Misc

  • use TouchDelegate if you want to touch area different from view bounding

Reference

2014年1月27日 星期一

[Android] CPU profiler

Android 有提供java level的profiler
詳情請看 http://developer.android.com/tools/debugging/debugging-tracing.html

使用方法很簡單, 開始跟結束加上以下的程式, 就會在/sdcard/.trace, 可以用adb pull /sdcard/.trace 把檔案取出來~ 接著就可以用traceview打開
    
    // start tracing to "/sdcard/calc.trace"
    Debug.startMethodTracing("");
    // ...
    // stop tracing
    Debug.stopMethodTracing();

但是沒辦法看到native code (JNI)以下的部分, 我測試了android-ndk-profiler, 按照說明的方式修改你的Android.mk, 然後把下載後的android-ndk-profiler 放到你的$NDK_MODULE_PATH 下面, 記得要profiling的library都要加上-pg 來compile
# add at beginning
LOCAL_CFLAGS := -pg
LOCAL_STATIC_LIBRARIES := android-ndk-profiler

# at the end of Android.mk
$(call import-module,android-ndk-profiler)
接著在你想要開始跟結束的地方加上profiling method, 跑完就會產生/sdcard/gmon.out.
/* in the start-up code */
monstartup("your_lib.so");

/* in the onPause or shutdown code */
moncleanup();

接著就可以用gprof 解開檔案
# find gprof under android sdk folder
$ find $ANDROID_NDK | grep gprof
# put gmon.out under your project top folder
$ $ANDROID_NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin/arm-linux-androideabi-gprof obj/local/armeabi-v7/your_lib.so > a.log
$ cat a.log
Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 17.46      9.07     9.07                             S32_opaque_D32_filter_DX(SkBitmapProcState const&, unsigned int const*, int, unsigned int*)
  8.86     13.67     4.60                             boxBlurInterp(unsigned char const*, int, unsigned char*, int, int, int, bool, unsigned char)
  7.37     17.50     3.83                             S32A_Opaque_BlitRow32_arm(unsigned int*, unsigned int const*, int, unsigned int)
  7.32     21.30     3.80                             D32_A8_Color(void*, unsigned int, void const*, unsigned int, unsigned int, int, int)
  3.60     23.17     1.87                             arm_memset32
  2.89     24.67     1.50                             RepeatX_RepeatY_filter_scale(SkBitmapProcState const&, unsigned int*, int, int, int)
  1.66     25.53     0.86                             __gnu_mcount_nc
  1.46     26.29     0.76                             S32A_Blend_BlitRow32_arm(unsigned int*, unsigned int const*, int, unsigned int)
  1.08     26.85     0.56                             D32_A8_Opaque(void*, unsigned int, void const*, unsigned int, unsigned int, int, int)
  1.06     27.40     0.55                             profCount
....



android-ndk-profiler 原理, 其實就是利用compiler -pg 會插入__gnu_mcount_nc method, 所以他就去implemnent __gnu_mcount_nc 來對method invoke 計數~ 經過fcamel 提醒, 這類安插code進去的profiling 是屬於Instrumentation (有可能影響程式流程), 像是我用android-ndk-profiler 有些static library 就不能加-pg, 不然程式會hang住, 另外像是oprofile 則是sampling的方式, 透過CPU interrupt 去sample (比較不會影響程式進行), 不過目前我沒有找到其他方式來做native code profiling ... Profiler wiki

2013年10月12日 星期六

[AOSP] ninja build system design

Build system performs 3 main tasks
  1. load and analyze build goals
  2. figure out what steps need to run
  3. execute those steps

Optimization

Use GYP save intermediate state for ninja to load when it generate ninja build files. It can reduce ninja load time.

Use lookup table to check input character which can reduce parsing time.

In order to represent file dependency of nodes and graph which make checking  Canonicalize file path and map the name to an internal Node object which can reduce file name comparison.

Use build log to check whether it should rebuild the command since we can see whether different compilation flags.

When compiler compile the file, it knows what header files the file needs. Record the compiler to output dependent header files can reduce "header scanner" time. Of course first time build need to compile all files since there is no record files. (file name should be canonicalize before output)

Alternative design

ninja run as memory-resident daemon which monitor file modification and avoid load/write data time between build.

Reference
http://aosabook.org/en/posa/ninja.html




2013年8月28日 星期三

[NOTE] HTTP 2.0

The primary goals for HTTP 2.0 are to reduce latency by enabling full request and response multiplexing, minimize protocol overhead via efficient compression of HTTP header fields, and add support for request prioritization and server push.


  • Request/Response multiplexing
    • Each session can have many streams, each stream can transfer many messages in both direction. Each message is contained by many frames. Frame is the base unit.
    • one connection per origin
      • avoid "Slow-Start" on TCP
      • better header compression
        • keep track key-value header table on server/client side

    •  
  • Server push
    • server can create stream to client as well
  • Header compression
    • header tables with key/value and maintain on server/client side
    •  so no need to send the same header if it match previous request
  • Flow control on each stream
Reference:
High Performance Browser Networking CH12