“work-life balance” at school

Everything so far goes great for me. Austin is a nice place: you don’t have to worry about extremely cold weather and unlike Beijing’s summer, the summer here is not about humid air. Everything feels both familiar and strange at the same time. The usual part is that the school life style is the one that I’m most familiar with. However, on the other hand, it feels a little bit strange to me because I become quite okay with working style: you get up, go to work, and after eight hours, you go back home and sleep. To be honest, there isn’t much pressure when you can enjoy your adult single life. You just get out of school, and there is no intensively homework due, and you are free to do whatever you want after work. That’s why I have the opportunity to write bunch of blog posts in the past two years. But, taking a break from work and heading back to school is totally different story. You need to adjust your time schedule back to probably the most intensive and high pressure schedule. There are endless deadlines you have to meet and all of them are quite intense. You cannot say to your professor that due to the limit of resources, you have to push back the GA date of your programming assignment. All in all, you are expected to get the job done in a timely fashion at school (of course, you are also expected this from your boss but lots of factors can make this sentence not strictly hold in a real setting working environment).

That brings up one important issue that people usually emphasize the most when they work: work-life balance. Specifically, under the academia setting, the question becomes:  does work-life balance matter to the students? In my early college year, the answer I’ll give is “No!”. The reasoning is simple: I’m in a state of endless worry. I worry about the job hunting; I worry about I become lazy and don’t make enough out of the expensive tuition and cost of living. So, I spend most of time working at library or labs in the hope of that “hard working” can make myself less anxious. The end result is not good. I can practice this life style until I’m sophomore and I quickly burn out when I’m junior and senior. Those years the intensity of advanced classes and the work in research labs make me breathless. Thanks to the cold weather in Wisconsin, things become even worse: I feel depressed and hopeless. I don’t want to work at all. I end up spending whole days playing video games and I even skip the final exam to my algorithm class in the Fall semester of my junior year.

Now, after two years of work, I gain some new insights from this miserable experience. One thing is about the worry itself. I have been reading Dale Carnegie’s book “HOW TO STOP WORRYING and Start Living“, and in this book, the author says the following:

Clearly, what I needed was a textbook on how to conquer worry – so again I tried to find one. I went to New York’s great public library at Fifth Avenue and Forty-second Street and discovered to my astonishment that this library had only twenty-two books listed under the title WORRY. I also noticed, to my amusement, that it had one hundred eighty-nine books listed under WORMS. Almost nine times as many books about worms as about worry! Astounding, isn’t it? Since worry is one of the biggest problems facing mankind, you would think, would’t you, that every high school and college in the land would give a course on “How to Stop Worrying”? Yet, if there is even one course on that subject in any college in the land, I have never heard of it. No wonder David Seabury said in his book How to Worry Successfully: “We come to maturity with as little preparation for the pressures of experience as a bookworm asked to do a ballet.”

I have strong feelings towards this text. Lots of important lessons are barely taught or even mentioned in school. In most cases, you seem to be expected to find them out on your own from your own experience. It’s a “Swim or Sink” situation. I don’t blame our education system for this because you can hardly come up with a way to teach a course about “worry” with proper assignments and exams. However, those lessons are so crucial to people and you’d better have some tools in your mental toolbox to know how to handle it. Otherwise, sooner or later, some situation or life events will eat you up just like what happened to me in my junior year. There is a sentence from Jesus: “Take no thought for the morrow.”, which gets translated into “Have no anxiety for the tomorrow” in modern English. In other words, we try our best for today and hope for the best. This one is important for me because I don’t want to work ten hours day because of the worry. I want to work ten hours a day because I just want to work on the day.

Work-life balance means important to research as well. There is no doubt that research is a hard job and unquestionably, I will meet various difficulties when working on research projects. However, I want my future self know that even I face challenge in research, I can still have life. I don’t want to put all my eggs in one basket. This is just like researchers want to work on multiple research projects because you always have plan B when one project doesn’t go well. Keeping work-life balance can help you when you start losing faith in this job because, all in all, you still have something left in your pocket.

Advertisements

Some thoughts on learning

刚才在YouTube首页随便打开了一个推荐视频,视频的名字叫做How to Learn Faster with the Feynman Technique (Example Included)。我个人其实很少点开这种带有非常强烈功利色彩的标题去看的,更别提是这种方法论的视频。并不是说我讨厌这类视频,我只是觉得这类视频看多了,如果不立刻去实践的话,看了也没有任何效果,反而浪费掉了很多时间。这个视频本身不长5分钟左右,看完后,我不仅觉得这个方法可以试一试,而且更重要的是让我回忆起过去看过的一些东西以及一些想法。所以赶紧记录在这里。

方法本身并不复杂。具体其实可以看作者这个网页文字版。我就粗略记录一下要点:

这个方法的核心就是explaining the concept。一个典型场景就是去office hour找老师问问题:在你向老师解释完问题,你的疑惑点,以及你的解决方法之后,很有可能出现的情况就是还没等老师说话,你就说:“噢,我懂了。谢谢老师!” 然后转身跑出了办公室。这个场景体现出两个要点:1. explaining the concept确实非常重要 2. 也许这个问题已经在我们的内心里过了无数遍,却只有我们向另一个人解释的时候我们才会 “噢!!!!”。 第一点不难理解。但是第二点确是极度困难:我们从哪里能找到一个愿意天天听我们explain what we have learned的人呢? 上面的视频提出了一种解决办法,步骤如下:

  1. 找张纸,把你要解释的概念写在纸的最上头
  2. 假装有一个第三方在场,用你自己的语言向他解释这个概念。这里作者有几点强调:
    1.  用最通俗易懂的语言来解释
    2. 不要仅限于定义。挑战自己,用例子,图等形式来确定你可以把所解释的概念实际运用起来。
    3. 把在场的这个第三方想像成一个小孩子。这么做的好处就是小孩子会经常问“为什么?” 这个会让我们做到对这个概念的细节有百分百的理解。
  3. 在做完前两步之后,你就要重新回顾你在哪些地方解释出现模糊,拿不准,或者不知道。这些地方就是我们对这个概念理解薄弱的地方。我们要做的就是拿出资料将这些模糊点搞清楚。这步和考完试改错题非常相似。
  4. 这步其实是第三步的引申。就是看之前哪些解释的地方运用了复杂的语言或者堆砌了大量技术概念。我们要做的就是尽力把这些地方用更简洁的语句进行重写。

视频介绍的这个方法其实在各种我所看过的资料里都有体现过。比如在The Pragmatic Programmer一书中讲如何debug一节时,作者介绍的一个技巧叫做”Rubber Ducking”:

A very simple but particularly useful technique for finding the cause of a problem is simply to explain it to someone else. The other person should look over your shoulder at the screen, and nod his or her head constantly (like a rubber duck bobbing up and down in a bathtub). They do not need to say a word; the simple act of explaining, step by step, what the code is supposed to do often causes the problem to leap off the screen and announce itself.

It sounds simple, but in explaining the problem to another person you must explicitly state things that you may take for granted when going through the code yourself. By having to verbalize some of these assumptions, you may suddenly gain new insight into the problem.

