mongo::client::initialize() cause crash

在使用monod的C++ driver时,使用mongo::client::initialize() 方法会导致应用程序crash。

首先要明确一下:

  1. mongo::client::initialize()方法是legacy driver的方法,不推荐和3.X的driver一起使用。
  2. C++ driver是依赖于boost的

mongo::client::initialize()方法中会使用到Option类,但是这个类在头文件中没有定义析构函数,所以就会依赖于编译器来自动推导会这是自动生成的析构函数。crash的原因是,C++的编译器在不同的情况下的推导类型不一样。

case 1

不同的g++版本推导出来的析构函数不一样。所以,如果你的应用程序是用C++11编译的,但是你的driver不是用C++11编译的,肯定会crash。
- For non-C++ 11 builds you typedef stdx::function to be
boost::function.
- For C++ 11 builds you typedef it to be std::function.
https://jira.mongodb.org/browse/CXX-558

case 2.

应用程序的debug版本和release版本生成的析构函数也不一样。这里没有具体的去验证,只是猜想:debug的时候是-g,不会进行优化,这样会编译器会生成Option的析构函数,所以程序不会crash;
但是release版本时,编译器会将要隐式的析构函数drop掉,在link的时候,又发现需要这个函数,于是又生成了一个错误的,然后程序一运行就crash。

ABI vs API

application programming interfaces (APIs), which similarly define interfaces
between program components, but at the source code level.
是源代码级别的,每次都要编译

ABIs (which may or may not be officially standardized) is usually the job of
the compiler, OS or library writer, but application programmers may have to
deal with ABIs directly when writing programs in a mix of programming
languages, using foreign function call interfaces between them.
是binary级别的,如果两个componnet是ABI兼容的话,是可以直接调用的,不需要编译;但是如是不兼容的话,就需要从新编译两者了

ABIs cover details such as:

  • a processor instruction set (with details like register file structure, stack organization, memory access types, …)
  • the sizes, layout, and alignment of basic data types the processor can directly access
  • the calling convention, which controls how functions’ arguments are passed and return values retrieved; for example, whether all parameters are passed on the stack or some are passed in registers, which registers are used for which function parameters, and whether the first function parameter passed on the stack is pushed first or last onto the stack
  • how an application should make system calls to the operating system and, if the ABI specifies direct system calls rather than procedure calls to system call stubs, the system call numbers
  • and in the case of a complete operating system ABI, the binary format of object files, program libraries and so on.

https://en.wikipedia.org/wiki/Application_binary_interface

新版的Linux中的free命令的输出解释

free是用来查看当前系统的内存使用情况的。
在解释之前,先要熟悉几个概念。
共享链接库:它的意思是一些共享的库文件,不需要每个进程都加载到内存中,每个进程可以共享它们。从而达到节省内存的目的。比如libc.

然后是Cache Pages和Buffer,以下是从Redhat的网站上抓出来的。
这里需要注意一点的是:它们的系统来使用的,在新版本的free中是used列中,是没有计算出来的,原因就是在系统的可用内存没有的时候,OS会释放一些Cached或Buffered的内存,给应用程序。

Linux always tries to use RAM to speed up disk operations by using
available memory for buffers (file system metadata) and cache (pages
with actual contents of files or block devices). This helps the system
to run faster because disk information is already in memory which
saves I/O operations. If space is needed by programs or applications
like Oracle, then Linux will free up the buffers and cache to yield
memory for the applications. If your system runs for a while you will
usually see a small number under the field “free” on the first line.

Cache Pages:

A cache is the part of the memory which transparently stores data so
that future requests for that data can be served faster. This memory
is utilized by the kernel to cache disk data and improve i/o
performance.

The Linux kernel is built in such a way that it will use as much RAM
as it can to cache information from your local and remote filesystems
and disks. As the time passes over various reads and writes are
performed on the system, kernel tries to keep data stored in the
memory for the various processes which are running on the system or
the data that of relevant processes which would be used in the near
future. The cache is not reclaimed at the time when process get
stop/exit, however when the other processes requires more memory then
the free available memory, kernel will run heuristics to reclaim the
memory by storing the cache data and allocating that memory to new
process.

When any kind of file/data is requested then the kernel will look for
a copy of the part of the file the user is acting on, and, if no such
copy exists, it will allocate one new page of cache memory and fill it
with the appropriate contents read out from the disk.

The data that is stored within a cache might be values that have been
computed earlier or duplicates of original values that are stored
elsewhere in the disk. When some data is requested, the cache is first
checked to see whether it contains that data. The data can be
retrieved more quickly from the cache than from its source origin.

SysV shared memory segments are also accounted as a cache, though they
do not represent any data on the disks. One can check the size of the
shared memory segments using ipcs -m command and checking the bytes
column.

