ngeohash: node module for geohash algorithm

ngeohash是一个geohash的javascript实现,之所以叫做ngeohash是因为到了Publish的时候才发现已经有geohash这个module了。这么令人沮丧的事就不多说了。

安装
npm install ngeohash

使用
var geohash = require(‘ngeohash’);
sys.puts(geohash.encode(32.1717, 118.2342));

详细
访问github的相关页面:https://github.com/sunng87/node-geohash

Checkout my forked version of reddit-is-fun

每天上下班要花掉两个多小时,这一路只好浏览一些新闻、reddit以及HN。reddit的app相对来说不算多,找了一圈倒是在market里没找到的reddit-is-fun最好用,功能最全。HN的app最近添加的一个小功能非常实用,通过viewtext.org打开链接。使用这个服务,可以提取出页面的正文部分,既减少了流量又提高了阅读体验。于是我想到给reddit-is-fun添加这个功能。reddit-is-fun是个GPLv3的软件,程序本身就在github上,对Android一无所知的我花了两个小时完成了这个功能。感谢IDEA,感谢IDEA的Android插件。

给作者发了pull request,不过作者最近似乎没有什么实质性的动作。不等他了,今天先把包含这个功能的fork放出来,大家如果感兴趣可以下载安装。这个fork的版本为1.1.4-sunng0,应该不会影响未来升级的吧(我猜啊)。

可以通过这个码下载:
https://github.com/downloads/sunng87/reddit-is-fun/reddit_is_fun-sunng-fork.apk

链接地址:
https://github.com/downloads/sunng87/reddit-is-fun/reddit_is_fun-sunng-fork.apk

Update on HeatCanvas and gefr

HeatCanvas的百度地图扩展

感谢@lbt05姐的无私贡献,现在HeatCanvas又增加了百度地图API支持。你可以在你的百度地图中使用heat map了。详情可以参考@lbt05姐撰写的文档,而这里是一个简单的live demo。此外,@lbt05姐还贡献了GoogleMap扩展的patch,帮助我解决了地图拖动后Canvas无法覆盖viewport的bug。再次感谢@lbt05姐。

百度地图支持已经汇入主干,可以在github找到它。

Gefr新增 Jetty WSGI Bridge

昨天为gefr新增了Jetty服务器的支持,这样你可以将自己的Python WSGI程序运行在成熟的Jetty服务器上。性能是大家关心的因素,下面是在我的本机(32位CentOS,双核2.8GHz,4G内存)上一个粗略的测试结果:

100并发,20000请求:

Server Software: gefr-jetty/0.3dev
Server Hostname: localhost
Server Port: 8088

Document Path: /
Document Length: 19 bytes