这个”Rubber ducking”的来源就是其中一位作者在早期的时候看见一个很厉害的developer经常拿着一个”a small yellow rubber duck, which he’d place on his terminal while coding”。

The Lady Tasting Tea一书的前言中作者也提到作者在写着本书的时候收到了来自他的妻子很多的帮助。因为他的妻子不是statistician,所以如果作者用很technical的语言来写的话,他的妻子根本就看不懂。所以这迫使作者不得不采用更加通俗易懂的语言来解释统计背后的哲学及观念发展。

这也让我想到我最开始写Tech blog的一个主要motivation就是把我所学的东西通过文章的形式解释出来,争取消灭掉不懂装懂的情况。而视频方法的3,4步就是未来我在写tech blog的时候需要更加注意的地方:不要把所学的内容进行简单的归乃重复,要注意用更加简略的语言讲述出来。这里题外话一句:我发现将知识点内嵌在文章里是一个非常不错的保存知识点的方式。这么做我感觉会使知识点不会过于碎片化,并且提供充足的上下文将独立的知识点很有效的串联起来。这也许是“connect the dots”的一种体现吧。

最后用一个quote来作为这篇post的收尾:

“The first principle is that you must not fool yourself — and you are the easiest person to fool.” — Richard Feynman

Sqoop2 7 Minutes Demo with DB2

In this post, I’m walking you through Sqoop 1.99.6 5 minutes Demo with emphasis on working with DB2. Hope this post can save you some time on googling (Believe me, I spent quite some time to get everything figured out when doing this hands-on practice on my own.) Let’s get started.

Preparation phase

Installation

I highly recommended to use cloudera hadoop distribution, CDH for this hands-on lab because CDH has already pre-installed Sqoop2 and has everything well-configured. I have tried out sqoop2 installation on  Hortonworks HDP. The experience is not fun. So, I will assume you work with CDH for the rest of walkthrough.

I’m working with cloudera CDH 5.7.0 and “sqoop-1.99.6-bin-hadoop200”.

  1. Once you have sqoop downloaded, you need to untar it on the client that DB2 instance installed.
  2. You need to download the JDBC 4.0 Driver from IBM that matches with your DB2 version.
  3. You need to install the driver onto CDH sqoop and restart the sqoop service:
sudo cp db2jcc4.jar db2jcc.jar /var/lib/sqoop2/
sudo /sbin/service sqoop2-server stop
sudo /sbin/service sqoop2-server start

Create a test database and table in DB2 to work with

$ db2 list db directory

System Database Directory

Number of entries in the directory = 1

Database 1 entry:

Database alias                       = HZY
Database name                        = HZY
Local database directory             = /home/iidev20
Database release level               = 14.00
Comment                              =
Directory entry type                 = Indirect
Catalog database partition number    = 0
Alternate server hostname            =
Alternate server port number         =

$ db2 connect to hzy

  Database Connection Information

Database server        = DB2/LINUXX8664 11.1.0
SQL authorization ID   = IIDEV20
Local database alias   = HZY

$ db2 list tables

Table/View                      Schema          Type  Creation time
------------------------------- --------------- ----- --------------------------
TEST1                           IIDEV20         T     2016-07-12-20.33.38.801694

  1 record(s) selected.

$ db2 "select * from test1"

C1
-----------
          4

  1 record(s) selected.

Creating Link Object

Check for the registered connectors on your sqoop server:

sqoop:000> show connector
+----+------------------------+-----------------+------------------------------------------------------+----------------------+
| Id |          Name          |     Version     |                        Class                         | Supported Directions |
+----+------------------------+-----------------+------------------------------------------------------+----------------------+
| 1  | kite-connector         | 1.99.5-cdh5.7.0 | org.apache.sqoop.connector.kite.KiteConnector        | FROM/TO              |
| 2  | kafka-connector        | 1.99.5-cdh5.7.0 | org.apache.sqoop.connector.kafka.KafkaConnector      | TO                   |
| 3  | hdfs-connector         | 1.99.5-cdh5.7.0 | org.apache.sqoop.connector.hdfs.HdfsConnector        | FROM/TO              |
| 4  | generic-jdbc-connector | 1.99.5-cdh5.7.0 | org.apache.sqoop.connector.jdbc.GenericJdbcConnector | FROM/TO              |
+----+------------------------+-----------------+------------------------------------------------------+----------------------+

Generic JDBC Connector in our example has a persistence Id 4 and we will use this value to create new link object for this connector:

sqoop:000> create link -c 4
Creating link for connector with id 4
Please fill following values to create new link object
Name: Fist Link

Link configuration

JDBC Driver Class: com.ibm.db2.jcc.DB2Driver
JDBC Connection String: jdbc:db2://9.112.250.80:50591/HZY
Username: iidev20
Password: ********
JDBC Connection Properties:
There are currently 0 values in the map:
entry#
New link was successfully created with validation status OK and persistent id 4

There are two things worth mentioning about DB2:

  1. “JDBC Driver Class” for DB2 is “com.ibm.db2.jcc.DB2Driver
  2. In “JDBC Connection String”, I specify the IP address of the client where DB2 instance resides. Then I specify the port number that is for DB2. Lastly I specify the database name we just created.  The port number “50591” can be obtained by:
$ db2 get dbm cfg | grep SVCE
 TCP/IP Service name                          (SVCENAME) = iidev20
 SSL service name                         (SSL_SVCENAME) =

$ grep xiidev20 /etc/services
xiidev20                      50591/tcp
xiidev20_int                  50592/tcp

Our new link object was created with assigned id 4.

Let us create another link object but this time for the hdfs-connector instead:

sqoop:000> create link -c 3
Creating link for connector with id 3
Please fill following values to create new link object
Name: Second Link

Link configuration

HDFS URI: hdfs://quickstart.cloudera:8020/
New link was successfully created with validation status OK and persistent id 5
  1. “quickstart.cloudera” is the hostname, which can be obtained by hostname command in CDH.

Now, we have created two links. You can check by running show link --all:

sqoop:000> show link --all
2 link(s) to show:
link with id 4 and name Fist Link (Enabled: true, Created by iidev20 at 8/4/16 11:57 AM, Updated by iidev20 at 8/4/16 11:57 AM)
Using Connector generic-jdbc-connector with id 4
  Link configuration
      JDBC Driver Class: com.ibm.db2.jcc.DB2Driver
      JDBC Connection String: jdbc:db2://9.112.250.80:50591/HZY
      Username: iidev20
      Password:
      JDBC Connection Properties:
link with id 5 and name Second Link (Enabled: true, Created by iidev20 at 8/4/16 12:36 PM, Updated by iidev20 at 8/4/16 12:36 PM)
Using Connector hdfs-connector with id 3
  Link configuration
    HDFS URI: hdfs://quickstart.cloudera:8020/

Creating Job Object

Now, we create the job object:

sqoop:000> create job -f 4 -t 5
Creating job for links with from id 4 and to id 5
Please fill following values to create new job object
Name: sqoopy

