2012-09-20

reading notes of Programming Ruby 2nd





a.rb
#!/usr/bin/ruby -w
# -*- coding: utf-8 -*-
animals = %w{ant bee cat dog elk}
def say_hello (name)
  "Hello, #{name.capitalize}"
end

puts say_hello('ww')

$globalV = "hello"
@instanceV = "instanceV"
@@classV = "ww"
puts "#$globalV, #@instanceV #@@classV"



hash_example = {
  'a' => 'A',
  'b' => 'B',
  'c' => 'C'
}
puts hash_example['c']

hash_default_value_zero = Hash.new(0)
puts hash_default_value_zero['key-do-not-exists'] == 0

testflag = true
puts "use simple if statement, if possible" if testflag

puts "regex demo: if perl match /perl|python/" if "perl" =~ /perl|python/

aline = 'Perl and Python'
aline.sub(/Perl/, 'Ruby') # replace first 'Perl' with 'Ruby' 
aline.gsub(/Python/, 'Ruby') # replace every 'Python' with 'Ruby'
aline.gsub(/Perl|Python/, 'Ruby')

animals.each { |animal| puts animal }
5.times { print "*" }
3.upto(6) {|i| print i }
('a'..'e').each {|char| print char }

class Song
  attr_reader :name, :artist, :duration, :attr_foo
  attr_writer :name, :artist, :duration
  protected :attr_foo

  def initialize(name, artist, duration)
    @name = name
    @artist = artist
    @duration = duration
  end
  
  def to_s
    "Song: #@name, #@artist, #@duration "
  end
end

class SubSong < Song
  CONSTANTS_START_WITH_UPPERCASE_LETTER = 300
  def initialize(name, artist, duration, lyrics)
    super(name, artist, duration)
    @lyrics = lyrics
  end  

  def SubSong.staticMethod
    "static method"
  end

  def [] (seconds)  #index method, e.g: SubSong[22]
    seconds
  end

  def play
  end

  def pause
  end

  def inspect
    '#' * 10
  end
end

s = SubSong.new("a", "b", "c", "lyrics")
puts
puts s.duration
puts s.name
puts SubSong.staticMethod

class SingletonLogger
  private_class_method :new
  @@logger = nil
  def SingletonLogger.get_instance
    @@logger = new unless @@logger
    @@logger
  end

  def self.static_method_form_b
  end
  
  class << self
    def static_method_form_c
    end
  end

  def public_method_a
  end
  public :public_method_a

  protected
    def protected_method_a
    end
  private
    def private_method_a
    end
end

i = SingletonLogger.get_instance
puts i.object_id == SingletonLogger.get_instance.object_id
puts i.class
j = i.dup   #duplicate a new object
puts j.class
j.freeze    #freeze an object

array = Array.new
array[0] = "xxx"
array[1] = "yyy"
array[2] = "zzz"
puts array[0,2]
puts array[100] == nil

#a=[1,3,5,7,9]    → [1,3,5,7,9]                        
#a[2, 2] = ’cat’   → [1, 3, "cat", 9]                   
#a[2, 0] = ’dog’   → [1, 3, "dog", "cat", 9]            
#a[1,1]=[9,8,7]   → [1,9,8,7,"dog","cat",9]            
#a[0..3] = []     → ["dog", "cat", 9]                  
#a[5..6] = 99, 98 → ["dog", "cat", 9, nil, nil, 99, 98]



require 'test/unit'
class TestSong < Test::Unit::TestCase
  def test_method
    h = { 'a' => 'A', 'b' => 'B', 'c' => 'C'}
    assert_equal(h['c'], 'C')
  end
end


def two_times
  yield
  yield
end

two_times { puts "Hello"}

a = [1, 'cat', 3.14]   #array with three elements
a[2] = nil
puts a.find {|element| element == 1}
puts [1,3,5,7,9].find{|v|v*v>30}
puts [1,3,5,7,9].each {|i| puts i}
puts ['S', 'V'].collect {|x| x.succ}
puts defined?(not_defined_variable) == nil

puts [1,2,3,4].inject {|p, e| p*e}

class File
  def File.with_file_open(*args)
    result = f = File.open(*args)
    if block_given?
      result = yield f
      f.close
    end
    f
  end
end

song = SubSong.new("a", "b", "c", "d")
p s
class SongButton
  def initialize(label, &action)
    @label = label
    @action = action
  end

  def button_pressed
    @action.call(self)
  end
end

start_button = SongButton.new("Start") { song.start }

def n_times(thing)
  return lambda { |n| thing *n }
end

proc_3_times = n_times("hello")
puts proc_3_times.call(3)

num = 81
5.times do 
  puts "#{num.class}: #{num}"
  num *= num
end

99.downto(96) { |i| print i, " " }
50.step(80,5) { |i| print i, " " }

puts "#{'hello ' * 3}"
puts "now is #{
def the(a)
  'the ' + a
end
the('time')
} for all.."

p (1..10).to_a
p ('bar'..'bat').to_a

digits = 0..9
puts digits.include?(5)

puts 1 <=> 2
puts 1 <=> 1

puts (1..10) === 5
puts (1..10) === 12

#102 More about methods
#method name instance_of? chop chop! name=

def method_without_parameters_do_not_need_parenthesis
puts ' '
end

def method_parameter_can_have_default_value(input="hello")
puts input
end
method_parameter_can_have_default_value