Buffers :

Buffers are the disk block representation of the data that is stored
under the page caches. Buffers contains the metadata of the files/data
which resides under the page cache. Example: When there is a request
of any data which is present in the page cache, first the kernel
checks the data in the buffers which contain the metadata which points
to the actual files/data contained in the page caches. Once from the
metadata the actual block address of the file is known, it is picked
up by the kernel for processing.

我们来看看free的输出:

- total used free shared buff/cache available
Mem: 65697148 28995804 15909532 1587368 20791812

32578364

total : 表示系统的总内存
used : 表示应用程序已经使用的内存
free : 表示当前还没有被使用的内存
shared :表示共享链接库使用的内存
buff/cache : 表示系统的page cache和buffer使用到的内存
available : 表示应用程序还可以申请到的内存

系统当前使用到的内存是:used + buff/cache,used中包含了shared。

所以total = used + buff/cache + free = 28995804 +20791812 + 15909532 =
65697148。

available(32578364) <= free + buff/cache(15909532 + 20791812 =
36701344),为什么是小于呢?因为系统的一些page或cache是不能回收的。

As of the new available field, for Linux kernels older than 2.6.27,
its value is the same as the free value, but for the later versions of
the Kernel, its a bit different:

Estimation of how much memory is available for starting new
applications, without swapping. Unlike the data provided by the cache
or free fields, this field takes into account page cache and also
that not all reclaimable memory slabs will be reclaimed due to items
being in use (MemAvailable in /proc/meminfo, available on
kernels 3.14, emulated on kernels 2.6.27+, otherwise the same as
free)

refs:
https://askubuntu.com/questions/770108/what-do-the-changes-in-free-output-
from-14-04-to-16-04-mean

http://www.cnblogs.com/chenpingzhao/p/5161844.html

https://access.redhat.com/documentation/en-
US/Red_Hat_Enterprise_Linux/5/html/Tuning_and_Optimizing_Red_Hat_Enterprise_Linux_for_Oracle_9i_and_10g_Databases/chap-
Oracle_9i_and_10g_Tuning_Guide-Memory_Usage_and_Page_Cache.html

うわさ的一些惯用搭配

うわさ

- うわさが立つ、うわさを立てる 流言四起
- うわさが流れる、うわさを流す 流言四起
- うわさがある 有流言
- 噂を(うわさ)すれば影(かげ) 说曹操曹操到


ご馳走になる vs ご馳走する vs ご馳走様でした

简单的说:
ご馳走になる是 别人请我
ご馳走する 是我请别人
ご馳走様でした 是谢谢请客的人款待


复杂的说:

食卓で食事を終えて箸を置き、「ご馳走様でした」という。
在饭桌上吃完饭,放下筷子后,说「ご馳走様でした」
これは無事食事を終え、命をつなぐことができたことへの感謝を口に出したものです。
来表达我能安全无事的吃完饭,并和我的命连起来的感谢。
だから、一人で食事をした場合でも、「ご馳走様でした」ということはあります。
但是一个人吃法的时候,也可以说「ご馳走様でした」。
自宅で、家族で食事をしていた場合は、その食事を用意(調理など)した人と、その食事を用意するために必要だったお
金を稼いできた人に対する感謝も含みます。
在自己家里或者和家族的人一起吃法的时候,也包含对做饭人(这里的人可以是自己家里做饭的人,也可以是外面餐馆为了挣钱而做饭的人)的感谢。

飲食店で、食事を終えて店を出るときに、「緒馳走様(でした)」と、料理人(姿が見えていれば)や店員に声をかけることもあります。
在饭店吃完饭离开时,可以对做饭的人(如果能看到的话)和店员说一句「緒馳走様(でした)」。
合理的に考えると、自分はお金を払っている客だからそんなことを言う必要はない、ということになりますが、料理を作り、もてなしをしてくれたことに対して、自分は満足しましたよ、ありがとう、という気持ちを言葉に出します。
从常理来讲,自己花钱去吃法,不必要说这样的话。然而,给我们做饭,客气的招待我们,自己会不会觉得很满足。这个时候说出一句这样的话,来表示感谢。
もちろん、料理がおいしくなかったり、店員の態度が悪かったりしたら、そんなことは言いません。
当然,如果饭菜很难吃,店员的态度很差,你也可以不说。

職場で上司が、「今日は私がご馳走する(=支払いをする)から、一緒に食事に行こう。」と誘ってきたら、「ご馳走になります。」と答えます。これは、「一緒に行きます。支払いはお任せします。」という意味です。
在公司里,如果老板说“今天我来请客,一起去吃法吧”这样的意见的话,你可以回答「ご馳走になります。」。这就是一起去,我会付款的意思。
食事を終えて、会計を済ませた(その上司が支払った)後で、「ご馳走になりました。」とお礼をいいます。
吃完饭后,当老板结完账后,你可以再说一遍「ご馳走になります。」,来表示感谢