From database configuration

Schema name: IIDEV20
Table name: TEST1
Table SQL statement:
Table column names:
Partition column name: C1
Null value allowed for the partition column:
Boundary query:

ToJob configuration

Override null value:
Null value:
Output format:
  0 : TEXT_FILE
    1 : SEQUENCE_FILE
    Choose: 0
    Compression format:
      0 : NONE
      1 : DEFAULT
      2 : DEFLATE
      3 : GZIP
      4 : BZIP2
      5 : LZO
      6 : LZ4
      7 : SNAPPY
      8 : CUSTOM
    Choose: 0
    Custom compression format:
    Output directory: /cloudera/

    Throttling resources

    Extractors: 2
    Loaders: 2
    New job was successfully created with validation status OK  and persistent id 3

sqoop:000> show job
+----+--------+----------------+--------------+---------+
| Id |  Name  | From Connector | To Connector | Enabled |
+----+--------+----------------+--------------+---------+
| 3  | sqoopy | 4              | 3            | true    |
+----+--------+----------------+--------------+---------+

The idea here is quite simple. We use JDBC connector to read data from our DB2 table (indicated by -f 4), and then we write the data to HDFS by using -t 5.

Here, you need to pay attention to “Partition column name: C1”. If you don’t specify the partition column, you may hit the error when starting the job:

Exception has occurred during processing command
Exception: org.apache.sqoop.common.SqoopException Message: CLIENT_0001:Server has returned exception

Our new job object was created with assigned id 3.

Start Job (Data Transfer)

Now we are ready to start the sqoop job we just created:

sqoop:000> start job -j 3
Submission details
Job ID: 3
Server URL: http://9.181.139.59:12000/sqoop/
Created by: iidev20
Creation date: 2016-08-04 11:57:43 CDT
Lastly updated by: iidev20
External ID: job_1469730693462_0125
        http://quickstart.cloudera:8088/proxy/application_1469730693462_0125/
2016-08-04 11:57:43 CDT: BOOTING  - Progress is not available

You can interatively check your running job status with status job command:

sqoop:000> status job -j 3
Submission details
Job ID: 3
Server URL: http://9.181.139.59:12000/sqoop/
Created by: iidev20
Creation date: 2016-08-04 11:57:43 CDT
Lastly updated by: iidev20
External ID: job_1469730693462_0125
        http://quickstart.cloudera:8088/proxy/application_1469730693462_0125/
2016-08-04 11:58:30 CDT: RUNNING  - 0.00 %

sqoop:000> status job -j 3
Submission details
Job ID: 3
Server URL: http://9.181.139.59:12000/sqoop/
Created by: iidev20
Creation date: 2016-08-04 11:57:43 CDT
Lastly updated by: iidev20
External ID: job_1469730693462_0125
        http://quickstart.cloudera:8088/proxy/application_1469730693462_0125/
2016-08-04 11:58:47 CDT: RUNNING  - 50.00 %

sqoop:000> status job -j 3
Submission details
Job ID: 3
Server URL: http://9.181.139.59:12000/sqoop/
Created by: iidev20
Creation date: 2016-08-04 11:57:43 CDT
Lastly updated by: iidev20
External ID: job_1469730693462_0125
        http://quickstart.cloudera:8088/proxy/application_1469730693462_0125/
2016-08-04 12:00:02 CDT: SUCCEEDED
Counters:
        org.apache.hadoop.mapreduce.FileSystemCounter
                FILE_LARGE_READ_OPS: 0
                FILE_WRITE_OPS: 0
                HDFS_READ_OPS: 1
                HDFS_BYTES_READ: 110
                HDFS_LARGE_READ_OPS: 0
                FILE_READ_OPS: 0
                FILE_BYTES_WRITTEN: 373985
                FILE_BYTES_READ: 17
                HDFS_WRITE_OPS: 2
                HDFS_BYTES_WRITTEN: 2
        org.apache.hadoop.mapreduce.lib.output.FileOutputFormatCounter
                BYTES_WRITTEN: 0
        org.apache.hadoop.mapreduce.lib.input.FileInputFormatCounter
                BYTES_READ: 0
        org.apache.hadoop.mapreduce.JobCounter
                MB_MILLIS_MAPS: 20448256
                TOTAL_LAUNCHED_MAPS: 1
                VCORES_MILLIS_REDUCES: 82496
                TOTAL_LAUNCHED_REDUCES: 2
                VCORES_MILLIS_MAPS: 19969
                SLOTS_MILLIS_REDUCES: 82496
                MB_MILLIS_REDUCES: 84475904
                SLOTS_MILLIS_MAPS: 19969
                MILLIS_REDUCES: 82496
                MILLIS_MAPS: 19969
                OTHER_LOCAL_MAPS: 1
        org.apache.sqoop.submission.counter.SqoopCounters
                ROWS_READ: 1
                ROWS_WRITTEN: 1
                Shuffle Errors
                CONNECTION: 0
                WRONG_LENGTH: 0
                BAD_ID: 0
                WRONG_MAP: 0
                WRONG_REDUCE: 0
                IO_ERROR: 0
         org.apache.hadoop.mapreduce.TaskCounter
                MAP_OUTPUT_MATERIALIZED_BYTES: 17
                MERGED_MAP_OUTPUTS: 2
                SPILLED_RECORDS: 2
                REDUCE_INPUT_RECORDS: 1
                VIRTUAL_MEMORY_BYTES: 4516757504
                MAP_INPUT_RECORDS: 0
                SPLIT_RAW_BYTES: 110
                FAILED_SHUFFLE: 0
                REDUCE_SHUFFLE_BYTES: 17
                MAP_OUTPUT_BYTES: 3
                PHYSICAL_MEMORY_BYTES: 466186240
                GC_TIME_MILLIS: 1305
                REDUCE_INPUT_GROUPS: 1
                COMBINE_OUTPUT_RECORDS: 0
                SHUFFLED_MAPS: 2
                REDUCE_OUTPUT_RECORDS: 1
                MAP_OUTPUT_RECORDS: 1
                COMBINE_INPUT_RECORDS: 0
                CPU_MILLISECONDS: 7470
                COMMITTED_HEAP_BYTES: 393216000
Job executed successfully
  1. start job -j 3 -s allows you to start a sqoop job and observe job running status. stop job -j 3 will not stop running job at any time.

 

Check Result

we can check the result in CDH:

[cloudera@quickstart ~]$ hdfs dfs -ls /cloudera/
Found 2 items
-rw-r--r--   1 sqoop2 supergroup          0 2016-08-04 09:59 /cloudera/33895be5-a670-4e25-aada-a66fc2cf1919.txt
-rw-r--r--   1 sqoop2 supergroup          2 2016-08-04 09:59 /cloudera/ffe359d6-afe9-40e9-baf9-d2e29937a86c.txt
[cloudera@quickstart ~]$ hdfs dfs -cat /cloudera/33895be5-a670-4e25-aada-a66fc2cf1919.txt
[cloudera@quickstart ~]$ hdfs dfs -cat /cloudera/ffe359d6-afe9-40e9-baf9-d2e29937a86c.txt
4

 

