loop in codes

Kevin Lynx BLOG

Dhtcrawler的进程模型经验

距离写dhtcrawler已经有半年时间。半年前就想总结点心得经验,但最后写出来的并没有表达出我特别有感慨的地方。最近又被人问到这方面的经验问题,才静下心来思考整理了下。

我的经验是关于在写一个网络项目时所涉及到的架构(或者说是模型)。

在dhtcrawler中,一个主要的问题是:程序在网络中需要尽可能快尽可能多地收集请求,然后程序需要尽可能快地加工处理这些信息。本质上就这么简单,我觉得很多网络系统面临的都可能是类似的问题。

详细点说,dhtcrawler高峰期每天会收到2000万的DHT协议请求,收到这些请求后,dhtcrawler需要对这些请求做处理,包括:合并相同的请求;从外部网站请求下载种子文件;新增/更新种子信息到数据库;建立种子sphinx索引等。在实际运行期间,高峰期每天能新录入14万个种子。

那么如何架构这个系统来让处理速度尽可能地快呢?首先,毫无疑问这个系统是多线程/多进程,甚至是分布式的。写一个多线程程序学几个API谁都会,但是如何组织这些线程以让系统最优则是一个较困难的问题。根据dhtcrawler的经验,我简单总结了以下几种模型/架构:

My 2013

技术

这一年里个人的技术感觉进步不是那么大。一方面技术之外的事情多了起来,另一方面由于工作原因接触的技术也较为杂乱,没有机会专注。技术的提升还是得靠业余时间。

系统分析设计

学了些RUP的方法,对规范化的系统分析设计算是有了一定认识。但这个东西在实践的过程中往往较难运用,好的方法学还是得看项目的实际情况而定。

Scala主要特性一览

概述

scala语言包含了函数式语言和面向对象语言的语法特性,从我目前的感受来看,这不是一门简单的语言。同Ruby/Erlang相比,其语法集大多了。scala基于JVM或.NET平台,其可以几乎无缝地使用Java库(不但使用上没有负担,其运行效率上也不会增加负担),配合其强大的语言表达能力,还是很有吸引力。

类型

类/对象

scala中一切都是对象,虽然Java也是这样说的(其实ruby也是这样说的)。在Java中一个数字仅仅是个值,但在scala中却真的是对象:

    
println("2 type: " + 2.getClass())

scala同Java一样将所有类型都设定了一个基类:Any。不同的是,Any下还区分了AnyValAnyRef

类型推断

scala是一门静态类型语言,但是其强大的类型推断可以避免很多冗余信息的代码。例如:

    
val map:Map[String, Int] = new HashMap[String, Int]
// 可简写为
val map = new HashMap[String, Int]

def func():String = {
    "hello"
}
// 可简写为
def func() = {
    "hello"
}

类型推断可以根据表达式的类型决定这个变量/函数的类型,这就如同C++11中的auto关键字。

函数

scala既然包含了函数式语言的特性,那么函数作为first citizen就是自然而言的事情。而function literal的语法形式也就必须更自然(想想common lisp里lambda那蛋疼的关键字):

    
val factor = 3
val multiplier = (i:Int) => i * factor // function literal, lexical bind to factor
val l1 = List(1, 2, 3, 4, 5) map multiplier // map `multiplier` to every element in List l1

def add(a:Int, b:Int) = {
  a + b
}

val f:(Int, Int) => Int = add // f is a function type: (Int, Int) => Int
println("f:" + f(2, 3))

Javascript Overview

Lexical Structure

In JavaScript, identifiers are used to name variables and functions and to provide labels for certain loops in JavaScript code. A JavaScript identifier must begin with a letter, an underscore (_), or a dollar sign ($). Subsequent characters can be letters, digits, underscores, or dollar signs

i
abc
v1
$str

JavaScript allows identifiers to contain letters and digits from the entire Unicode character set.

Like many programming languages, JavaScript uses the semicolon (;) to separate statements from each other. In JavaScript, you can usually omit the semicolon between two statements if those statements are written on separate lines.

Types/Values/Variables

Numbers

Unlike many languages, JavaScript does not make a distinction between integer values and floating-point values. All numbers in JavaScript are represented as floating-point values.

0
3
0xff
3.14

Strings

"hello world"
'hello world'
"Wouldn't you prefer O'Reilly's book?"  

记一次堆栈平衡错误

最近在一个使用Visual Studio开发的C++程序中,出现了如下错误:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

这个错误主要指的就是函数调用堆栈不平衡。在C/C++程序中,调用一个函数前会保存当前堆栈信息,目标函数返回后会把堆栈恢复到调用前的状态。函数的参数、局部变量会影响堆栈。而函数堆栈不平衡,一般是因为函数调用方式和目标函数定义方式不一致导致,例如:

void __stdcall func(int a) {
}

int main(int argc, char* argv[]) {
    typedef void (*funcptr)(int);
    funcptr ptr = (funcptr) func;
    ptr(1); // 返回后导致堆栈不平衡
    return 0;
}

__stdcall修饰的函数,其函数参数的出栈由被调用者自己完成,而__cdecl,也就是C/C++函数的默认调用约定,则是调用者完成参数出栈。