def varargs(arg1, *rest)
  "Got #{arg1} and #{rest.join(', ')}"
end

puts varargs("first variable", "and", "more", "params")

#if block_given?

#if omit the receiver, it defaults to self.
#self.frozen?  is same as frozen?
#self.id       is same as id

#Modules
module Module_Can_do_mixin
  PI = 3.14
  def morsecode
  end
end

module Debug
  def who_am_i
    "#{self.class.name}"
  end
end

class Photo
  include Debug
end

require 'open-uri'
open('http://www.sina.com.cn') do |f|
  puts f.read.scan(/<img src="(.*?)"/m).uniq
end

#Threads and Processes
#P377 to be continue...

2012-09-19

copy to end of line from current point

As an Emacs user, maybe you already known CopyWithoutSelection

But currently without copy to line end from current point.
Following is the my implementation, and bind to the shortcut "C-c e"




init.el

(defun copy-to-line-end (&optional arg)
  "Save point to current line end into Kill-Ring without mark (or kill and yank)"
  (interactive "P")
  (let ((start (point)))
    (save-excursion
      (end-of-line)
      (copy-region-as-kill start (point))
      )
    )
)
(global-set-key (kbd "C-c e") 'copy-to-line-end)


2012-09-03

Using Jenkins' Script Console to Download Files


jenkins.org

* Using Jenkins Script Console to Download Files
Scenario::
ServerA has a file test.t want to copy to ServerB, But don't have login user on ServerB.

And ServerB running a Jenkins server, we can access.

Solutions::
On ServerA:
    1. goto folder of test.t
    2. execute python -m SimpleHTTPServer
       19:41 ~ $ python -m SimpleHTTPServer
       Serving HTTP on 0.0.0.0 port 8000 ...

On Jenkins::
    1. execute following code in Jenkins's Script Console.
    
String cmd ="curl <ip_of_server_A>:8000/test.t -o test.t";
Runtime run = Runtime.getRuntime();
Process pr = run.exec(cmd);
pr.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = "";
while ((line=buf.readLine())!=null) {
        println line;
}
Then, test.t will located in Home folder of user who running the Jenkins.

   2. Surely,  any Groovy Script can execute here.

2012-08-26

handy commands for development





whunmr.org




COMMAND::
Watch something to happen                                  :: $ watch -d -n 0.1 "ls"
Find all handle of App                                     :: $ lsof -p <pid>
Find files opened by App                                   :: $ lsof -f -p <pid> 
Find which App is using specified socket port 8080         :: $ lsof -i :8080
Monitor file changes                                       :: $ lsof -f -p <pid>
Grep except something                                      :: $ grep -v string_to_except <fileName>
Monitor CPU balance                                        :: $ cat /proc/interrupts
Monitor system performance                                 :: $ nmon
Using python to start a HTTP Server to share files         :: $ python -m SimpleHTTPServer
call command with ! followed by first letter of recent cmd :: $ !<first-letter-of-recent-cmd>
pushd and popd to navigation in dir                        :: $ pushd <target-dir>
- console::
  Ctrl + u            Erase the current line.
  Ctrl + k            Delete the line from the position of the cursor to the end of the line.
  Ctrl + w            Delete the word before the cursor.
  Ctrl + r            incremental search previously called commands, continue type Ctrl+ r to search next
  Ctrl + a            Move to line beginning
  Ctrl + e            Move to line end
  Ctrl + d            Delete char under cursor
  Ctrl + _            Undo
  ESC b               Move backward one word
  ESC f               Move forward one word
  ESC d               Delete word right
  ESC backspace       Delete word left

let mysql log the queries:: 
mysql -uroot -pYOUR-PASSWORD -e "SET GLOBAL log_output = 'FILE'; Set GLOBAL general_log_file = '/tmp/mysql.log'; SET GLOBAL general_log = 'ON';"

mac os::
- To move files in Finder first press Command+C to copy the selected files, then press Command+Option+V to move the copied files to the current folder.
- ctrl+F2 to focus on menu bar
- command+shift+/ activate Help and search menu items with name
- pbcopy
- pbpaste
- Quicksilver open directory in iTerm
- cmd+D split iTerm window

-->

2012-08-25

Favorite emacs key-bindings


(global-set-key "\M-n"  'next-buffer)
(global-set-key "\M-p"  'previous-buffer)
(global-set-key (kbd "C-c w") (quote copy-word))
(global-set-key (kbd "C-c l") (quote copy-line))
(global-set-key (kbd "C-c p") (quote copy-paragraph))
(global-set-key (kbd "C-c s") (quote thing-copy-string-to-mark))
(global-set-key (kbd "C-c a") (quote thing-copy-parenthesis-to-mark))

(global-set-key "\C-o"  'other-window)
(global-set-key "\M-o"  'other-window)

(defvar my-keys-minor-mode-map (make-keymap) "my-keys-minor-mode keymap.")
(define-key my-keys-minor-mode-map (kbd "C-,") 'beginning-of-buffer)
(define-key my-keys-minor-mode-map (kbd "C-.") 'end-of-buffer)
(define-minor-mode my-keys-minor-mode
  "A minor mode so that my key settings override annoying major modes."
  t " my-keys" 'my-keys-minor-mode-map)
(my-keys-minor-mode 1)
(global-set-key (kbd "C-M-'") 'er/expand-region)
(define-key global-map (kbd "C-c SPC") 'ace-jump-mode)
(define-key global-map (kbd "C-;") 'ace-jump-char-mode)
(define-key global-map (kbd "C-'") 'ace-jump-line-mode)
(require 'mark-more-like-this)
(global-set-key (kbd "C-<") 'mark-previous-like-this)
(key-chord-define-global "zz" 'mark-previous-like-this)
(global-set-key (kbd "C->") 'mark-next-like-this)
(key-chord-define-global "??" 'mark-next-like-this)
(global-set-key (kbd "C-M-m") 'mark-more-like-this) 
(global-set-key (kbd "C-*") 'mark-all-like-this)
(key-chord-define-global ",," 'mark-all-like-this)
(key-chord-define-global "zk" 'zap-to-char)
(key-chord-define-global ";w" 'kill-region)
;;accumulate-kill
(defun append-kill-line (&optional arg)
  "Append kill-line to current kill buffer, prefix arg kills from beginning of line."
  (interactive "P")
  (append-next-kill)
  (kill-line arg)
)
(define-key global-map "\C-x\C-m" 'append-kill-line)






More on github.

2012-08-24

mongodb-mapreduce and highcharts

During company's hackday, we analyze some bigdata in mongodb. We want to find out whether XXXXX price's short term and long term Moving averages can predicting the future price changing trends. BACKGROUND: http://www.hardrightedge.com/tactics/indicators/movingaverages.htm http://winninginvestor.quickanddirtytips.com/The-Top-5-Chart.aspx
THE SCRIPT TO MAP-REDUCE DATA IS:
m = function () {
    if (this.landsize > 0) {
        seq_key = NumberInt(this.seq / 100);
       if (this.valuation_range_high > 0 && this.valuation_range_low > 0) {
            emit(seq_key, {seq:seq_key, avg_price:0, price:(this.valuation_range_high + this.valuation_range_low) / this.landsize, count:1});
        }
    }
}



r = function (key, values) {
    r = {seq:key, avg_price:0, price:0, count:0};
    values.forEach(function (v) {r.price += v.price;r.count += v.count;});
    return r;
}
function finalizef(key, value) {
    if (value.count > 0) {
        value.avg_price = value.price / value.count / 2;
    }
    return value;
}

s = db.rpdata.mapReduce(m, r, {finalize:finalizef, out : "price"})

result::
{
 "result" : "price",
 "timeMillis" : 730604,
 "counts" : {
  "input" : 19477443,
  "emit" : 7345947,
  "reduce" : 26799,
  "output" : 19468
 },
 "ok" : 1,
}
THE PYTHON SCRIPT TO LOAD DATA FROM MONGODB:
from pymongo import Connection
import pymongo

...

    def get_price_from_db(self):
        connection = Connection()
        db = connection.bigdata
        price_records = db.price

        avg_prices = []
        for record in price_records.find():
            avg_prices.append(record['value']['avg_price'])
 
        mean_value = mean(avg_prices)
        std_value = std(avg_prices)

        normalized_prices = []
        for price in avg_prices:
            //using z-score to strip strange values
            if abs((price - mean_value) / std_value) < 1.0 :
                normalized_prices.append(price)
Code on github
REFERENCES:
moving_averages
http://en.wikipedia.org/wiki/Moving_average
http://en.wikipedia.org/wiki/Z-score
http://www.mongodb.org/display/DOCS/MapReduce
http://highcharts.com/demo/
http://docs.python.org/library/basehttpserver.html
http://www.tanzilli.com/python_httpserver

2012-08-17

Enhance htmlize.el , now can export org-link.

Several Days ago, I found a problem when write blog using org-mode.
The 'html-region command in htmlize.el, just generate a CSS style for org-link,  not a real link.

So I went to great stackoverflow.com:
 http://stackoverflow.com/questions/11937649/in-emacs-how-to-export-links-to-a-clickable-link-when-htmlize-emacs-buffer


BACKGROUND
  1. I using great htmlize.el to export my org-mode buffer contents with font hi-lock.
  2. Emacs org-mode has a Link format.
PROBLEM
For Example, here is a org-mode file with contents:
[[http://hunmr.blogspot.com][blog]]
When I Using Htmlize.el to htmlize buffer to HTML contents, The link was missing. produces HTML like:
<span style="hyperlinkFOOBAR">blog</span>
EXPECTED
I expected it produces clickable link like:
<a style="hyperlinkFOOBAR" href="http://hunmr.blogspot.com">blog</a>
QUESTION
EDIT1 The org-export-as-html can export link, but can not create CSS for the Hi-locks.
  • Do you know other ways to to export org-mode links to HTML?
  • To read the real link in org-mode buffer using elisp, how to do that? read text property?



----------------------------------------------------------------------------------------------------------------
@Andreas gave a great hint, so I tried to read the code of org-mode,
after write some elisp function, finally it worked.

The new htmlize.el was shared on github.com now:

https://github.com/whunmr/dotemacs/blob/master/site-lisp/htmlize.el
----------------------------------------------------------------------------------------------------------------


And this the main code:

(defun expand-org-link (&optional buffer)
  "Change [[url][shortname]] to [[url] [shortname]] by adding a space between url and shortname"
  (goto-char (point-min))
  (while (re-search-forward "\\[\\[\\([^][]+\\)\\]\\(\\[\\([^][]+\\)\\]\\)?\\]"
                nil t)
    (let ((url (match-string 1))
      (link-text (match-string 3)))
      (delete-region (match-beginning 0) (match-end 0))
      (insert "[[" url "] [" link-text "]]"))))

(defun shrink-org-link (&optional buffer)
  "Change [[url] [shortname]] to [[url][shortname]], remove the space between url and shortname"
  (goto-char (point-min))
  (while (re-search-forward "\\[\\[\\([^][]+\\)\\] \\(\\[\\([^][]+\\)\\]\\)?\\]"
                nil t)
    (let ((url (match-string 1))
      (link-text (match-string 3)))
      (delete-region (match-beginning 0) (match-end 0))
      (insert "[[" url "][" link-text "]]"))))

(defun transform-org-link ()
  "transform htmlized  to "
  (goto-char (point-min))
  (while (re-search-forward "\\[\\[]+\\)>\\([^][]+\\)\\] \\[\\([^][]+\\)\\]\\]"
                nil t)
    (let ((style (match-string 1))
          (url (match-string 2))
      (link-text (match-string 3)))
      (delete-region (match-beginning 0) (match-end 0))
      (insert "" link-text ""))))




2012-08-12

Java Performance Tuning

performance_tunning.org -->
* What I found in Performance Tuning
** BETTER MACHINE
- "we need more CPU core. we need more memory, currently 96G is not enough on our server. we need SSD"

** BETTER ALGORITHM
- using Array instead of HashMap
  || - ASN.1 parse
  || - There is a system, Every component has a uuid, but that's NOT efficient to dispatch calls.
  ||   So we assigned each component a numeric ID for fast dispatch.













** CHOOSE PROPER INITIAL SIZE
- StringBuilder
- HashMap && ConcurrentHashMap && ArrayList ...

- YOUNG & OLD generation's size
  















+ GC in JAVA



 GC for Eden Space:

GC for Old Generation:



 

+ HotSpot VM options: 
    -Xmn 
    -Xms256m -Xmx512m   ||Set initial and maximum to equal, to avoid using CPU cycle to grow heap size.
    -XX:NewRatio=n //Ratio of new/old generation sizes. The default value is 2.  
    -XX:SurvivorRatio=n //Ratio of eden/survivor spacesize. The default value is 8.  
    -XX:MaxTenuringThreshold=n
    -XX:PermSize -XX:MaxPermSize

    -XX:UseConcMarkSweepGC
-XX:ParallelGCThreads=n

+ If most of the application's data are short lived, you should expand size of YOUNG generation.
    otherwise, expand the size of OLD generation.
    find more GC options of HotSpot VM












+ About java GC GC Collectors
    ‐XX:+UseConcMarkSweepGC 

+ SoftReference, WeakReference
  + Use case of PhantomReference
  + Apple has a new Compile-time tech to avoid performance problem caused by GC: Automatic Reference Counting
   
















** LOW DOWN THE MEMORY CONSUMPTION
- String's memory structure in JVM
  - structure of Object in JVM
    + a normal object requires 8 bytes of "housekeeping" space;
        OpenJDK6: src/hotspot/src/share/vm/oops/markOop.hpp
        //  32 bits:
        //  --------
        //             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)
        //             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)
        //             size:32 ------------------------------------------>| (CMS free block)
        //             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
                
    + arrays require 12 bytes (the same as a normal object, plus 4 bytes for the array length).















- structure of String Object
    
    public final class String
    8        |String's object header
    4        |private final java.lang.Object value;--------->,
    4        |private final int offset;                      |
    4        |private final int count;                       |
    4        |private int hash;                              |
                                                             |
    8        |Char Array's object header  |<-----------------'   
    4        |array length                |
    N*2      |bytes of N characters       |
    P        |bytes of padding to 8n      |
   
    so, empty string will using 40 bytes.    
    In 64bits JVM, Object header will use 16bytes. 

    ||Using AnsiString, with byte[] rather than char[]

 
- string's substring implementation 
    ||why we need create a new String after substring.  //new String(str.substring(5, 4));

  - StringBuilder/StringBuffer use less memory. 
  - ||If not concern string contents in computation and caching, you can create your own String 
    || constant pool(HashMap) to convert frequently used String to Integer value.
    || when the string is never use anymore, convert it back.












- memory compress
  - snapp-java
  - Out of heap memory #find more
  - BigMemory

- Story about not use AtomicInteger - has better performance than synchronize adding (interlockedincrement __sync_fetch_and_add) - use more memory - IN THAT STORY: can be avoided through hash re-Dispatch - AtomicReference Java volatile reference vs. AtomicReference ( compareAndSet() used in Queue implementation)


























** TOOLS
*** jps  use jps to find correct jvm process Id

   
C:\Documents and Settings\Administrator>jps -lmVv
   3672 org.nasa.marsrovers.Main -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:4176 -Dfile.encoding=UTF-8 -Xbootclasspath:C:\Program Files\Java\jre6\lib\resources.jar;C:\Program Files\Java\jre6\lib\rt.jar;C:\Program Files\Java\jre6\lib\jsse.jar;C:\Program Files\Java\jre6\lib\jce.jar;C:\Program Files\Java\jre6\lib\charsets.jar
   3380 sun.tools.jps.Jps -lmVv -Denv.class.path=.;C:\Program Files\Java\jdk1.6.0_22\jre\lib;C:\Program Files\Java\jdk1.6.0_22\lib; -Dapplication.home=C:\Program Files\Java\jdk1.6.0_22 -Xms8m
   552  -Dosgi.requiredJavaVersion=1.5 -Xms40m -Xmx384m -XX:MaxPermSize=256m















*** jstack
    ||Find out current stack trace.
    ||Thread name will show in stack trace, that's why we need set name for thread and threadPool.

    + look stack pattern find bug
       ||DeadLock in webserver
          We reproduced three days. If we grab a thread dump before restart server,
          This bug will be super easy to find. same as .NET and C++.
          before restart server, first thing we need to do is collect more
           information (dump, memory usage, CPU usage)

       ||HashMap infinite loop

       ||Most thread blocked on LOG message queue's put()























 $ jstack -l 3672
        
2012-08-12 22:48:17
        Full thread dump Java HotSpot(TM) Client VM (17.1-b03 mixed mode):
         
        "Low Memory Detector" daemon prio=6 tid=0x16bb2800 nid=0x1314 runnable [0x00000000]
           java.lang.Thread.State: RUNNABLE
         
           Locked ownable synchronizers:
         - None
         
        "CompilerThread0" daemon prio=10 tid=0x16baf400 nid=0xbd4 waiting on condition [0x00000000]
           java.lang.Thread.State: RUNNABLE
         
           Locked ownable synchronizers:
         - None
         
        "JDWP Command Reader" daemon prio=6 tid=0x16bad000 nid=0xdc4 runnable [0x00000000]
           java.lang.Thread.State: RUNNABLE
         
           Locked ownable synchronizers:
         - None
         
        "JDWP Event Helper Thread" daemon prio=6 tid=0x16bab000 nid=0x16c8 runnable [0x00000000]
           java.lang.Thread.State: RUNNABLE
         
           Locked ownable synchronizers:
         - None
         
        "JDWP Transport Listener: dt_socket" daemon prio=6 tid=0x16ba8c00 nid=0x11d4 runnable [0x00000000]
           java.lang.Thread.State: RUNNABLE
         
           Locked ownable synchronizers:
         - None
         
        "Attach Listener" daemon prio=10 tid=0x16b99000 nid=0x168c waiting on condition [0x00000000]
           java.lang.Thread.State: RUNNABLE
         
           Locked ownable synchronizers:
         - None
         
        "Signal Dispatcher" daemon prio=10 tid=0x16bb3400 nid=0x1320 runnable [0x00000000]
           java.lang.Thread.State: RUNNABLE
         
           Locked ownable synchronizers:
         - None
         
        "Finalizer" daemon prio=8 tid=0x16b85000 nid=0x1678 in Object.wait() [0x16cff000]
           java.lang.Thread.State: WAITING (on object monitor)
         at java.lang.Object.wait(Native Method)
         - waiting on <0x029d0b28> (a java.lang.ref.ReferenceQueue$Lock)
         at java.lang.ref.ReferenceQueue.remove(Unknown Source)
         - locked <0x029d0b28> (a java.lang.ref.ReferenceQueue$Lock)
         at java.lang.ref.ReferenceQueue.remove(Unknown Source)
         at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)
         
           Locked ownable synchronizers:
         - None
         
        "Reference Handler" daemon prio=10 tid=0x16b83c00 nid=0x13ec in Object.wait() [0x16caf000]
           java.lang.Thread.State: WAITING (on object monitor)
         at java.lang.Object.wait(Native Method)
         - waiting on <0x029d0a28> (a java.lang.ref.Reference$Lock)
         at java.lang.Object.wait(Object.java:485)
         at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
         - locked <0x029d0a28> (a java.lang.ref.Reference$Lock)
         
           Locked ownable synchronizers:
         - None
         
        "main" prio=6 tid=0x00847000 nid=0x1464 runnable [0x0091f000]
           java.lang.Thread.State: RUNNABLE
         at java.io.FileInputStream.readBytes(Native Method)
         at java.io.FileInputStream.read(Unknown Source)
         at java.io.BufferedInputStream.read1(Unknown Source)
         at java.io.BufferedInputStream.read(Unknown Source)
         - locked <0x029e19f0> (a java.io.BufferedInputStream)
         at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
         at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
         at sun.nio.cs.StreamDecoder.read(Unknown Source)
         - locked <0x02b63a00> (a java.io.InputStreamReader)
         at java.io.InputStreamReader.read(Unknown Source)
         at java.io.BufferedReader.fill(Unknown Source)
         at java.io.BufferedReader.readLine(Unknown Source)
         - locked <0x02b63a00> (a java.io.InputStreamReader)
         at java.io.BufferedReader.readLine(Unknown Source)
         at org.nasa.marsrovers.simulator.Simulator.startUp(Simulator.java:53)
         at org.nasa.marsrovers.Main.main(Main.java:50)
         
           Locked ownable synchronizers:
         - None
         
        "VM Thread" prio=10 tid=0x16b81400 nid=0xef0 runnable 
         
        "VM Periodic Task Thread" prio=10 tid=0x16bc9000 nid=0x304 waiting on condition 
         
        JNI global references: 1508



*** jmap
**** show memory usage 08:57 ~ $ jmap -heap 623
Attaching to process ID 623, please wait...
        Debugger attached successfully.
        Server compiler detected.
        JVM version is 20.6-b01-414
        
        using parallel threads in the new generation.
        using thread-local object allocation.
        Concurrent Mark-Sweep GC
        
        Heap Configuration:
           MinHeapFreeRatio = 40
           MaxHeapFreeRatio = 70
           MaxHeapSize      = 838860800 (800.0MB)
           NewSize          = 21757952 (20.75MB)
           MaxNewSize       = 174456832 (166.375MB)
           OldSize          = 65404928 (62.375MB)
           NewRatio         = 7
           SurvivorRatio    = 8
           PermSize         = 21757952 (20.75MB)
           MaxPermSize      = 367001600 (350.0MB)
        
        Heap Usage:
        New Generation (Eden + 1 Survivor Space):
           capacity = 19595264 (18.6875MB)
           used     = 16274240 (15.52032470703125MB)
           free     = 3321024 (3.16717529296875MB)
           83.0519047867893% used
        Eden Space:
           capacity = 17432576 (16.625MB)
           used     = 15573992 (14.852516174316406MB)
           free     = 1858584 (1.7724838256835938MB)
           89.33844315378289% used
        From Space:
           capacity = 2162688 (2.0625MB)
           used     = 700248 (0.6678085327148438MB)
           free     = 1462440 (1.3946914672851562MB)
           32.37859552556818% used
        To Space:
           capacity = 2162688 (2.0625MB)
           used     = 0 (0.0MB)
           free     = 2162688 (2.0625MB)
           0.0% used
        concurrent mark-sweep generation:
           capacity = 154337280 (147.1875MB)
           used     = 120364648 (114.7886734008789MB)
           free     = 33972632 (32.398826599121094MB)
           77.98805836153132% used
        Perm Generation:
           capacity = 176562176 (168.3828125MB)
           used     = 134844944 (128.59815979003906MB)
           free     = 41717232 (39.78465270996094MB)
           76.37249781062961% used







**** show memory usage according object type
        09:02 ~ $ jmap -histo 623 | head -n 20
        
num     #instances         #bytes  class name
        ----------------------------------------------
           1:         57975       34551008  [B
           2:        304951       33637464  [C
           3:        166951       23748152  <constMethodKlass>
           4:        166951       22721672  <methodKlass>
           5:         21247       21762832  <constantPoolKlass>
           6:        279214       18444400  <symbolKlass>
           7:         21247       17749960  <instanceKlassKlass>
           8:         20092       13129152  <constantPoolCacheKlass>
           9:        304840        9754880  java.lang.String
          10:         53366        4497624  [Ljava.lang.Object;
          11:         15038        4360504  [I
          12:        122304        3913728  java.util.HashMap$Entry
          13:         22426        2332304  java.lang.Class
          14:          4146        2094728  <methodDataKlass>
          15:         32534        1717344  [S
          16:         12637        1676168  [Ljava.util.HashMap$Entry;
          17:         35117        1544960  [[I

**** get a JVM heap dump
        $ jmap -dump:file=/tmp/demo.map 91440
        Dumping heap to /private/tmp/demo.map ...
        Heap dump file created
or 
      -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:/temp/oom.hprof

**** analyze heap dump
     
     +   $ jhat /private/tmp/demo.map 
        Reading from /private/tmp/demo.map...
        Started HTTP server on port 7000
      

+  Like !dumpheap -type Exception in windbg+sos, you can use OQL to find out 
        more useful stuff in the dumped heap, like:
select file.path.toString() from java.io.File file
**** using eclipse MAT http://www.eclipse.org/mat to analyze the dump file. 
- articles about MAT
     











**** Monitor GC status of JVM
  - jstat

     $ jstat -gcutil 21891 250 7
     S0     S1     E      O      P     YGC    YGCT    FGC    FGCT     GCT
    12.44   0.00  27.20   9.49  96.70    78    0.176     5    0.495    0.672
    12.44   0.00  62.16   9.49  96.70    78    0.176     5    0.495    0.672
    12.44   0.00  83.97   9.49  96.70    78    0.176     5    0.495    0.672
     0.00   7.74   0.00   9.51  96.70    79    0.177     5    0.495    0.673
     0.00   7.74  23.37   9.51  96.70    79    0.177     5    0.495    0.673
     0.00   7.74  43.82   9.51  96.70    79    0.177     5    0.495    0.673
     0.00   7.74  58.11   9.51  96.71    79    0.177     5    0.495    0.673







































- visualVM
    

    When CPU high, can use visualVM find out the most long run method.
    When CPU low, can get some stack sample, see where is the block point.
    queue.put? queue.take? 

  - nmon  great tool to monitor CPU, memory, network, disks...


















** OTHERS
*** JAVA AS SCRIPT
  aim:     write business calculation/logic to script
  problem: java call Groovy/Python was so slow.

  - write business calculation/logic to file XXX.java, then compile and load use customized class loader.
  - can reload java class, after business calculation/logic changed, without restart Java instance.
  - use script to trace data




































*** NETWORK
  - ||CPU balance for network interfaces.  
    For some machine with multi CPU, if not properly configured, 
    all network interfaces' interrupts will goto CPU0 (like following show). 
    Then network performance will be restricted by power of CPU0.  see here for the solution.

      $ cat /proc/interrupts
              CPU0       CPU1       CPU2       CPU3
     65:      20041      0          0          0      IR-PCI-MSI-edge  eth0-tx-0
     66:      20232      0          0          0      IR-PCI-MSI-edge  eth0-tx-1
     67:      20105      0          0          0      IR-PCI-MSI-edge  eth0-tx-2
     68:      20423      0          0          0      IR-PCI-MSI-edge  eth0-tx-3
     69:      21036      0          0          0      IR-PCI-MSI-edge  eth0-rx-0
     70:      20201      0          0          0      IR-PCI-MSI-edge  eth0-rx-1
     71:      20587      0          0          0      IR-PCI-MSI-edge  eth0-rx-2
     72:      20853      0          0          0      IR-PCI-MSI-edge  eth0-rx-3
























- set_thread_affinity
    ||If your system's performance is not stable, you can try set_thread_affinity.
    Restricting a process to run on a single CPU also avoids the performance cost 
    caused by the cache invalidation that occurs when a process ceases to execute
    on one CPU and then recommences execution on a different CPU.
    
int sched_setaffinity(pid_t pid,size_t cpusetsize,cpu_set_t *mask);
- send several packages in a Big package. - pfring - Google Protocol Buffer

*** thread local storage to prevent new objects
JAVA: ThreadLocal
    gcc: __thread int i;

 - use array if possible
 - use hash dispatch to avoid locking
 - log sampling, if log is not important, then use queue.offer()
 - keep thread count low. 
 - use message loop instead of timers
 - less exception
 - double buffer queue




** THE END











_______________________________________________________________________
_______________________________________________________________________

2009-05-04

Firebug 如何提供console API到页面的window中

Firebug 如何提供console API到页面的window中?
How Firebug inject the console API to DOM window?
1. Use Components.utils.evalInSandbox and Components.utils.Sandbox

2. Register a listener to an Element in DOM window, which is created during injection phase.

3. Use attribute in precreated Element to specify the return value's type.


页面中执行的JavaScript与Firefox插件中执行的JavaScript代码是不能相互调用的。
因为各处于自己的解释器的工作范围中,运行时看不到对方定义的函数。

那么Firebug是如何把console API提供给页面的window的属性中的呢?
1. API如何绑定到页面的window中.
    如果是在页面中写代码,很容易在window属性中加入一个console对象,
    但是那样的话, 又不能调用或控制Firefox插件的控件了。

    Firebug通过在插件代码中调用 evalInSandbox方法, 传入用外部页面的window构造sandbox。
    在sandbox中执行一段注入(injection)代码, 使页面的window中有了console的定义。
           
            a. 注入代码的构造         \content\firebug\consoleInjector.js [getConsoleInjectionScript]
                var script = "";
                script += "window.__defineGetter__('console', function() {\n";                                                          //[1]
                script += " return window.loadFirebugConsole(); })\n\n";
               
                script += "window.loadFirebugConsole = function() {\n";                                                                   //[2]
                script += "window._firebug =  new _FirebugConsole();";                                                                   //[3]
                script += " return window._firebug };\n";
               
                var theFirebugConsoleScript = getResource("chrome://firebug/content/consoleInjected.js");            //[4]
                script += theFirebugConsoleScript;
            
            [1] 在此处定义了console 对象
             [2] 在此处定义了loadFirebugConsole方法,其中[3]实例化一个_FirebugConsole对象
             [4] 在此处加载_FirebugConsole的定义代码,稍后会说_FirebugConsole这段代码
             到此script中就构造好了准备注入的代码了。
          b. 构造sanbox
             // Use DOM Window 用外部的DOM window构造sandbox
            sandbox = new Components.utils.Sandbox(win);        
            sandbox.__proto__ = (win.wrappedJSObject?win.wrappedJSObject:win);

            c. 执行注入代码
            result = Components.utils.evalInSandbox(scriptToEval, sandbox);

到此页面的window有console的定义了,那console的方法(如log, debug, info, error)是如何把参数传递给Firebug插件的代码中的呢?

函数调用一般有三个过程
1. 参数准备             firebug 把要调用的函数的名字设置到预先定义的页面元素的属性中; 将参数设置为window的一个
userObjects属性。  
2. 函数执行             firebug 的chrome 会在预先定义页面元素上加一个linster, addEventListener, 进行chrome代码的调用。
3. 返回结果             firebug 把结果存回window的userObjects属性中, 并将返回值类型设置为预定的页面元素的一个属性中。



2. 函数的调用
   log, debug等函数的定义在_FirebugConsole这个类中, 代码位于 consoleInjected.js中.
        
          a. 建立一个页面元素来标示返回值的类型
           window._getFirebugConsoleElement = function()  // could this be done in extension code? but only after load....
  {
    var element = document.getElementById("_firebugConsole");                                              //[5]                  
    if (!element)
    {
        element = document.createElementNS("http://www.w3.org/1999/xhtml","html:div");
        element.setAttribute("id", "_firebugConsole");
        element.firebugIgnore = true;
         
        element.setAttribute("style", "display:none");

        document.documentElement.appendChild(element);
    }
    return element;
 };

         [5] 检测当前页面是否已经创建了用来传递数据及提供事件监听的页面元素
        

        b. 函数通过事件发出去,发送事件前的准备
            
    this.notifyFirebug = function(objs, methodName, eventID)
      {
        var element = this.getFirebugElement();                                     //获得元素

        var event = document.createEvent("Events");                             //创建事件
        event.initEvent(eventID, true, false);

        this.userObjects = [];
        for (var i=0; i<objs.length; i++)
            this.userObjects.push(objs[i]);                                              //准备参数

        var length = this.userObjects.length;
        element.setAttribute("methodName", methodName);                     //设置要调用的console对象的方法名
        element.dispatchEvent(event);                                               
        
        var result;
        if (element.getAttribute("retValueType") == "array")
            result = [];

        if (!result && this.userObjects.length == length+1)                       //如果只有一个元素新增,返回那个新增元素
            return this.userObjects[length];

        for (var i=length; i<this.userObjects.length && result; i++)
            result.push(this.userObjects[i]);                                          //将返回的结果数据向上层返回

        return result;
      };
 
         c. 调用事件监听
           在firebug注入代码到页面中后,进行了对调用事件的监听
   
         因为在sandbox中执行代码后, 页面中就会有一个叫_firebugConsole的页面元素,可以通过window.getElementById来获得。
                     
             
var handler = new FirebugConsoleHandler(context, win);  
           handler.attachTo(element);                                                       //调用内部执行addEventListener
          
        d. 响应调用事件
          handle: function(event, api, win)
  {
        var element = event.target;                                                 //获得事件对应的页面元素
        var methodName = element.getAttribute("methodName");          //获得想调用的方法名
        //获得调用的参数
        var hosed_userObjects = (win.wrappedJSObject?win.wrappedJSObject:win)._firebug.userObjects;

        var userObjects = hosed_userObjects ? cloneArray(hosed_userObjects) : [];
        var subHandler = api[methodName];                                     //找到相应的function对象
        if (!subHandler)
            return false;

        element.removeAttribute("retValueType");
        var result = subHandler.apply(api, userObjects);                    //用apply 来调用相应方法
        if (typeof result != "undefined")
        {
            if (result instanceof Array)
            {
                element.setAttribute("retValueType", "array");              //设置返回值类型
                for (var item in result)
                    hosed_userObjects.push(result[item]);
            }
            else
            {
                hosed_userObjects.push(result);
            }
        }

        return true;
  }

           到现在element.dispatchEvent(event);  后面的代码可以继续执行,并将返回值传给window中对console.log等方法。

再回顾一下:Firebug是如何把console API提供给页面的window的属性中的呢?
                答: 应用监听页面事件的方式来接收调用

注:文本中代码引自firebug 1.3.3 代码,有删减。


参考资料:
[1] JavaScript: The Definitive Guide, 5th
Edition ,
By David Flanagan
 注:作者写书时想把此书写成一本相当全面的JavaScript书,我认为,他做到了。
 作者书中对JavaScript的评价

Because JavaScript is interpreted instead of compiled, it is
often considered a scripting language instead of a true programming language.
The implication is that scripting languages are
simpler and that they are programming languages for nonprogrammers. The fact
that JavaScript is loosely typed does make it somewhat more forgiving for
unsophisticated programmers. And many web designers have been able to use
JavaScript for limited, cookbook-style programming tasks.


Beneath its thin veneer of simplicity, however, JavaScript is a
full-featured programming language, as complex as any and more complex than
some. Programmers who attempt to use JavaScript for nontrivial tasks often find
the process frustrating if they do not have a solid understanding of the
language. This book documents JavaScript comprehensively so that you can develop a sophisticated
understanding. If you are used to cookbook-style JavaScript tutorials, you may
be surprised at the depth and detail of the chapters ahead.

 [2] Firebug Console API, http://getfirebug.com/console.html
[3]https://developer.mozilla.org/en/Code_snippets/Interaction_between_privileged_and_non-privileged_pages

2009-02-21

System.Data.OracleClient requires Oracle client software version 8.1.7 or greater

Windows Server 2003下安装了完整版的Oracle9i后,用C#程序连接Oracle时出现奇怪现象.

同样的代码编成console application后可以找Oracle的驱动.
但是当编译成Web 站点,部署到IIS6.0后提示"System.Data.OracleClient requires Oracle client software version 8.1.7 or greater"

后来google,找到一个帖子原来是权限问题.
http://social.msdn.microsoft.com/forums/zh-TW/233/thread/51e8076a-66be-45da-aeb3-da9b83394d70/

具体步骤:
* Log on to Windwos as a user with Administrator privileges.
以管理员身份登录windows
* Start Window Explorer and navigate to the ORACLE_HOME folder.
浏览到ORACLE_HOME目录
* Choose properties on the ORACLE_HOME folder.
选择属性
* Click the “Security” tab of the “Properties” window.
选择安全
* Click on “Authenticated Users” item in the “Name” list.
* Uncheck the “Read and Execute” box in the “Permissions” list under the “Allow” column.
* Re-check the “Read and Execute” box under the “Allow” column
设置Authenticated Users的权限为读和执行.
* Click the “Advanced” button and in the “Permission Entries” verify that “Authenticated Users” are listed with permission = “Read & Execute”, and Apply To = “This folder, subfolders and files”. If not, edit that line and make sure that “Apply To” drop-down box is set to “This folder, subfolders and files”. This should already be set properly but it is important that you verify it.
* Click the “Ok” button until you close out all of the security properties windows. The cursor may present the hour glass for a few seconds as it applies the permissions you just changed to all subfolders and files.
应用权限到所有的子目录
* Reboot, to assure that the changes have taken effect.
重启电脑