Extra 2 Minutes …

In this section, we transfer data back from HDFS to DB2 table:

sqoop:000> create job -f 5 -t 4
Creating job for links with from id 5 and to id 4
Please fill following values to create new job object
Name: h2d

From Job configuration

Input directory: /cloudera/
Override null value:
Null value:

To database configuration

Schema name: IIDEV20
Table name: TEST1
Table SQL statement:
Table column names:
Stage table name:
Should clear stage table:

Throttling resources

Extractors: 2
Loaders: 2
New job was successfully created with validation status OK  and persistent id 4

Then, we start the job:

sqoop:000> start job -j 4 -s
Submission details
Job ID: 4
Server URL: http://9.181.139.59:12000/sqoop/
Created by: iidev20
Creation date: 2016-08-04 14:53:20 CDT
Lastly updated by: iidev20
External ID: job_1469730693462_0134
        http://quickstart.cloudera:8088/proxy/application_1469730693462_0134/
2016-08-04 14:53:20 CDT: BOOTING  - Progress is not available
2016-08-04 14:53:37 CDT: BOOTING  - 0.00 %
2016-08-04 14:53:48 CDT: BOOTING  - 0.00 %
2016-08-04 14:53:58 CDT: BOOTING  - 0.00 %
2016-08-04 14:54:11 CDT: RUNNING  - 0.00 %
2016-08-04 14:54:21 CDT: RUNNING  - 0.00 %
2016-08-04 14:54:32 CDT: RUNNING  - 0.00 %
2016-08-04 14:54:43 CDT: RUNNING  - 0.00 %
2016-08-04 14:54:54 CDT: RUNNING  - 0.00 %
2016-08-04 14:55:05 CDT: RUNNING  - 0.00 %
2016-08-04 14:55:16 CDT: RUNNING  - 50.00 %
2016-08-04 14:55:27 CDT: RUNNING  - 50.00 %
2016-08-04 14:55:38 CDT: RUNNING  - 50.00 %
2016-08-04 14:55:49 CDT: RUNNING  - 50.00 %
2016-08-04 14:55:59 CDT: RUNNING  - 50.00 %
2016-08-04 14:56:10 CDT: RUNNING  - 50.00 %
2016-08-04 14:56:21 CDT: RUNNING  - 100.00 %
2016-08-04 14:56:35 CDT: SUCCEEDED
Counters:
      org.apache.hadoop.mapreduce.FileSystemCounter
              FILE_LARGE_READ_OPS: 0
              FILE_WRITE_OPS: 0
              HDFS_READ_OPS: 8
              HDFS_BYTES_READ: 427
              HDFS_LARGE_READ_OPS: 0
              FILE_READ_OPS: 0
              FILE_BYTES_WRITTEN: 494580
              FILE_BYTES_READ: 17
              HDFS_WRITE_OPS: 0
              HDFS_BYTES_WRITTEN: 0
      org.apache.hadoop.mapreduce.lib.output.FileOutputFormatCounter
              BYTES_WRITTEN: 0
      org.apache.hadoop.mapreduce.lib.input.FileInputFormatCounter
              BYTES_READ: 0
      org.apache.hadoop.mapreduce.JobCounter
              MB_MILLIS_MAPS: 109466624
              TOTAL_LAUNCHED_MAPS: 2
              VCORES_MILLIS_REDUCES: 135729
              TOTAL_LAUNCHED_REDUCES: 2
              VCORES_MILLIS_MAPS: 106901
              SLOTS_MILLIS_REDUCES: 135729
              MB_MILLIS_REDUCES: 138986496
              SLOTS_MILLIS_MAPS: 106901
              MILLIS_REDUCES: 135729
              MILLIS_MAPS: 106901
              OTHER_LOCAL_MAPS: 2
      org.apache.sqoop.submission.counter.SqoopCounters
              ROWS_READ: 1
              ROWS_WRITTEN: 1
              Shuffle Errors
              CONNECTION: 0
              WRONG_LENGTH: 0
              BAD_ID: 0
              WRONG_MAP: 0
              WRONG_REDUCE: 0
              IO_ERROR: 0
      org.apache.hadoop.mapreduce.TaskCounter
              MAP_OUTPUT_MATERIALIZED_BYTES: 29
              MERGED_MAP_OUTPUTS: 4
              SPILLED_RECORDS: 2
              REDUCE_INPUT_RECORDS: 1
              VIRTUAL_MEMORY_BYTES: 6016950272
              MAP_INPUT_RECORDS: 0
              SPLIT_RAW_BYTES: 420
              FAILED_SHUFFLE: 0
              REDUCE_SHUFFLE_BYTES: 29
              MAP_OUTPUT_BYTES: 3
              PHYSICAL_MEMORY_BYTES: 670957568
              GC_TIME_MILLIS: 4852
              REDUCE_INPUT_GROUPS: 1
              COMBINE_OUTPUT_RECORDS: 0
              SHUFFLED_MAPS: 4
              REDUCE_OUTPUT_RECORDS: 1
              MAP_OUTPUT_RECORDS: 1
              COMBINE_INPUT_RECORDS: 0
              CPU_MILLISECONDS: 9510
              COMMITTED_HEAP_BYTES: 453255168
Job executed successfully

Finally, we verify the result from DB2’s perspective:

$ db2 "select * from test1"

C1
-----------
          4
          4

  2 record(s) selected.

Understanding shebang + eval combo from ancient perl script

During the daily development, we have a collection of scripts to help us automate some mundane task. Most of them are written in perl and quite often, I feel shamed to be a programmer that only know how to use those scripts without actually taking a look at their source code. However, I don’t know perl by any measure and recently, I decided to take this challenge: I quickly went through the basic aspects of the language (with the help of this nice tutorial: Learn Perl in about 2 hours 30 minutes )  and dived directly into some scripts to start reading. Then I met this daunting code chunk from the very beginning of a perl script:

#!/usr/bin/perl
eval 'exec perl5 -S $0 ${1+"$@"}'
   if 0;

So, I spent some days digging, and finally get this code chunk clears out. I’ll try my best to explain this code chunk in a newbie-friendly way (because I am one of them :)).

History

Usually, it is unnecessary for people to know that if a script should be executed by Perl, shell, or other interpreters. In other words, they can execute the script by typing the filename and the script itself will find the right interpreter to run it. This is usually done with shebang.  In perl, the common way to do so is to write


#!/usr/bin/perl

at the very first line of your perl script. However, not all system supports shebang and most likely, those systems will run your script as if it is a shell script, which, of course, will lead to the failure of execution. In this case, we need to figure out a way to tell those systems that “even if you are running the script as a shell script, please invoke perl interpreter to interpret the content of the script” and that is exactly what that daunting code does.  Now, let’s dive into this code chunk to see how it works.

Dive in

#!/usr/bin/perl
eval 'exec perl5 -S $0 ${1+"$@"}'
   if 0;

 [1]:  First line of code uses shebang and it invokes perl interpreter located under /usr/bin/, which should be enough  for systems that support shebang to know which perl interpreter should be used to run the content of script.