Concurrency Level: 100
Time taken for tests: 3.120827 seconds
Complete requests: 20000
Failed requests: 0
Write errors: 0
Total transferred: 2584515 bytes
HTML transferred: 380665 bytes
Requests per second: 6408.56 [#/sec] (mean)
Time per request: 15.604 [ms] (mean)
Time per request: 0.156 [ms] (mean, across all concurrent requests)
Transfer rate: 808.44 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 4 114.1 0 3000
Processing: 0 7 18.5 5 1776
Waiting: 0 6 18.5 4 1776
Total: 0 12 115.8 6 3015

Percentage of the requests served within a certain time (ms)
50% 6
66% 7
75% 8
80% 8
90% 10
95% 13
98% 70
99% 74
100% 3015 (longest request)

如果打开KeepAlive,吞吐量可以达到10000以上:

Server Software: gefr-jetty/0.3dev
Server Hostname: localhost
Server Port: 8088

Document Path: /
Document Length: 19 bytes

Concurrency Level: 100
Time taken for tests: 1.749189 seconds
Complete requests: 20000
Failed requests: 0
Write errors: 0
Keep-Alive requests: 20000
Total transferred: 3062142 bytes
HTML transferred: 380266 bytes
Requests per second: 11433.87 [#/sec] (mean)
Time per request: 8.746 [ms] (mean)
Time per request: 0.087 [ms] (mean, across all concurrent requests)
Transfer rate: 1709.36 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.8 0 23
Processing: 0 8 8.0 6 85
Waiting: 0 8 8.0 6 85
Total: 0 8 8.1 6 85

Percentage of the requests served within a certain time (ms)
50% 6
66% 7
75% 8
80% 9
90% 11
95% 20
98% 41
99% 43
100% 85 (longest request)

你可以根据gefr的文档安装它。

jip.embed: On-the-fly classpath resolution for Jython

jip 0.7 introduces a module called jip.embed, which allows you to add libraries to your code in the runtime as you declare them. With jip.embed, you don’t have to download jars manually and append them to your -Dpython.path. You just pick your editor, import jip.embed, code your business, then save and run it.

Code example:

import jip.embed
jip.embed.require('commons-lang:commons-lang:2.6')
from org.apache.commons.lang import StringUtils

print StringUtils.reverse('jip rocks')

Output:

skcor pij

(jip will print some log here if dependencies are included for first time)

So please check out my new released jip, 0.7:
https://github.com/sunng87/jip

For virtualenv user, you can install full-featured jip via pip:
$ pip install jip

To install jip globally, download the package from python cheese shop and run:
$ jython setup.py install

GPars的Actor实现

Actor是一种Continuation技术,可以在少量的线程运行大量Actor对象。Actor对象之间通过消息机制进行交互。而Actor本身线程安全,这样的模型使并发编程的复杂度降低,同时也在一定的场景下实现了可扩展性。

gpars是Java和Groovy都可以使用的并行编程库,他实现了Actor、Agent、DataFlow等模型,旨在为Groovy提供高层的并行编程模型。以下分析gpars 0.12中非阻塞Actor的实现。

@Grab("org.codehaus.gpars:gpars:0.11")
import groovyx.gpars.actor.Actors

def worker = Actors.actor {
    loop {
        react {
            reply it.reverse()
        }
    }
}

def console = Actors.actor {
    worker << "Hello GPars"
    react {
        println it
    }
}

console.join()

首先,在工厂类中Actors里会初始化一个DefaultPGroup用来封装后台的线程池、管理actors。Actors默认使用ResizeablePool,他是JDK Concurrent Framework中的ThreadPoolExecutor的封装,coreSize和maxSize不同所以称Resizeable。

Actors的工厂方法actor生成的是DefaultActor,它是非阻塞actor的默认实现。(ActorGroup:67)

DefaultActor的构造方法接受一个Groovy的闭包对象,将其封装为DefaultActorClosure对象后,调用其父类AbstractLoopingActor的initialize方法(DefaultActor:73).

initialize方法创建一个Runnable对象AsyncMessagingCore,并将线程池传递给core对象。(AbstractLoopingActor:57)AsyncMessagingCore对象负责消息的传递和处理,是线程池处理的目标对象。

调用start启动actor后,actor会向自己发送一个start消息(AbstractLoopingActor:173).
core获得start消息后,调用DefaultActor覆盖的handleStart方法(DefaultActor:328)。

在handleStart中,actor会调用用户传入的闭包方法。上面的例子是一种典型的用法,loop是DefaultActor中的方法,loop也并不是无限空转的,他仅在收到消息被时被触发(DefaultActor:191)react也是DefaultActor中的方法,它将nextContinuation方法设为内部闭包对象,用来处理actor接收的消息。

向Actor发送消息,是通过actor的send方法和重载的leftShift运算符进行操作。(AbstractLoopingActor:236)actor调用core的store方法,将ActorMessage压入core的队列中。入队列之后,core会检查锁对象activeUpdater,判断当前core是否在线程处理中,如果不在,则将core加入线程池中处理。activeUpdater是一个AtomicIntegerFieldUpdater对象,他的compareAndSet可以保证原子性。而通过activeUpdater也可以保证同一时刻只有一个core被线程池处理,从而使actor的线程不安全代码也线程安全地运行。

进入线程池后,core首先将自己放进threadlocal对象中,并保存当前线程的引用。然后会循环消费MessageQueue中的消息直至Queue的可处理部分为空。(AsyncMessagingCore:126)。handleMessage在AbstractLoopingActor中被覆盖,会根据消息的类型进行分发调用(前面提到的start消息就是一种)。默认的业务消息,在DefaultActorClojure中调用DefaultActor的onMessage方法处理。

onMessage中,react的闭包会被调用来处理业务。之后nextContinuation被置为null,这时loop闭包被重新调用,react闭包重新被赋给nextContinuation。这部分代码就是前面所说的loop并非空转,而是在消息处理完成后重新准备而已。

此外,core的MessageQueue的实现是DefaultMessageQueue。它使用两个LinkedList作为输入(向actor输入)队列和输出队列,当输入队列为空时,通过同步方法swap交换输入输出队列。swap是整个actor系统里唯一一个同步方法。这样的机制保证actor的core在线程池中处理时,外界仍然可以向actor发送消息,消息会在actor被调度出线程池之前全部处理掉。不过,他的前提是只有一个线程读这个队列,这个条件在actor系统里,通过core对象的activeUpdater可以有效的保证。

Actor模式采用这种onDemand方式的线程使用,允许大量的actor共存,并只有活跃的actor会占用线程,非活跃状态的actor处在dettach状态,并不消耗计算资源,取消了空转的loop。