上司や伯父など、目上の人の家に招かれて食事をしたとき、食卓では「ご馳走様でした。」といいます。
如果你被请到上司或者长辈的家里吃饭的话,在饭桌上你要说「ご馳走様でした。」
ホスト・ホステスに対して、感謝の意もありますが、自分は食事を終えました、と伝える意味合いが強いと思います。
在自己吃完饭后,对服务员也可以说。来表示感谢。
食卓上を片付けて、デザートを出すとか、お茶を出すとかしてもいいですよ、ということになります。
当饭桌被收拾好后,上来甜点或茶水的时候,也可以说。
その家を辞するときに「今日は、ご馳走になりました。」といいます。ここで改めてもてなしに対して感謝の意を示すのです。
在离开家的时候,可以说「今日は、ご馳走になりました。」。来再次表示对你款待的谢意。
食事を終えて食卓で、「ご馳走になりました。」ということもありますが、「それでは(=食事は終えたので)、これで帰ります。」というようなニュアンスが漂ってしまうような気がします。
在吃完饭后,说一句「ご馳走になりました。」。在我看来就像是说,”吃完饭了,我该回家了”,的废话一样。

食事をした場所(食堂)から他の部屋に移動するならそれでもいいでしょう。
让我们从吃饭的地方挪到别的地方去吧。

帰宅後に、家人に「食事(夕食)はどうしますか?(=食べますか?)」あるいは「食事はどうしましたか?」と尋ねたれたら、「○○さんに、ご馳走になりました。」と答えます。
回到家里后,家人问“你吃饭了吗”或者“放吃了吗”,你可以说谁谁请我吃饭了
これは、家人が○○さんを知っており、そのことを知っておいてもらう必要がある場合です。
这是在家人知道这个人的时候,并且有必要让家人知道请客这件事的时候
そうではない、自分で支払った食事や、家人に内緒の相手との食事だったら、ただ「(外で)済ませてきました。」と答えます。
如果不是这样,而是自己花钱或者是和一个不需要家人知道的人吃饭,你只需要说“在外面吃了”

翌日、その上司にあったら、「昨日(昨夜)は、ご馳走様でした。」と再度、礼をいいます。
第二天,加到上司后,说「昨日(昨夜)は、ご馳走様でした。」,表示再次感谢
ここで「昨日は、ご馳走になりました。」というのも間違いではありませんが、私は違和感があります。
在这里说「昨日(昨夜)は、ご馳走様でした。」没有什么问题,但是我觉得有点不协调。
明確にどのように誤りなのかは指摘できないのですが、「ご馳走様でした。」のほうが自然だと感じます。
但是没有什么名气的理由。说「ご馳走様でした。」反而更自然

自分と相手との関係によってではなく、場面や時によって使い分けられていると思います。
不是由于对方的关系,而是有地点和时间来决定使用什么
ほとんどの場合は、「ご馳走様でした。」でよいと思います。
「ご馳走になりました。」でなければならないのは、上記の例のように、相手にではなく相手以外の第三者に答える場合だけであると思います。
在大部分场合,使用「ご馳走様でした。」就可以了。只有在像上例中一样,当你想第三方说明,被谁谁请客的时候,才必须使用「ご馳走になりました。」
他の例では、「ご馳走になりました」を「ご馳走様でした」に置き換えても違和感はありません。
其他的场合两个可以相互替换

強いて言えば、「ご馳走様でした」は食事の終了、「ご馳走になりました」は食事を含めたもてなし全体の完了を意味するように思います。
换句话说,「ご馳走様でした」是吃完饭了。「ご馳走になりました」表示包括吃饭在内的所有招待都结束了。
訪問先を辞去するときに、「ご馳走になりました」といえば、「私は帰ります。」の意を含むし、食事会を終えて店を出て、上司に「ご馳走になりました」といえば、「ここで一旦解散。」の意を含んで、帰宅する人あり、別の店に行く人あり、ということになります。
当离开拜访者家里的时候,如果说「ご馳走になりました」,就是说我要回家了。在吃饭的时候,如果给老板说「ご馳走になりました」,意思是这里的事情一旦结束,我就要回家或者去别的地方的意思。

「ご馳走様でした」はそれだけで充分に丁寧な表現だと思います。
一句话,只要说「ご馳走様でした」就可以表现尊敬的意思的。
refs:
https://www.hjenglish.com/q/p371167/
https://oshiete.goo.ne.jp/qa/8872358.html

日语的年份怎么读