[2-3]:  For system that support shebang, the system already knows the content of script should be interpreted as perl. So, line 2 – 3 will be treated as perl. Since “Carriage return” is the same as “whitespace” in perl world, line 2 -3 will not get executed because of if 0. However, for system that doesn’t support shebang, the whole script is treated as shell script and thus, line 1 will be treated as shell comment and ignored. Then, the system continues to run line 2 – 3 as shell command. There is one important difference between perl and shell (i.e., bash) is that perl will spot the continuation line (because carriage return is the same as white space) but not bash. So, shell will first execute line 2. For now, let’s just say line 2 executed by shell will tell the system that “to re-run the whole script again under perl and where to find perl interpreter” (we will investigate more in detail in the following section). So now our goal is achieved: system that doesn’t support shebang will go ahead to use specified perl interpreter from line 2 to re-run the whole script as perl script. During the re-run, line 2-3 will get ignored by perl.

Line 2: what the heck is this?

Now, let’s study code from line 2 in detail.

eval 'exec perl5 -S $0 ${1+"$@"}'

The eval in shell takes a string as its argument, and evaluates it as if you’d typed that string on a command line. So, the shell actually executes

exec perl5 -S $0 ${1+"$@"}

$0 get expands to the name of the script by shell. However, ${1+”$@”} looks quite mysterious. It involves an ancient Bourne shell bug (if no argument provided, it uses an empty argument instead of nothing) and the article What does ${1+”@”} mean explains it very clear:

The ${1+"$@"} syntax first tests if $1 is set, that is, if there is an argument at all.
If so, then this expression is replaced with the whole "$@" argument list.
If not, then it collapses to nothing instead of an empty argument.

Aside note on ${1+"$@"}, it follows ${parameter+alt_value} pattern: If parameter set, use alt_value, else use null string. See more on it here.

So now, we can put all pieces together: when shell executes line 2, perl program (i.e. perl5) will be invoked and execute the script itself (expand from $0) and supply the argument list, which may be required by the script.

Example

Let me give an example.

Suppose we have a perl script named foo:

#!/usr/bin/perl
eval 'exec /wsdb/oemtools/linux/bin/perl5.16.2 -S $0 ${1+"$@"}'
    if 0;

use Config;
my $perl = $Config{perlpath};

print $perl."\n";

Besides the daunting code chunk, the rest will print out the absolute path of perl interpreter that our script get executed by. Now, let’s try out different way of executing our perl script foo:

$ perl foo
/usr/bin/perl
$ ./foo
/usr/bin/perl
$ sh foo
/wsdb/oemtools/linuxbin/perl5.16.2

The first two cases, we run the perl script in a standard way, since my system (SUSE Linux 11) supports shebang, the script gets executed by the perl interpreter specified in the shebang line. However, if we try to mimic the system that doesn’t support shebang by executing our script using shell (i.e., sh), the script is also get interpreted as perl script but with the perl interpreter from eval part. Notice sh usage here, sometimes the user of the script may assume the script is written by shell, and they will try to execute the script by sh. Then, in this case, our daunting code chunk provides a defensive mechanism that allows the perl script to be executed correctly even when it is run by shell.

With this explanation, I don’t think code chunk in find2perl will be daunting to you now:

#! /usr/bin/perl -w
    eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
        if 0; #$running_under_some_shell

 Modern days

Nowadays, people rarely use that daunting code chunk solely because some systems don’t support shebang. Increasingly, that daunting code chunk usually appears when people want to use a specified version of perl (not system default one like /usr/bin/perl) and at the same time, maintain some portability to the system that doesn’t support shebang. However, if we solely consider to use a specified version of perl instead of default one, then there is more than one way to do so. My list may not complete. Please feel free to comment below if I miss some usage on invoking customized perl.

#!/usr/bin/perl
eval 'exec /wsdb/oemtools/linux/bin/perl5.16.2 -S $0 ${1+"$@"}'
    if 0;

The first way is again our daunting code chunk. If we run our script by sh, then our customized perl (i.e., /wsdb/oemtools/linux/bin/perl5.16.2) is executed. -S as perl command option used here is to make perl use PATH environment variable to search for the script because on some system $0 doesn’t always contain the full pathname to the script. You can read more about -S option in perlrun doc and in fact, the daunting code chunk also got explained there.

The second way is to put the following code at the first line of perl script:

#!/wsdb/oemtools/linux/bin/perl5.16.2

This way you directly hardcode the customized perl interpreter in your script. This may sacrifice portability of the script.

Another way to use customized perl interpreter is put this code chunk, again, at the first line of the script:

#!/usr/bin/env perl

This will tell the system (that understands the shebang) to find the first “perl” executable in the list of $PATH. If you want to run your customized perl interpreter this way, you want to put the path to your customized perl interpreter at the beginning of $PATH environment varaible so that you ensure if first “perl” executable found by the system from $PATH is indeed the perl interpreter you want to use.

The last way to run your customized perl interpreter is somewhat similar to our daunting code chunk but with significant difference:

#!/bin/sh
#! -*-perl-*-
eval 'exec /wsdb/oemtools/linux/bin/perl5.16.2 -x -wS $0 ${1+"$@"}'
    if 0;

Let’s run it first to see what we can get. Like previous example section, we put the above code chunk inside a script called bar:

#!/usr/bin/sh
#!-*-perl-*-
eval 'exec /wsdb/oemtools/linux/bin/perl5.16.2 -x -wS $0 ${1+"$@"}'
    if 0;

use Config;
my $perl = $Config{perlpath};

print $perl."\n";
$ bar
/wsdb/oemtools/linuxbin/perl5.16.2
$ perl bar
/wsdb/oemtools/linuxbin/perl5.16.2
$ ./bar
/wsdb/oemtools/linuxbin/perl5.16.2
$ sh bar
/wsdb/oemtools/linuxbin/perl5.16.2

No matter how we execute our script, we always use our customized perl interpreter, even when system perl is explicitly specified (i.e., perl bar). The significant difference than our original daunting code chunk is the use of -x option. The -x does the following:

tells Perl that the program is embedded in a larger chunk of unrelated text, such as in a mail message. Leading garbage will be discarded until the first line that starts with #! and contains the string “perl”. Any meaningful switches on that line will be applied.

Let me walk through what exactly happen in our case. We will use the following information taken from perldoc during the walkthrough as well:

 If the #! line does not contain the word “perl” nor the word “indir”, the program named after the #! is executed instead of the Perl interpreter. This is slightly bizarre, but it helps people on machines that don’t do #! , because they can tell a program that their SHELL is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them.

We launch our bar script as ./bar:

1. Shell executes our script ./bar
2. The system actually executes /bin/sh ./bar because of our shebang specification.
3. sh executes /wsdb/oemtools/linux/bin/perl5.16.2 -x -wS bar
4. /wsdb/oemtools/linux/bin/perl5.16.2 skips:

#!/usr/bin/sh
#!-*-perl-*-
eval 'exec /wsdb/oemtools/linux/bin/perl5.16.2 -x -wS $0 ${1+"$@"}'
    if 0;

and executes:

use Config;
my $perl = $Config{perlpath};

print $perl."\n";

Let’s break down this step into further detail:

4.1 /wsdb/oemtools/linux/bin/perl5.16.2 executes /usr/bin/sh ./bar because it sees a shebang that doesn’t contain the word “perl”
4.2 eval part get executed (i.e., sh executes
/wsdb/oemtools/linux/bin/perl5.16.2 -x -wS bar
)
4.3 Since -x is specified, the first line #!/usr/bin/sh is ignored because it is a shebang but doesn’t contain the string “perl”. Line 2-3 is ignored because if 0. So, the execution starts with use Config; and move forward.

Let’s try launch our bar script using perl bar to see why system perl is not used in this case:

1. Shell executes the script perl bar
2. perl (i.e. /usr/bin/perl) executes /bin/sh bar because it sees a shebang that doesn’t contain the word “perl”
3. eval part get executed (i.e., sh executes
/wsdb/oemtools/linux/bin/perl5.16.2 -x -wS bar
)
4. So our script bar is executed by /wsdb/oemtools/linux/bin/perl5.16.2 instead of /usr/bin/perl

Let’s Practice

Based upon what we learn, you should not have much trouble understanding why

#!/bin/sh
eval 'exec /wsdb/oemtools/linux/bin/perl5.16.2 -wS $0 ${1+"$@"}'
    if 0;

will lead to

/bin/sh: -S: invalid option

error. The key lies in we are not using 1) shebang + string word “perl” and 2) -x option. If you have hard time finding out why, here is the answer.

Thanks for the reading!

 Reference

GRE考后总结

历时3个月的准备,今天我终于考完了GRE。 最后的结果是V157 + Q168我还是比较满意的(这比我两年前V153+Q165还是有所进步的)。下面我就对整个GRE准备+考试做个小结,也是对自己这三个月做个回顾。

备考

我整个备考其实主要参考了向死而生的首战GRE330+4.0的经验分享。下面我就结合一下我的具体情况谈一谈我的经验教训。

个人情况和分数

理论上来说这次是我二战GRE,两年前的秋天我在Madison考的第一次。当时的成绩是318 (V153+Q165)+3.5。第一次备考整体准备是不认真的。由于当时心态非常不好外加觉得只要有个GRE分数就可以了,所以考前没有练过写作,没有做过模考,单词只是看过一遍,数学做过OG就上阵了。所以对于那个成绩我也是可以接受的。这次,我给自己制定的目标是330,最低下限是320。所以,对于这次325我也是可以接受的。

开始备考是从今年三月中旬开始的。由于我是全职工作的,所以一周的主要复习时间主要集中在周中的晚上和周末。平常工作非常忙,到家吃完饭后就已经8,9点钟了。所以真正能系统复习的时间主要是周末。最后离考试还有一周的时候,我请了4天年假在家做最后的冲刺(6月21日-6月24日)。

关于新东方和Magoosh

两次考G我都没有报名参加新东方。准确来讲,我只有在2012年暑假也就是大二的暑期报过一次新东方GRE强化班。但是由于距离我真正考G时间过于久远,所以我觉得新东方GRE对于考G帮助不大。所以我最推崇的还是以Magoosh复习为主,其他一些备选资料为辅的复习方式。至于Magoosh的好处,在向死而生的帖子里也有所提及,我就不再赘述了。

总体就Magoosh难度来讲,我觉得数学确实比实际考试要难上一些,但是感觉实际考试难题多出现在统计上面,而Magoosh的难题以代数居多,但是我觉得对于复习G的数学,Magoosh数学还是非常够用的。Verbal方面, Magoosh的text completion难度绝对是够的。其难度不仅体现在逻辑方面,在词汇方面也会有很大挑战。Magoosh的RC,尤其是长阅读还有paragraph argument还是比实考难度大一点。其实这种难度感觉和真题的差异性上面因人而异,也因做题量多少而有所不同,所以,我的观点仅供参考。

我下面简单列出一下我Magoosh做题的情况,希望对大家有个参考

  • 数学,刷了640题,剩余0题没刷,总体正确率85% (由于后边又将错误的题目重新做过一遍所以按难度划分的统计不准,就不写在这里了)
  • Verbal, 刷了302题,剩余252题没刷,总体正确率53%
    • text completion刷了180题,总体正确率49% (88/180), easy 91% (21/23), medium 53% (29/55), hard 40% (33/83), very hard 26% (5/19)
    • sentence equivalence刷了30题,总体正确率50% (15/30), easy 60% (3/5), medium 58% (7/12), hard 38% (5/13),  very hard 0% (0/0)
    • reading comprehension刷了92题,总体正确率62% (57/92), easy 93% (13/14), medium 71% (20/28),  hard 59% (23/39), very hard 9% (1/11)

tl;dr Magoosh为主,其余资料为辅。

单词

我最开始是用的百词斩背单词。百词斩背单词最大好处是每个单词有四幅图片,可以让你对一些单词快速记忆。这个对一些晦涩死活也记不住的单词效果非常明显。但是这也伴随着问题。那就是真实GRE你是需要看到单词直接反映出每个单词的英文释义的。用百词斩背久之后,你首先想到的其实是你记住的图片。这无形当中会浪费一定时间,因为你需要将图片进行二次翻译,翻译成英文释义。另外一点不足就是百词斩没有对单词的英文释义。这点尤其致命。

背好《要你命3000》是非常重要的。背的好坏直接影响填空能拿到多少分。而背的好与不好的评判标准非常简单,那就是如果你对3000里的单词掌握得像对apple, pear一样熟悉的话,那你的单词准备就是非常成功的。具体的背法因人而异。我的背法首先是拿着3000的书去看中文,再看英文释义和例句。如果英文释义,例句用法与中文释义吻合,那么我就记住中文释义。如果不吻合,我就要牢记英文释义。对于每个单词,我都会去联想一下之前背过的哪些单词和这个单词含义相近或者在拼写形式上与这个单词拼写相近,然后我会记在这个单词的旁边。这个做法的好处一是补充3000里每个单词近义词没有归纳全的地方,另一个好处是增加一个单词的出现频率。如果一个单词在你翻3000时每隔几页就会出现一次,那么你想记不住都很难呀。

背3000另一个工具就是网上有人总结好的3000单词excel表。这里我用的是一个白词灰词黑词的方法。如果一个单词你看着就跟看apple一样亲切的话,那就把它标成白词(即底色为白色,字体为黑色);如果一个单词你每次有点似是而非,有的时候想的起来,有的时候想不起来的话,那么你就把它标记为灰词(即底色为浅灰色,字体为黑色);最后,如果一个单词你死活都记不住,那么你把它标记为黑词(底色为黑色,字体为白色) 。这么做的目的是更加有的放矢的去记单词,而不是每个单词都要花一定脑力去记。