日语中的「年」读做「ねん」(nen)。
剩下的年份数字就是按日语数字的读法读就行了。
比如说
2011年读作:にせん じゅういち ねん
1999年读作:せん きゅうひゃく きゅうじゅう きゅう ねん
1948年读作:せん きゅうひゃく よんじゅう はち ねん

注:

  1. 2005年读作にせん ご ねん 二千五年(但是2005年在中文读作“二千零五年”,日语里只读“二千”和“五”就可以了,这是日语数字的一种读法)
  2. 1988年せん きゅうひゃく はちじゅう はちねん,在读 一千,一百,一十的时候不要读”一”,但是一万,一亿,一兆的时候要读”一”
    例:200年にひゃくねん; 如果 201年にひゃく いちねん 中间的”0”不需要读。

refs:

https://zhidao.baidu.com/question/518743542.html?fr=iks&word=%C8%D5%D3%EF%B5%C4%C4%EA%B7%DD%D4%F5%C3%B4%B6%C1&ie=gbk

遅くまで起きる vs 遅くまで寝る

父は毎晩遅くまで寝るようだ
这句话的意思很明显,就是说 爸爸每天晚上都到很晚才睡

父は毎晩遅くまで起きているようだ
这里的 起きる 翻译成不睡觉
所以这句话的意思是: 爸爸每天晚上到很晚都不睡觉 。言外之意就是很晚才睡。和上面是一个意思。
而不能翻译成每天晚上很晚才起来。

mongodb's mapreduce

mapReduce可是实现增量的计算,但是它有以下问题:
1. 使用javascript写成,不便于debug
2. 帮助很少
3. 性能不如aggregate
4. 你可以在mongo shell中使用
- interpreterVersion() ordb.serverBuildInfo()
- 来获得mongo的 javascriptEngine
5. 在3.2中,javascript的执行引擎是 MozJS-38(mozjs)

以下测试数据时在3.4的Java driver测试的,测试数据的格式如下:

> db.test_1.findOne()
{
        "_id" : ObjectId("599d2107faa2eca315046852"),
        "test_name" : "test_name0",
        "value" : 79.39512182533956,
        "site" : 1
}

collection row count | mapreduce with jsMode = true | mapreduce with
jsMode = false | aggregate
—|—|—|—
5000000 | 650425 | 646297 | 4226
10000 | 2260 | 2628 | 50

time unit is milliseconds
https://docs.mongodb.com/manual/tutorial/perform-incremental-map-reduce/
https://docs.mongodb.com/ecosystem/use-cases/hierarchical-aggregation/

TensorFlow basic

TensorFlow basic
1. install Python 3.5+
2. install it with pip3
2.1 config aliyun mirror for pip3, because direct url is very slow
create %APPDATA%\pip\pip.ini file, and add below line to this file:

[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com  

2.2 install
pip3 install –upgrade tensorflow
3. test it
import tensorflow as tf
hello = tf.constant(‘Hello, TensorFlow!’)
sess = tf.Session()
print(sess.run(hello))

Lexical Scoping 和 Dynamic Scoping

Lexical Scoping 和 Dynamic Scoping
A name that is lexically bound is looked up only in bindings in the lexical
environment of the name – that is, in bindings that enclose the name in the
source code. When there are multiple bindings in the lexical environment, the
innermost one is used.
只是在距离被调用代码最近的环境中去找,如果有多个环境的话,从最里面的环境先找

A name that is dynamically bound is looked up only in bindings in the dynamic
environment of the name – that is, in all bindings which have been created
since the program began and which have not yet been destroyed. When there are
multiple bindings in the dynamic environment, the most recently created one is
used.
在从程序启动到现在创建的还没有销毁的环境中去找,找的顺序是按时间序去找(从最新被创建的环境开始)

https://www.emacswiki.org/emacs/DynamicBindingVsLexicalBinding

(let ((x 2))                        ; bind 1
  (let ((f (lambda (y) (* x y))))   ; define a closure with (bind 1) 
    (let ((x 4))                    ; bind 2
      (f 3))))

现在的问题是f函数中的自由变量x从bind 1中获得还是从bind 2中获得?
如果是Lexical scoping的语言的话,在声明lambda的时候,会将当前的环境也就是bind 1保存一份新的环境,假设叫做env-
save,当你调用函数f的时候,自由变量会从env-save中查找,又因为这个保存起来的环境和当前执行的环境不相互影响,所以被称之为闭包。所以输出是:2*3
= 6

如果是Dynamic scoping的语言的话,对函数f中的自由变量,程序会从离自己最近的环境中去找它的值,最近的是bind 2,所以输出是:4*3 =
12

实在不懂的话,可以看看yinwang的 这篇文章