另一个要背的就是Magoosh GRE flashcard。这个可以用Magoosh官方提供的GRE Prep Vocabulary App来记。这个App做的非常好。每个单词后边的释义都是英文的,并且伴有带有GRE式的例句。每个不会的单词它会按照一定特殊的频率去重复,保证你会将这个单词牢记。

向死而生的帖子里还提到了SuperMemoUX。这个应用本身确实非常强大。但是现在网上能搜到的3000文本库是需要安装金山字体的。这个字体在我这里不知道什么原因始终无法在SuperMemoUX里正确显示,导致整个软件使用感觉欠佳。

最后,就是要背一些填空中出现的单词了。这个可以作为背3000和Magoosh单词之外的补充。这个重点还是要放在看单词在题目中的实际用法。这些单词需要平常大家去积累一下。我个人用的是sphinx-doc来将以restructuredtext文本形式储存的单词以网页的形式生成出来的。这样做的好处就是在平常break的时候可以打开来看一下。

tl;dr 背3000和Magoosh单词要到像看到apple一样熟练,但具体记忆方法因人而异

填空

填空本身没有什么技巧,只要你单词量足够强大,读得懂题目,题目你就会做。我看到网上很多人对陈圣元的书很是推崇。这里我的看法是题目确实是可以去做的。尤其是在背单词的阶段,陈圣元的书会让你在实战中去体会3000中出现的词汇的用法,会使整个背单词的过程不会那么枯燥,同时也会增强战胜GRE填空的信心。但是陈圣元前面会去集中讲解填空的做题技巧。我个人的体会是上来就看这个帮助不大,反而会变得为了套用技巧而去做题,忽略了单词的重要性。当你做题目做到一定程度的时候,陈圣元前面技巧可能会有点醒梦中人的效果。

我个人比较喜欢的是Magoosh中关于填空的讲解。实际非常简单,那就是你通读整个句子,然后根据句子,用你自己的词汇将句子中的空补全,然后再看选项去选择和你自己词汇意义最接近的答案就可以了。

tl;dr 填空中单词最重要!结合Magoosh填空讲解集中去做Magoosh填空和陈圣元填空吧!

阅读

阅读机考这点对于我这种凡是读东西就喜欢拿根笔的人来说造成了莫大的困难。说说我是怎么准备的吧。

首先我用的是“花儿阅读”。这本书针对的应该是老G,但是前几章讲文章结构(TS, SE), 文章出题点(转折,比较,人物观点),题目类型,题目解法还是同样适用于新G的。尤其是文章结构,我在读的时候有一种捅破窗户纸的感觉。以前是我拿到一篇阅读上来就去读,但是现在我在读的时候会更加关注文章结构,这会很大程度上帮助我更好的去了解文章大意,更好的去应对主旨题,以及帮助细节题定位。当然后面花儿阅读中会讲一些如何做笔记的方法,这点大家就可以不用特别关注了。毕竟新G已经是机考,做笔记只会耽误时间(主要是因为新G阅读不带行号了,这点对做笔记法尤为致命,但是如果哪天新G阅读又带行号了,那么我觉得对于长阅读,适当做笔记还是有必要的)。

接着我去做了陈虎平36套。这里我从第17套开始做的。也就是每套标准10道题。这里我计时做在17-18分钟的时候正确率在60%-70%。在做了7套题后,我就开始集中在Magoosh上做题了。这里我还是建议尽早去在真实条件下(盯着电脑屏幕,无发做笔记的情况下)去做题。很多时候机器上做题的正确率是要比在纸上来做要低的。

tl;dr 花儿阅读学技巧,Magoosh来练

写作

写作由于还没有出分我就不多谈了。我个人非常喜欢Magoosh的阅读讲解,怎么去写,怎样体现analytical response讲解的非常清楚。尤其是写issue时,只花2min写主题,然后写body,conclusion,最后再写intro的方法让我受益匪浅。因为我依然记得我第一次考G的时候,6-7分钟就花在构思如何写第一段了。Magoosh里管这个现象叫做Perfect work syndrome。很多时候你写出body后,写intro就是自然而然的事了。

EDIT (07/29/2016):

我最后写作成绩是4.0。这个可以说是Magoosh写作方法的功劳。当然,因为我是美本,平常上学的时候写作机会还是很多的。因此,也不能说Magoosh所教的写作就能包治百病了。但是,对于平常有一定的写作功底,但是不知道GRE写作套路的同学,我严重推荐Magoosh写作视频!

tl; dr 看Magoosh写作视频

数学

我之所以能把640道Magoosh数学题刷完,主要是因为我每天8,9点钟到家后还有力气做的就是做几道数学题。平常我个人把一些Magoosh题目中出现,自己忘记的数学知识点都会同样用收集起来。

最后一周里,我又集中的把95道做错的题重新做了一遍,并且把一些我认为自己容易错的题用错题本整理了一下。最后,我又把平时收集的知识点过了一下。虽然最后数学没有拿满分,但是我觉得还是没有遗憾的,因为确实出现了平常没有见过的题目(是道关于median的题目)

tl;dr 做Magoosh数学,总结错题及知识点

模考

我个人在考前倒数第二天,和倒数第一天分别做了PP2的第二套和第一套。模拟成绩分别是V154+Q170和V156+Q170。从我考出来的成绩看,PP2还是很准的。有一点PP2没有的就是随机加试。

tl;dr 用PP2来做模考

复习资料一揽

  • Magoosh
  • 要你命3000
  • Magoosh GRE flashcard
  • 陈圣元填空
  • 花儿阅读
  • 陈虎平36套
  • OG
  • 杨鹏长难句

教训

  • 单词! 单词! 单词! 单词背的好不好直接决定你G能考多少。一定要把3000背的像看到apple那样熟。这点即使我到考试前一天也没有做到。
  • 杨鹏长难句 阅读很多时候你即使读了却很难在保证阅读速度的同时理解句子的含义。这点对于TS尤其致命。如果TS是一个长难句,但是你却始终没有读懂,那么你做这篇阅读的难度无疑是会大大增加的。《杨鹏长难句》恰好是用来针对读长难句来训练的。我个人在这方面做的远远不够,这大概也是我verbal没上160的原因之一吧。
  • 模考最好提前1个月做一套 我觉得模考还是要提前1个月做一套的。这样会给自己留出充裕的时间查缺补漏。我最后发现自己paragraph argument还是弱项,但是已经没有时间再做改进了。
  • 时间成本 我住在南三环外,公司地点在北五环外,每天通勤时间就长达4个小时。再加上本身从事软件开发,一天下来可以说是身心俱疲。6点钟从公司出来,到家就7点半,8点了,很难有力气再去复习一些比较耗脑力的GRE部分(如阅读)。所以,如果可能的话,还是想办法尽可能节约一些时间成本和一些不必要的体力浪费。这点在我看来对于非脱产考G的工作党来讲非常重要。
  • 文学类阅读 在所有阅读题材中,我觉得文学类阅读是最难得。因为描述往往非常抽像,讨论的内容很多是nusance级别,所以在平常练习的时候应该更加重点训练。我这次3个V中印象中只考了一篇文学类阅读,确实非常幸运。但是,在今后考G中还是不要抱着侥幸心态为好。
  • 写作题库还是要看一遍 每个题目如果能写一下或者列一下提纲就最好不过。但是最基本的是应该把issue以及argument的题目都过一遍,看看有没有题目都读不懂的情况!比如说我这次写作issue题目是

Claim: It is no longer possible for a society to regard any living man or woman as a hero.

Reason: The reputation of anyone who is subjected to media scrutiny will eventually be diminished.

Write a response in which you discuss the extent to which you agree or disagree with the claim and the reason on which that claim is based.

          感觉我就写的有点跑偏因为我没能很好的理解media scrutiny的含义。最后就这个题目再多说一    句。向死而生的帖子里提到台湾老师的写作题目出现频率 而这次我这个题目在里面是1,也就是说有时     间还是尽量把每个题目都读一遍看理解题目是否障碍,然后再列一下提纲避免考场慌张。

          哦,对了,这次argument我遇到的是

The following appeared in a memo to the board of directors of Bargain Brand Cereals.

“One year ago we introduced our first product, Bargain Brand breakfast cereal. Our very low prices quickly drew many customers away from the top-selling cereal companies. Although the companies producing the top brands have since tried to compete with us by lowering their prices and although several plan to introduce their own budget brands, not once have we needed to raise our prices to continue making a profit. Given our success in selling cereal, we recommend that Bargain Brand now expand its business and begin marketing other low-priced food products as quickly as possible.”

Write a response in which you discuss what questions would need to be answered in order to decide whether the recommendation and the argument on which it is based are reasonable. Be sure to explain how the answers to these questions would help to evaluate the recommendation.

考试当天

我报名的是高等教育出版社马甸考点(北京市西城区德外大街4号 高等教育出版社A座3层)。让我很吃惊的是,整个考试体验比我在Madison Prometric center考试体验要好上很多。原因如下

  • 马甸考点在我考的时段是只有GRE考试的,这和prometric center不一样。不知道是不是因为整个Madison只有一个考点的原因,不管是GRE还是托福或者精算考试都是同一个考点。而且整个prometric center只有一个屋子,这就导致你在考GRE的时候很有可能会有人在对着屏幕大声说话(没错,他在考托福)。这就对发挥造成了很大影响。
  • 马甸考点是统一开始GRE考试的。准考证上写的是9点30分开始入场,10点开始考试。这点和中国其他考试非常相似。这点好处是大家都会处在一个模块下考试。同时开始写作,狂敲键盘。同时开始安静算数。这就很大程度上避免了一个人在聚精会神做verbal或者数学的时候,另外一个人在狂敲键盘写作文影响别人的情况的发生。在Prometric Center考试情况有点不一样。虽然也会要求你在几点之前进场准备考试,但是早到早考,晚到晚考的特点会很大程度上造成参加考试人的不同步,也就非常容易出现我之前描述的互相干扰的情况。
  • 马甸考点在第3个section结束中间休息10分钟的时候,工作人员会把每个考生用过的草稿纸替换成新的草稿纸。最开始的时候每个人会发3张,但是如果没有人去替换的话,就会很有可能导致考生在做到第二个数学的时候出现草稿纸不够用的情况。这就会导致考生频繁的举手索要新的草稿纸,从而产生频繁的走动,影响其他考生。相对应的在prometric center, 监考员是不会主动帮你去更换草稿纸的。
  • 马甸考点用的铅笔是子弹头铅笔,这能保证你时时刻刻铅笔头都是尖锐的状态。而且考场标配是2根,但是你可以索取更多。Prometric center的铅笔就是正经的2B铅笔,笔头磨损非常快,这在做数学的时候非常影响心情。同时,我需要打断自己做题节奏去换取新的铅笔,并且监考员会看一下铅笔是否真的有磨损,这让人心情非常不爽。

至于说临街的问题大家不用担心,由于是出版社并不是大学,不会出现非常吵闹的情况。我在考的时候也就听见了偶尔一两声车响(不是鸣笛那种)。唯一的遗憾就是考场不提供饮水机,过去考试的时候要带好充足的饮用水。

关于实际考试没有什么多说的,我还是一如既往的人品差碰到的是QVQVQ。

tl;dr 北京考的话选马甸考点,比美国madison的prometrc center要好哟!

最后祝考G,申请成功!

后记(07/26/19更新)

我在这里更新一下GRE Diagnostic Service中提供的信息吧。仅供参考!

Quantitative Reasoning

Verbal Reasoning

 

Quick primer on checking database object privileges in DB2 LUW

db2talk

If you are a DBA, you will inevitably work on troubleshooting/ granting / revoking object privileges to database users. In this blog post, I am going to share how to check for privileges that have been granted to an object in a DB2 LUW database. This post is an introductory level post for new DBAs. Database level authorities are not discussed in this post.

View original post 461 more words

Way to be pro

This is gonna be a live update post. All the experience I acquired in order to become a *professional* programmer are listed here. This will be a reminder for me, and hope it is somewhat useful to you 😀

M/D/Y

09/01/15:

1. Be aware of coding convention used in the file

What’s the difference between the following two chunks of code?


if (block_buf > REQUESTS_BLOCK_BUF_MAX){

my_requests_block_buf = REQUESTS_BLOCK_BUF_MAX;

} else {

my_requests_block_buf = block_buf;

}


if (block_buf > REQUESTS_BLOCK_BUF_MAX)

{

my_requests_block_buf = REQUESTS_BLOCK_BUF_MAX;

}

else

{

my_requests_block_buf = block_buf;

}

I guess you would say they are literally the same. In fact, that was what I thought initially, and I chose to write the code like the first one. However, in the code review, this chunk of code is commented by reviewer “Note the coding convention in the file.” Then I realized with more than 3,000 lines of code, all the condition structure is following the second one I listed above. So, consistency in style is really the key in professional programming.

2. Don’t add redundant debug statement

Following the code chunk I added above, it is probably natural to add a printout statement to see if my_requests_block_buf is actually set to the right value. So, I added:


pdTraceData1(FUNCTION_TRACE_ID,
             1992,
             PD_SINT(my_requests_block_buf));

However, this statement may not be OK in the professional setting. There is a clear cutline between what can include in development phase and what should include in actual product. The debug statement is OK for development phase: developer need to immediately make sure everything work correctly so far before moving on to next part, and this is exactly the incremental development philosophy. But, once developer are pretty sure the value he get is correct, he need to delete the debug statement. With excessive debug statements, the performance of product hurts. 

3. Treat comment as serious as code

I developed a bad habit to joke around in the comment during the college, and I somewhat carry it out to the real job. This is one of the comments I wrote in my recent work:


// cheat on initialize_server() function
#define REQUESTS_BLOCK_BUF_MAX_OLD 1024  

If this comment appears in a hobby project or the project that shared with limited people, it will be fine. However, it might not be appropriate when comes to real business. And, this comment is essentially useless: why named “OLD”? What do you mean by “cheating”? My fellow developers will have no clue what I am trying to convey here.