<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
    <channel>
        <title>CUBRID Blog</title>
        <link>http://blog.cubrid.org</link>
        <description>Latest stories in the CUBRID Blog</description>
        <language>en</language>
        <pubDate>Wed, 07 Sep 2011 03:12:42 +0900</pubDate>
        <lastBuildDate>Tue, 21 Feb 2012 02:24:05 +0900</lastBuildDate>
        <generator>XpressEngine 1.4.4.1</generator>
                        										        <item>
            <title>Understanding JVM Internals</title>
            <dc:creator>Se Hoon Park</dc:creator>
            <link>http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals/</guid>
                        <comments>http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals/#comment</comments>
                                    <description><![CDATA[<p>Every developer who uses Java knows that Java bytecode runs in a JRE (Java Runtime Environment). The most important element of the JRE is <b>Java Virtual Machine</b> (JVM), which analyzes and executes Java byte code. Java developers do not need to know how JVM works.&nbsp;So many great applications and libraries have already&nbsp;been&nbsp;developed without developers understanding JVM deeply.&nbsp;However, if you understand JVM, you will understand Java more, and will be able to solve the problems which seem to be so simple but unsolvable.</p><p>Thus, in this article I will explain how JVM works, its structure, how it executes Java bytecode, the order of execution, examples of common mistakes and their solutions, as well as the new features in Java SE 7 Edition.</p><p></p><h2>Virtual Machine</h2><p><b><span class="Apple-style-span" style="font-weight: normal; ">The JRE is composed of the Java API and the JVM. The role of the JVM is to read the Java application through the Class Loader and execute it along with the Java API.</span></b></p><p><b>A virtual machine</b> (VM) <i>is a software implementation of a machine (i.e. a computer) that executes programs like a physical machine</i>. Originally, Java was designed to run based on a virtual machine separated from a physical machine for implementing <b>WORA</b> (<i>Write Once Run Anywhere</i>), although this goal has been mostly forgotten. Therefore, the JVM runs on all kinds of hardware to execute the <b>Java Bytecode</b> without changing the Java execution code.</p><p>The features of JVM are as follows:</p><p></p><ul><li><b>Stack-based virtual machine</b>: The most popular computer architectures such as Intel x86 Architecture and ARM Architecture run based on a&nbsp;<i>register</i>. However, <i>JVM runs based on a stack</i>.</li><li><b>Symbolic reference</b>: All types (class and interface) except for primitive data types are referred to through symbolic reference, instead of through explicit memory address-based reference.&nbsp;</li><li><b>Garbage collection</b>: A class instance is explicitly created by the user code and automatically destroyed by garbage collection.</li><li><b>Guarantees platform independence by clearly defining the primitive data type</b>: A traditional language such as C/C++ has different int type size according to the platform. The JVM clearly defines the primitive data type to maintain its compatibility and guarantee platform independence.</li><li><b>Network byte order</b>: The Java class file uses the network byte order. To maintain platform independence between the little endian used by Intel x86 Architecture and the big endian used by the RISC Series Architecture, a fixed byte order must be kept. Therefore, JVM uses the network byte order, which is used for network transfer. The network byte order is the big endian.</li></ul><p></p><p>Sun Microsystems developed Java. However, any vendor can develop and provide a JVM by following the Java Virtual Machine Specification. For this reason, there are various JVMs, including Oracle Hotspot JVM and IBM JVM. The Dalvik VM in Google's Android operating system is a kind of JVM, though it does not follow the Java Virtual Machine Specification. Unlike Java VMs, which are stack machines, the Dalvik VM is a register-based architecture. Java bytecode is also converted into an register-based instruction set used by the Dalvik VM.</p><h2>Java bytecode</h2><p>To implement WORA, the JVM uses Java bytecode, a middle-language between Java (user language) and the machine language. This Java bytecode is the smallest unit that deploys the Java code.</p><p>Before explaining the Java bytecode, let's take a look at it. This case is a summary of a real example that has occurred in development process.</p><h3>Symptom</h3><p>An application that had been running successfully no longer runs. Moreover, returns the following error after the library has been updated.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>Exception in thread "main" java.lang.NoSuchMethodError: com.nhn.user.UserAdmin.addUser(Ljava/lang/String;)V<br />&nbsp; &nbsp; at com.nhn.service.UserService.add(UserService.java:14)<br />&nbsp; &nbsp; at com.nhn.service.UserService.main(UserService.java:19)</p></div><p></p><p></p><p>The application code is as follows, and no changes to it have been made.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>// UserService.java<br />…<br />public void add(String userName) {<br />&nbsp; &nbsp; admin.addUser(userName);<br />}</p></div><p></p><p></p><p>The updated library source code and the original source code are as follows.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>// UserAdmin.java - Updated library source code<br />…<br />public User addUser(String userName) {<br />&nbsp; &nbsp; User user = new User(userName);<br />&nbsp; &nbsp; User prevUser = userMap.put(userName, user);<br />&nbsp; &nbsp; return prevUser;<br />}<br />// UserAdmin.java - Original library source code<br />…<br />public void addUser(String userName) {<br />&nbsp; &nbsp; User user = new User(userName);<br />&nbsp; &nbsp; userMap.put(userName, user);<br />}</p></div><p></p><p>In short, the addUser() method which has no return value has been changed to a method that returns the User class instance. However, the application code has not been changed, since it does not use the return value of the addUser() method.</p><blockquote class="q1"><p>At first glance, the com.nhn.user.UserAdmin.addUser() method seems to still exist, but if so, <b>why does NoSuchMethodError occur?</b></p></blockquote><h3>Reasons</h3><p>The reason is that the application code has not been compiled to a new library. In other words, the application code seems to invoke methods regardless of the return value. However, the compiled class file indicates the method that has a return value.</p><p>You will see this through the following error message.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;">java.lang.NoSuchMethodError: com.nhn.user.UserAdmin.addUser(Ljava/lang/String;)V</div><p></p><p><i>NoSuchMethodError</i> has occurred since the "<i>com.nhn.user.UserAdmin.addUser(Ljava/lang/String;)V</i>" method could not be found. Take a look at "Ljava/lang/String;" and the last "V". In the expression of Java Bytecode, <i>"L&lt;classname&gt;;" </i>is the class instance. This means that the addUser() method returns one java/lang/String object as a parameter. In the library of this case, the parameter has not been changed, so it is normal. The last <i>"V"</i> of the message stands for the return value of the method. In the expression of Java Bytecode, "V" means that it has no return value. In short, the error message means that one java.lang.String object has been returned as a parameter and the com.nhn.user.UserAdmin.addUser method without any return value has not been found.</p><p>Since the application code has been compiled to the previous library, the class file defined that a method that returns "V" should be invoked. However, in the changed library, the method that returned "V" did not exist, but the method that returned "Lcom/nhn/user/User;" has been added. Therefore, a NoSuchMethodError occurred.</p><blockquote class="q4"><p><b>Note</b></p><p>The error has occurred since the developer did not compile a new library again. However, in this case, the library provider is mostly responsible for that. There was no return value of the method as public, but it later has been changed to return the user class instance. This is an obvious method signature change. This means that the backward compatibility of the library has been broken. Therefore, the library provider must have reported to the users that the method has been changed.</p></blockquote><p>Let's go back to the Java Bytecode. <b>Java Bytecode</b> is the essential element of JVM. The JVM is an emulator that emulates the Java Bytecode. Java compiler does not directly convert high-level language such as C/C++ to the machine language (direct CPU instruction); it converts the Java language that the developer understands to the Java Bytecode that the JVM understands. Since Java bytecode has no platform-dependent code, it is executable on the hardware where the JVM (accurately, the JRE of the same profile) has been installed, even when the CPU or OS is different (a class file developed and compiled on the Windows PC can be executed on the Linux machine without additional change.) The size of the compiled code is almost identical to the size of the source code, making it easy to transfer and execute the compiled code via &nbsp;the network.</p><p>The class file itself is a binary file that cannot be understood by a human. To manage this file, JVM vendors provide <b>javap</b>, the disassembler. The result of using javap is called Java assembly. In the above case, the Java assembly below is obtained by disassembling the UserService.add() method of the application code with the javap -c option.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>public void add(java.lang.String);<br />&nbsp; Code:<br />&nbsp; &nbsp;0: &nbsp; aload_0<br />&nbsp; &nbsp;1: &nbsp; getfield &nbsp; &nbsp; &nbsp; &nbsp;#15; //Field admin:Lcom/nhn/user/UserAdmin;<br />&nbsp; &nbsp;4: &nbsp; aload_1<br />&nbsp; &nbsp;5: &nbsp; invokevirtual &nbsp; #23; //Method com/nhn/user/UserAdmin.addUser:(Ljava/lang/String;)V<br />&nbsp; &nbsp;8: &nbsp; return</p></div><p></p><p>In this Java assembly, the addUser() method is invoked by the fourth row, "5: invokevirtual #23;". This means that the method corresponding to the 23rd index should be invoked. The method of the 23rd index is annotated by the javap program. The <b>invokevirtual</b> is the OpCode (operation code) of the most basic command that invokes a method in the Java Bytecode. For reference, there are four OpCodes that invoke a method in the Java Bytecode: <i>invokeinterface, invokespecial, invokestatic</i>, and <i>invokevirtual</i>. The meaning of each OpCode is as follows.</p><p></p><ul><li><b>invokeinterface</b>: Invokes an interface method</li><li><b>invokespecial</b>: Invokes an initializer, private method, or superclass method</li><li><b>invokestatic</b>: Invokes static methods</li><li><b>invokevirtual</b>: Invokes instance methods</li></ul><p></p><p>The instruction set of Java Bytecode consists of OpCode and Operand. The OpCode such as invokevirtual requires a 2-byte Operand.</p><p>By compiling the application code above with the updated library and then disassembling it, the following result will be obtained.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>public void add(java.lang.String);<br />&nbsp; Code:<br />&nbsp; &nbsp;0: &nbsp; aload_0<br />&nbsp; &nbsp;1: &nbsp; getfield &nbsp; &nbsp; &nbsp; &nbsp;#15; //Field admin:Lcom/nhn/user/UserAdmin;<br />&nbsp; &nbsp;4: &nbsp; aload_1<br />&nbsp; &nbsp;5: &nbsp; invokevirtual &nbsp; #23; //Method com/nhn/user/UserAdmin.addUser:(Ljava/lang/String;)Lcom/nhn/user/User;<br />&nbsp; &nbsp;8: &nbsp; pop<br />&nbsp; &nbsp;9: &nbsp; return</p></div><p></p><p></p><p>You can see that the method corresponding to the 23rd has been converted to the method that returns "Lcom/nhn/user/User;".</p><blockquote class="q2"><p><b>In the disassembled result above, what does the number in front of the code mean?</b></p></blockquote><p>It is the byte number. Perhaps this is the reason why the code executed by the JVM is called Java "Byte"code. In short, the bytecode instruction OpCodes such as <i>aload_0</i>, <i>getfield</i>, and <i>invokevirtual</i> are expressed as a 1-byte byte number. (aload_0 = 0x2a, getfield = 0xb4, invokevirtual = 0xb6) Therefore, the maximum number of Java Bytecode instruction OpCodes is 256.</p><p>OpCodes such as aload_0 and aload_1 do not need any Operand. Therefore, the next byte of aload_0 is the OpCode of the next instruction. However, getfield and invokevirtual need the 2-byte Operand. Therefore, the next instruction of getfield on the first byte is written on the fourth byte by skipping two bytes. The bytecode shown through Hex Editor is as follows.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;">2a b4 00 0f 2b b6 00 17 57 b1</div><p></p><p>In the Java Bytecode, the class instance is expressed as "L;" and void is expressed as "V". In this way, other types have their own expressions. The table below summarizes the expressions.</p>

<h4>Table 1: Type Expression in Java Bytecode</h4>

<table>
<thead>
<tr>
	<td>Java Bytecode</td>
	<td>Type</td>
	<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
	<td>B</td>
	<td>byte</td>
	<td>signed byte</td>
</tr>
<tr>
	<td>C</td>
	<td>char</td>
	<td>Unicode character</td>
</tr>
<tr>
	<td>D</td>
	<td>double</td>
	<td>double-precision floating-point value</td>
</tr>
<tr>
	<td>F</td>
	<td>float</td>
	<td>single-precision floating-point value</td>
</tr>
<tr>
	<td>I</td>
	<td>int</td>
	<td>integer</td>
</tr>
<tr>
	<td>J</td>
	<td>long</td>
	<td>long integer</td>
</tr>
<tr>
	<td>L&lt;classname&gt;</td>
	<td>reference</td>
	<td>an instance of class &lt;classname&gt;</td>
</tr>
<tr>
	<td>S</td>
	<td>short</td>
	<td>signed short</td>
</tr>
<tr>
	<td>Z</td>
	<td>boolean</td>
	<td>true or false</td>
</tr>
<tr>
	<td>[</td>
	<td>reference</td>
	<td>one array dimension</td>
</tr>
</tbody>
</table>

<p>The table below shows examples of Java Bytecode expressions.</p>


<h4>Table 2: Examples of Java Bytecode Expressions</h4>

<table>
<thead>
<tr>
	<td>Java Code</td>
	<td>Java Bytecode Expression</td>
</tr>
</thead>
<tbody>
<tr>
	<td>double d[][][];</td>
	<td>[[[D</td>
</tr>
<tr>
	<td>Object mymethod(int I, double d, Thread t)</td>
	<td>(IDLjava/lang/Thread;)Ljava/lang/Object;</td>
</tr>
</tbody>
</table>

<p>For more details, see "4.3 Descriptors" in "<i>The Java Virtual Machine Specification, Second Edition</i>". For various Java Bytecode instruction sets, see "6. The Java Virtual Machine Instruction Set" in "The Java Virtual Machine Specification, Second Edition".</p><h2>Class File Format</h2><p>Before explaining the Java class file format, let's review an example that frequently occurs in Java Web applications.</p><h3>Symptom</h3><p>When writing and executing JSP on Tomcat, the JSP did not run, and the following error occurred.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>Servlet.service() for servlet jsp threw exception org.apache.jasper.JasperException: Unable to compile class for JSP Generated servlet error:<br />The code of method _jspService(HttpServletRequest, HttpServletResponse) is exceeding the 65535 bytes limit"</p></div><p></p><p></p><h3>Reasons</h3><p>The error message above varies slightly depending on the Web application server, however, one thing is the same; it is because of the 65535 byte limit. The 65535 byte limit is one of the JVM limitations, and stipulates that the <b>size of one method cannot be more than 65535 bytes</b>.</p><p>I will present the meaning of the 65535 byte limit and why it has been set in more detailed manner.</p><p>The branch/jump instructions used in the Java Bytecode are "goto" and "jsr".</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>goto [branchbyte1] [branchbyte2]<br />jsr [branchbyte1] [branchbyte2]</p></div><p></p><p></p><p>Both of the two receive 2-byte signed branch offset as their Operand so that they can be expanded to the 65535th index at a maximum. However, to support more sufficient branch, Java Bytecode prepares "goto_w" and "jsr_w" that receive 4-byte signed branch offset.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;">goto_w [branchbyte1] [branchbyte2] [branchbyte3] [branchbyte4]<br />jsr_w [branchbyte1] [branchbyte2] [branchbyte3] [branchbyte4]</div><p></p><p>With the two, branch is available with an index exceeding 65535. Therefore, the 65535 byte limit of Java method may be overcome. However, due to various other limits of the Java class file format, the Java method still cannot exceed 65535 bytes. To view other limits, I will simply explain the class file format.</p><p>The outline of a Java class file is as follows:&nbsp;</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>ClassFile {<br />&nbsp; &nbsp; u4 magic;<br />&nbsp; &nbsp; u2 minor_version;<br />&nbsp; &nbsp; u2 major_version;<br />&nbsp; &nbsp; u2 constant_pool_count;<br />&nbsp; &nbsp; cp_info constant_pool[constant_pool_count-1];<br />&nbsp; &nbsp; u2 access_flags;<br />&nbsp; &nbsp; u2 this_class;<br />&nbsp; &nbsp; u2 super_class;<br />&nbsp; &nbsp; u2 interfaces_count;<br />&nbsp; &nbsp; u2 interfaces[interfaces_count];<br />&nbsp; &nbsp; u2 fields_count;<br />&nbsp; &nbsp; field_info fields[fields_count];<br />&nbsp; &nbsp; u2 methods_count;<br />&nbsp; &nbsp; method_info methods[methods_count];<br />&nbsp; &nbsp; u2 attributes_count;<br />&nbsp; &nbsp; attribute_info attributes[attributes_count];</p><p>}</p></div><p></p><p></p><p>The above is included in "4.1. The ClassFile Structure" of "The Java Virtual Machine Specification, Second Edition".</p><p>The first 16 bytes of the UserService.class file disassembled earlier are shown as follows in the Hex Editor.</p><p>ca fe ba be 00 00 00 32 00 28 07 00 02 01 00 1b</p><p>With this value, see the class file format.</p><p></p><ul><li><b>magic</b>: The first 4 bytes of the class file are the magic number. This is a pre-specified value to distinguish the Java class file. As shown in the Hex Editor above, the value is always 0xCAFEBABE. In short, when the first 4 bytes of a file is 0xCAFEBABE, it can be regarded as the Java class file. This is a kind of "witty" magic number related to the name "Java".</li><li><b>minor_version, major_version</b>: The next 4 bytes indicate the class version. As the UserService.class file is 0x00000032, the class version is 50.0. The version of a class file compiled by JDK 1.6 is 50.0, and the version of a class file compiled by JDK 1.5 is 49.0. The JVM must maintain backward compatibility with class files compiled in a lower version than itself. On the other hand, when a upper-version class file is executed in the lower-version JVM, java.lang.UnsupportedClassVersionError occurs.</li><li><b>constant_pool_count, constant_pool[]</b>: Next to the version, the class-type constant pool information is described. This is the information included in the Runtime Constant Pool area, which will be explained later. While loading the class file, the JVM includes the constant_pool information in the Runtime Constant Pool area of the method area. As the constant_pool_count of the UserService.class file is 0x0028, you can see that the constant_pool has (40-1) indexes, 39 indexes.</li><li><b>access_flags</b>: This is the flag that shows the modifier information of a class; in other words, it shows public, final, abstract or whether or not to interface.</li><li><b>this_class, super_class</b>: The index in the constant_pool for the class corresponding to this and super, respectively.</li><li><b>interfaces_count, interfaces[]</b>: The index in the the constant_pool for the number of interfaces implemented by the class and each interface.</li><li><b>fields_count, fields[]</b>: The number of fields and the field information of the class. The field information includes the field name, type information, modifier, and index in the constant_pool.</li><li><b>methods_count, methods[]</b>: The number of methods in a class and the methods information of the class. The methods information includes the methods name, type and number of the parameters, return type, modifier, index in the constant_pool, execution code of the method, and exception information.</li><li><b>attributes_count, attributes[]</b>: The attribute_info structure has various attributes. For field_info or method_info, attribute_info is used.</li></ul><p></p><p>The javap program briefly shows the class file format in a format that users can read. When UserService.class is analyzed using the "javap -verbose" option, the following contents are printed.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>Compiled from "UserService.java"<br /><br />public class com.nhn.service.UserService extends java.lang.Object<br />&nbsp; SourceFile: "UserService.java"<br />&nbsp; minor version: 0<br />&nbsp; major version: 50<br />&nbsp; Constant pool:</p><p>const #1 = class &nbsp; &nbsp; &nbsp; &nbsp;#2; &nbsp; &nbsp; // &nbsp;com/nhn/service/UserService<br />const #2 = Asciz &nbsp; &nbsp; &nbsp; &nbsp;com/nhn/service/UserService;<br />const #3 = class &nbsp; &nbsp; &nbsp; &nbsp;#4; &nbsp; &nbsp; // &nbsp;java/lang/Object<br />const #4 = Asciz &nbsp; &nbsp; &nbsp; &nbsp;java/lang/Object;<br />const #5 = Asciz &nbsp; &nbsp; &nbsp; &nbsp;admin;<br />const #6 = Asciz &nbsp; &nbsp; &nbsp; &nbsp;Lcom/nhn/user/UserAdmin;;</p><p>// … omitted - constant pool continued …<br /><br />{<br />// … omitted - method information …<br /><br />public void add(java.lang.String);<br />&nbsp; Code:<br />&nbsp; &nbsp;Stack=2, Locals=2, Args_size=2<br />&nbsp; &nbsp;0: &nbsp; aload_0<br />&nbsp; &nbsp;1: &nbsp; getfield &nbsp; &nbsp; &nbsp; &nbsp;#15; //Field admin:Lcom/nhn/user/UserAdmin;<br />&nbsp; &nbsp;4: &nbsp; aload_1<br />&nbsp; &nbsp;5: &nbsp; invokevirtual &nbsp; #23; //Method com/nhn/user/UserAdmin.addUser:(Ljava/lang/String;)Lcom/nhn/user/User;<br />&nbsp; &nbsp;8: &nbsp; pop<br />&nbsp; &nbsp;9: &nbsp; return</p><p>&nbsp; LineNumberTable:<br />&nbsp; &nbsp;line 14: 0<br />&nbsp; &nbsp;line 15: 9</p><p>&nbsp; LocalVariableTable:<br />&nbsp; &nbsp;Start &nbsp;Length &nbsp;Slot &nbsp;Name &nbsp; Signature<br />&nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp;10 &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp;this &nbsp; &nbsp; &nbsp; Lcom/nhn/service/UserService;<br />&nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp;10 &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp;userName &nbsp; &nbsp; &nbsp; Ljava/lang/String;&nbsp;</p><p>// … Omitted - Other method information …<br />}</p></div><p></p><p></p><p>Due to a lack of space, I have extracted some parts from the entire printout. The entire printout shows you the various information included in the constant pool and the contents of each method.</p><p>The 65535 byte limit of method size is related to the contents of <b>method_info struct</b>. The method_info struct has Code, LineNumberTable, and LocalVariableTable attribute, as shown in the "javap -verbose" print shown above. All of the values corresponding to the length of LineNumberTable, LocalVariableTable, and exception_table included in the Code attribute are fixed at 2 bytes. Therefore, the method size cannot exceed the length of LineNumberTable, LocalVariableTable, and exception_table, and is limited to 65535 bytes.</p><p>Many people have complaints about the method size limit, and the JVM specifications state that 'it may be expandable later.’ However, no explicit move toward improvement has been made so far. Considering the characteristic of JVM specifications that loads almost same contents in the class file to the method area, it will be significantly difficult to expand the method size while maintining backward compatibility.</p><blockquote class="q2"><p><b>What will happen if an incorrect class file is created because of a Java compiler error? Or, what if due to errors in network transfer or file copy process, a class file can be broken?</b></p></blockquote><p>To prepare for such cases, the Java class loader is verified through a very strict and tight process. The JVM specifications explicitly detail the process.</p><blockquote class="q4"><p><b>Note</b></p><p>How can we verify that the JVM successfully executes the class file verification process? How can we verify that various JVMs from various JVM vendors satisfy the JVM specifications? For verification, Oracle provides a test tool, TCK (Technology Compatibility Kit). The TCK verifies a JVM specification by executing ten thousands of tests, including a many incorrect class files in various ways. After passing the TCK, the JVM can be called a JVM.&nbsp;</p><p>Like TCK, there is JCP (Java Community Process; http://jcp.org), which proposes new Java technical specifications as well as Java specifications. For the JCP, a specification document, reference implementation, and TCK for a proposed JSR (Java Specification Request) must be completed to complete JSR. Users who want to use new Java technology proposed as JSR should license the implementation from the RI provider, or directly implement it and test the implementation with TCK.</p></blockquote><h2>JVM Structure</h2><p>The code written in Java is executed by following the process shown in the figure below.&nbsp;</p><p style="text-align: center;">&nbsp;<img src="/files/attach/images/220547/468/290/java-code-execution-process.png" alt="java-code-execution-process.png" width="353" height="383" editor_component="image_link" />
</p><p style="text-align: center;"><b>Figure 1: Java Code Execution Process.</b></p><p>A class loader loads the compiled Java Bytecode to the Runtime Data Areas, and the execution engine executes the Java Bytecode.</p><h3>Class Loader</h3><p>Java provides a dynamic load feature; it loads and links the class when it refers to a class for the first time at runtime, not compile time. JVM's class loader executes the dynamic load. The features of Java class loader are as follows:</p><p></p><ul><li><b>Hierarchical Structure</b>: Class loaders in Java are organized into a hierarchy with a parent-child relationship. The Bootstrap Class Loader is the parent of all class loaders.</li><li><b>Delegation mode</b>: Based on the hierarchical structure, load is delegated between class loaders. When a class is loaded, the parent class loader is checked to determine whether or not the class is in the parent class loader. If the upper class loader has the class, the class is used. If not, the class loader requested for loading loads the class.</li><li><b>Visibility limit</b>: A child class loader can find the class in the parent class loader; however, a parent class loader can find the class in the child class loader.</li><li><b>Unload is not allowed</b>: A class loader can load a class but cannot unload it. Instead of unloading, the current class loader can be deleted, and a new class loader can be created.</li></ul><p></p><p>Each class loader has its namespace that stores the loaded classes. When a class loader loads a class, it searches the class based on FQCN (Fully Qualified Class Name) stored in the namespace to check whether or not the class has been already loaded. Even if the class has an identical FQCN but a different namespace, it is regarded as a different class. A different namespace means that the class has been loaded by another class loader.</p><p>The following figure illustrates the class loader delegation model.</p><p style="text-align: center;">&nbsp;<img src="/files/attach/images/220547/468/290/class-loader-delegation-model.png" alt="class-loader-delegation-model.png" width="409" height="455" editor_component="image_link" />
</p><p style="text-align: center;"><b>Figure 2: Class Loader Delegation Model.</b></p><p>When a class loader is requested for class load, it checks whether or not the class exists in the class loader cache, the parent class loader, and itself, in the order listed. In short, it checks whether or not the class has been loaded in the class loader cache. If not, it checks the parent class loader. If the class is not found in the bootstrap class loader, the requested class loader searches for the class in the file system.</p><p></p><ul><li><b>Bootstrap class loader</b>: This is created when running the JVM. It loads Java APIs, including object classes. Unlike other class loaders, it is implemented in native code instead of Java.</li><li><b>Extension class loader</b>: It loads the extension classes excluding the basic Java APIs. It also loads various security extension functions.</li><li><b>System class loader</b>: If the bootstrap class loader and the extension class loader load the JVM components, the system class loader loads the application classes. It loads the class in the $CLASSPATH specified by the user.</li><li><b>User-defined class loader</b>: This is a class loader that an application user directly creates on the code.</li></ul><p></p><p>Frameworks such as Web application server (WAS) use it to make Web applications and enterprise applications run independently. In other words, this guarantees the independence of applications through class loader delegation model. Such a WAS class loader structure uses a hierarchical structure that is slightly different for each WAS vendor.</p><p>If a class loader finds an unloaded class, the class is loaded and linked by following the process illustrated below.</p><p style="text-align: center;">&nbsp;<img src="/files/attach/images/220547/468/290/class-load-stage.png" alt="class-load-stage.png" width="701" height="340" editor_component="image_link" />
</p><p style="text-align: center;"><b>Figure 3: Class Load Stage.</b></p><p>Each stage is described as follows.</p><p></p><ul><li><b>Loading</b>: A class is obtained from a file and loaded to the JVM memory.</li><li><b>Verifying</b>: Check whether or not the read class is configured as described in the Java Language Specification and JVM specifications. This is the most complicated test process of the class load processes, and takes the longest time. Most cases of the JVM TCK test cases are to test whether or not a verification error occurs by loading wrong classes.</li><li><b>Preparing</b>: Prepare a data structure that assigns the memory required by classes and indicates the fields, methods, and interfaces defined in the class.</li><li><b>Resolving</b>: Change all symbolic references in the constant pool of the class to direct references.</li><li><b>Initializing</b>: Initialize the class variables to proper values. Execute the static initializers and initialize the static fields to the configured values.</li></ul><p></p><p>The JVM specification defines the tasks. However, it allows flexible application of the execution time.</p><h3>Runtime Data Areas</h3><p style="text-align: center;">&nbsp;<img src="/files/attach/images/220547/468/290/runtime-data-access-configuration.png" alt="runtime-data-access-configuration.png" width="365" height="423" editor_component="image_link" />
</p><p style="text-align: center;"><b>Figure 4: Runtime Data Areas Configuration.</b></p><p>Runtime Data Areas are the memory areas assigned when the JVM program runs on the OS. The runtime data areas can be divided into 6 areas. Of the six, one PC Register, JVM Stack, and Native Method Stack are created for one thread. Heap, Method Area, and Runtime Constant Pool are shared by all threads.</p><p></p><ul><li><b>PC register</b>: One PC (Program Counter) register exists for one thread, and is created when the thread starts. PC register has the address of a JVM instruction being executed now.</li><li><b>JVM stack</b>: One JVM stack exists for one thread, and is created when the thread starts. It is a stack that saves the struct (Stack Frame). The JVM just pushes or pops the stack frame to the JVM stack. If any exception occurs, each line of the stack trace shown as a method such as printStackTrace() expresses one stack frame.</li></ul><p></p><p style="text-align: center;">&nbsp;<img src="/files/attach/images/220547/468/290/jvm-stack-configuration.png" alt="jvm-stack-configuration.png" width="377" height="272" editor_component="image_link" />
</p><p style="text-align: center;"><b>Figure 5: JVM Stack Configuration.</b></p><p>−<span class="Apple-tab-span" style="white-space:pre">	</span>Stack frame: One stack frame is created whenever a method is executed in the JVM, and the stack frame is added to the JVM stack of the thread. When the method is ended, the stack frame is removed. Each stack frame has the reference for local variable array, Operand stack, and runtime constant pool of a class where the method being executed belongs. The size of local variable array and Operand stack is determined while compiling. Therefore, the size of stack frame is fixed according to the method.</p><p>−<span class="Apple-tab-span" style="white-space:pre">	</span>Local variable array: It has an index starting from 0. 0 is the reference of a class instance where the method belongs. From 1, the parameters sent to the method are saved. After the method parameters, the local variables of the method are saved.</p><p>−<span class="Apple-tab-span" style="white-space:pre">	</span>Operand stack: An actual workspace of a method. Each method exchanges data between the Operand stack and the local variable array, and pushes or pops other method invoke results. The necessary size of the Operand stack space can be determined during compiling. Therefore, the size of the Operand stack can also be determined during compiling.</p><p></p><ul><li><b>Native method stack</b>: A stack for native code written in a language other than Java. In other words, it is a stack used to execute C/C++ codes invoked through JNI (Java Native Interface). According to the language, a C stack or C++ stack is created.</li><li><b>Method area</b>: The method area is shared by all threads, created when the JVM starts. It stores runtime constant pool, field and method information, static variable, and method bytecode for each of the classes and interfaces read by the JVM. The method area can be implemented in various formats by JVM vendor. Oracle Hotspot JVM calls it Permanent Area or Permanent Generation (PermGen). The garbage collection for the method area is optional for each JVM vendor.</li><li><b>Runtime constant pool</b>: An area that corresponds to the constant_pool table in the class file format. This area is included in the method area; however, it plays the most core role in JVM operation. Therefore, the JVM specification separately describes its importance. As well as the constant of each class and interface, it contains all references for methods and fields. In short, when a method or field is referred to, the JVM searches the actual address of the method or field on the memory by using the runtime constant pool.</li><li><b>Heap</b>: A space that stores instances or objects, and is a target of garbage collection. This space is most frequently mentioned when discussing issues such as JVM performance. JVM vendors can determine how to configure the heap or not to collect garbage.</li></ul><p></p><p>Let's go back to the disassembled bytecode we discussed previously.&nbsp;</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>public void add(java.lang.String);<br />&nbsp; Code:<br />&nbsp; &nbsp;0: &nbsp; aload_0<br />&nbsp; &nbsp;1: &nbsp; getfield &nbsp; &nbsp; &nbsp; &nbsp;#15; //Field admin:Lcom/nhn/user/UserAdmin;<br />&nbsp; &nbsp;4: &nbsp; aload_1<br />&nbsp; &nbsp;5: &nbsp; invokevirtual &nbsp; #23; //Method com/nhn/user/UserAdmin.addUser:(Ljava/lang/String;)Lcom/nhn/user/User;<br />&nbsp; &nbsp;8: &nbsp; pop<br />&nbsp; &nbsp;9: &nbsp; return</p></div><p></p><p></p><p>Comparing the disassembled code and the assembly code of the x86 architecture that we sometimes see, the two have a similar format, OpCode; however, there is a difference in that Java Bytecode does not write register name, memory addressor, or offset on the Operand. As described before, the JVM uses stack. Therefore, it does not use register, unlike the x86 architecture that uses registers, and it uses index numbers such as 15 and 23 instead of memory addresses since it manages the memory by itself. The 15 and 23 are the indexes of the constant pool of the current class (here, UserService class). In short, the JVM creates a constant pool for each class, and the pool stores the reference of the actual target.</p><p>Each row of the disassembled code is interpreted as follows.</p><p></p><ul><li><b>aload_0</b>: Add the #0 index of the local variable array to the Operand stack. The #0 index of the local variable array is always this, the reference for the current class instance.</li><li><b>getfield #15</b>: In the current class constant pool, add the #15 index to the Operand stack. UserAdmin admin field is added. Since the admin field is a class instance, a reference is added.</li><li><b>aload_1</b>: Add the #1 index of the local variable array to the Operand stack. From the #1 index of the local variable array, it is a method parameter. Therefore, the reference of String userName sent while invoking add() is added.</li><li><b>invokevirtual #23</b>: Invoke the method corresponding to the #23 index in the current class constant pool. At this time, the reference added by using getfield and the parameter added by using aload_1 are sent to the method to invoke. When the method invocation is completed, add the return value to the Operand stack.</li><li><b>pop</b>: Pop the return value of invoking by using invokevirtual from the Operand stack. You can see that the code compiled by the previous library has no return value. In short, the previous has no return value, so there was no need to pop the return value from the stack.</li><li><b>return</b>: Complete the method.</li></ul><p></p><p>The following figure will help you understand the explanation.</p><p style="text-align: center;"><img src="/files/attach/images/220547/468/290/example-of-java-bytecode-loaded-on-runtime-data-areas.png" alt="example-of-java-bytecode-loaded-on-runtime-data-areas.png" width="401" height="520" editor_component="image_link" /><br /></p><p style="text-align: center;"><b>Figure 6: Example of Java Bytecode Loaded on Runtime Data Areas.</b></p><p>For reference, in this method, no local variable array has been changed. So the figure above displays the changes in Operand stack only. However, in most cases, local variable array is also changed. Data transfer between the local variable array and the Operand stack is made by using a lot of load instructions (aload, iload) and store instructions (astore, istore).&nbsp;</p><p>In this figure, we have checked the brief description of the runtime constant pool and the JVM stack. When the JVM runs, each class instance will be assigned to the heap, and class information including User, UserAdmin, UserService, and String will be stored in the method area.</p><h3>Execution Engine</h3><p>The bytecode that is assigned to the runtime data areas in the JVM via class loader is executed by the execution engine. The execution engine reads the Java Bytecode in the unit of instruction. It is like a CPU executing the machine command one by one. Each command of the bytecode consists of a 1-byte OpCode and additional Operand. The execution engine gets one OpCode and execute task with the Operand, and then executes the next OpCode.</p><p>But the Java Bytecode is written in a language that a human can understand, rather than in the language that the machine directly executes. Therefore, the execution engine must change the bytecode to the language that can be executed by the machine in the JVM. The bytecode can be changed to the suitable language in one of two ways.</p><p></p><ul><li><b>Interpreter</b>: Reads, interprets and executes the bytecode instructions one by one. As it interprets and executes instructions one by one, it can quickly interpret one bytecode, but slowly executes the interpreted result. This is the disadvantage of the interpret language. The 'language' called Bytecode basically runs like an interpreter.</li><li><b>JIT (Just-In-Time) compiler</b>: The JIT compiler has been introduced to compensate for the disadvantages of the interpreter. The execution engine runs as an interpreter first, and at the appropriate time, the JIT compiler compiles the entire bytecode to change it to native code. After that, the execution engine no longer interprets the method, but directly executes using native code. Execution in native code is much faster than interpreting instructions one by one. The compiled code can be executed quickly since the native code is stored in the cache.&nbsp;</li></ul><p></p><p>However, it takes more time for JIT compiler to compile the code than for the interpreter to interpret the code one by one. Therefore, if the code is to be executed just once, it is better to interpret it instead of compiling. Therefore, the JVMs that use the JIT compiler internally check how frequently the method is executed and compile the method only when the frequency is higher than a certain level.</p><p style="text-align: center;">&nbsp;<img src="/files/attach/images/220547/468/290/java-compiler-and-jit-compiler.png" alt="java-compiler-and-jit-compiler.png" width="400" height="173" editor_component="image_link" />
</p><p style="text-align: center;"><b>Figure 7: Java Compiler and JIT Compiler.</b></p><p>How the execution engine runs is not defined in the JVM specifications. Therefore, JVM vendors improve their execution engines using various techniques, and introduce various types of JIT compilers.&nbsp;</p><p>Most JIT compilers run as shown in the figure below:&nbsp;</p><p style="text-align: center;">&nbsp;<img src="/files/attach/images/220547/468/290/jit-compiler.png" alt="jit-compiler.png" width="400" height="233" editor_component="image_link" />
</p><p style="text-align: center;"><b>Figure 8: JIT Compiler.</b></p><p>The JIT compiler converts the bytecode to an intermediate-level expression, IR (Intermediate Representation), to execute optimization, and then converts the expression to native code.</p><p>Oracle Hotspot VM uses a JIT compiler called Hotspot Compiler. It is called Hotspot because Hotspot Compiler searches the 'Hotspot' that requires compiling with the highest priority through profiling, and then it compiles the hotspot to native code. If the method that has the bytecode compiled is no longer frequently invoked, in other words, if the method is not the hotspot any more, the Hotspot VM removes the native code from the cache and runs in interpreter mode. The Hotspot VM is divided into the Server VM and the Client VM, and the two VMs use different JIT compilers.</p><p style="text-align: center;"><img src="/files/attach/images/220547/468/290/hotspot-client-vm-and-server-vm.png" alt="hotspot-client-vm-and-server-vm.png" width="400" height="180" editor_component="image_link" />&nbsp;</p><p style="text-align: center;"><b>Figure 9: Hotspot Client VM and Server VM.</b></p><p>The client VM and the server VM use an identical runtime; however, they use different JIT compilers, as shown in the above figure. The client VM and the server VM use an identical runtime, however, they use different JIT compilers as shown in the above figure. Advanced Dynamic Optimizing Compiler used by the server VM uses more complex and diverse performance optimization techniques.</p><p>IBM JVM has introduced AOT (Ahead-Of-Time) Compiler from IBM JDK 6 as well as the JIT compiler. This means that many JVMs share the native code compiled through the shared cache. In short, the code that has been already compiled through the AOT compiler can be used by another JVM without compiling. In addition, IBM JVM provides a fast way of execution by pre-compiling code to JXE (Java EXecutable) file format using the AOT compiler.</p><p>Most Java performance improvement is accomplished by improving the execution engine. As well as the JIT compiler, various optimization techniques are being introduced so the JVM performance can be continuously improved. The biggest difference between the initial JVM and the latest JVM is the execution engine.</p><p>Hotspot compiler has been introduced to Oracle Hotspot VM from version 1.3, and JIT compiler has been introduced to Dalvik VM from Android 2.2.</p><blockquote class="q4"><p><b>Note</b></p><p>The technique in which an intermediate language such as bytecode is introduced, the VM executes the bytecode, and the JIT compiler improves the performance of JVM is also commonly used in other languages that have introduced intermediate languages. For Microsoft's .Net, CLR (Common Language Runtime), a kind of VM, executes a kind of bytecode, called CIL (Common Intermediate Language). CLR provides the AOT compiler as well as the JIT compiler. Therefore, if source code is written in C# or VB.NET and compiled, the compiler creates CIL and the CIL is executed on the CLR with the JIT compiler. The CLR uses the garbage collection and runs as a stack machine like the JVM.</p></blockquote><h2>The Java Virtual Machine Specification, Java SE 7 Edition</h2><p>On 28th July, 2011, Oracle released Java SE 7 and updated the JVM specifications to Java SE 7 version. After releasing "The Java Virtual Machine Specification, Second Edition" in 1999, it took 12 years for Oracle to release the updated version. The updated version includes various changes and modifications accumulated over 12 years, and describes more clear specifications. In addition, it reflects the contents included in "The Java Language Specification, Java SE 7 Edition" released with Java SE 7. The major changes can be summarized as follows:</p><p></p><ul><li>Generics introduced from Java SE 5.0, supporting variable argument method</li><li>Bytecode verification process technique changed since Java SE 6</li><li>Added invokedynamic instruction and related class file formats for supporting dynamic type languages</li><li>Deleted the description of the concept of the Java language itself and referred reader to the Java language specifications</li><li>Deleted the description on Java Thread and Lock, and transferred these to the Java language specifications</li></ul><p></p><p>The biggest change of these is the addition of invokedynamic instruction. This means that a change was made in the JVM internal instruction sets, as the JVM started to support dynamic type languages of which type is not fixed, such as script languages, as well as Java language from Java SE 7. The OpCode 186 which had not been used previously has been assigned to the new instruction, invokedynamic, and new contents have been added to the class file format to support the invokedynamic.</p><p>The version of the class file created by the Java compiler of Java SE 7 is 51.0. The version of Java SE 6 is 50.0. Much of the class file format has been changed. Therefore, class files with version 51.0 cannot be executed in the Java SE 6 JVM.&nbsp;</p><p>Despite these various changes, the 65535 byte limit of the Java method has not been removed. Unless the JVM class file format is innovatively changed, it may not be removed in the future.</p><p>For reference, Oracle Java SE 7 VM supports G1, the new garbage collection; however, it is limited to the Oracle JVM, so JVM itself does not limit any garbage collection type. Therefore, the JVM specifications do not describe that.</p><h3>String in switch Statements</h3><p>Java SE 7 adds various grammars and features. However, compared to the various changes in language of Java SE 7, there are not so many changes in the JVM. So, how can the new features of the Java SE 7 be implemented? We will see how String in switch Statements (a function to add a string to a switch() statement as a comparison) has been implemented in Java SE 7 by disassembling it.</p><p>For example, the following code has been written.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>// SwitchTest<br />public class SwitchTest {<br />&nbsp; &nbsp; public int doSwitch(String str) {<br />&nbsp; &nbsp; &nbsp; &nbsp; switch (str) {<br />&nbsp; &nbsp; &nbsp; &nbsp; case "abc": &nbsp; &nbsp; &nbsp; &nbsp;return 1;<br />&nbsp; &nbsp; &nbsp; &nbsp; case "123": &nbsp; &nbsp; &nbsp; &nbsp;return 2;<br />&nbsp; &nbsp; &nbsp; &nbsp; default: &nbsp; &nbsp; &nbsp; &nbsp; return 0;<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />}</p></div><p></p><p></p><p>Since it is a new function of Java SE 7, it cannot be compiled using the Java compiler for Java SE 6 or lower versions. Compile it using the javac of Java SE 7. The following screen is the compiling result printed by using javap –c.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>C:Test&gt;javap -c SwitchTest.class</p><p>Compiled from "SwitchTest.java"<br />public class SwitchTest {<br />&nbsp; public SwitchTest();<br />&nbsp; &nbsp; Code:<br />&nbsp; &nbsp; &nbsp; &nbsp;0: aload_0<br />&nbsp; &nbsp; &nbsp; &nbsp;1: invokespecial #1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Method java/lang/Object."&lt;init&gt;":()V<br />&nbsp; &nbsp; &nbsp; &nbsp;4: return</p><p>&nbsp; public int doSwitch(java.lang.String);<br />&nbsp; &nbsp; Code:<br />&nbsp; &nbsp; &nbsp; &nbsp;0: aload_1<br />&nbsp; &nbsp; &nbsp; &nbsp;1: astore_2<br />&nbsp; &nbsp; &nbsp; &nbsp;2: iconst_m1<br />&nbsp; &nbsp; &nbsp; &nbsp;3: istore_3<br />&nbsp; &nbsp; &nbsp; &nbsp;4: aload_2<br />&nbsp; &nbsp; &nbsp; &nbsp;5: invokevirtual #2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Method java/lang/String.hashCode:()I<br />&nbsp; &nbsp; &nbsp; &nbsp;8: lookupswitch &nbsp;{ // 2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;48690: 50<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;96354: 36<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;default: 61<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; 36: aload_2<br />&nbsp; &nbsp; &nbsp; 37: ldc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// String abc<br />&nbsp; &nbsp; &nbsp; 39: invokevirtual #4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Method java/lang/String.equals:(Ljava/lang/Object;)Z<br />&nbsp; &nbsp; &nbsp; 42: ifeq &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;61<br />&nbsp; &nbsp; &nbsp; 45: iconst_0<br />&nbsp; &nbsp; &nbsp; 46: istore_3<br />&nbsp; &nbsp; &nbsp; 47: goto &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;61<br />&nbsp; &nbsp; &nbsp; 50: aload_2<br />&nbsp; &nbsp; &nbsp; 51: ldc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// String 123<br />&nbsp; &nbsp; &nbsp; 53: invokevirtual #4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Method java/lang/String.equals:(Ljava/lang/Object;)Z<br />&nbsp; &nbsp; &nbsp; 56: ifeq &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;61<br />&nbsp; &nbsp; &nbsp; 59: iconst_1<br />&nbsp; &nbsp; &nbsp; 60: istore_3<br />&nbsp; &nbsp; &nbsp; 61: iload_3<br />&nbsp; &nbsp; &nbsp; 62: lookupswitch &nbsp;{ // 2<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0: 88<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1: 90<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;default: 92<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; 88: iconst_1<br />&nbsp; &nbsp; &nbsp; 89: ireturn<br />&nbsp; &nbsp; &nbsp; 90: iconst_2<br />&nbsp; &nbsp; &nbsp; 91: ireturn<br />&nbsp; &nbsp; &nbsp; 92: iconst_0<br />&nbsp; &nbsp; &nbsp; 93: ireturn</p></div><p></p><p></p><p>A significantly longer bytecode than the Java source code has been created. First, you can see that lookupswitch instruction has been used for switch() statement in Java bytecode. However, two lookupswitch instructions have been used, not the one lookupswitch instruction. When disassembling the case in which int has been added to switch() statement, only one lookupswitch instruction has been used. This means that the switch() statement has been divided into two statements to process the string. See the annotation of the #5, #39, and #53 byte instructions to see how the switch() statement has processed the string.</p><p>In the #5 and #8 byte, first, hashCode() method has been executed and switch(int) has been executed by using the result of executing hashCode() method. In the braces of the lookupswitch instruction, branch is made to the different location according to the hashCode result value. String "abc" is hashCode result value 96354, and is moved to #36 byte. String "123" is hashCode result value 48690, and is moved to #50 byte.</p><p>In the #36, #37, #39, and #42 bytes, you can see that the value of the str variable received as an argument is compared using the String "abc" and the equals() method. If the results are identical, '0' is inserted to the #3 index of the local variable array, and the string is moved to the #61 byte.</p><p>In this way, in the #50, #51, #53, and #56 bytes, you can see that the value of the str variable received as an argument is compared by using the String "123" and the equals() method. If the results are identical, '1' is inserted to the #3 index of the local variable array and the string is moved to the #61 byte.</p><p>In the #61 and #62 bytes, the value of the #3 index of the local variable array, i.e., '0', '1', or any other value, is lookupswitched and branched.</p><p>In other words, in Java code, the value of the str variable received as the switch() argument is compared using the hashCode() method and the equals() method. With the result int value, switch() is executed.</p><p>In this result, the compiled bytecode is not different from the previous JVM specifications. The new feature of Java SE 7, String in switch is processed by the Java compiler, not by the JVM itself. In this way, other new features of Java SE 7 will also be processed by the Java compiler.</p><h2>Conclusion</h2><p>I don't think that we need to review how Java has been developed to use Java well. So many Java developers develop great applications and libraries without understanding JVM deeply. However, if you understand JVM, you will understand Java more, and it will be helpful to solve the problems like the case we have reviewed here.</p><p>Besides the description mentioned here, the JVM has various features and technologies. The JVM specifications provide a flexible specification for JVM vendors to provide more advanced performance so that various technologies can be applied by the vendor. In particular, garbage collection is the technique used by most languages that provides usability similar to that of a VM, the latest and state-of-the-art technique in its performance. However, as this has been discussed in many more prominent studies, I did not explain it deeply in this article.</p><p>For Korean speakers, if you need more information on the internal structure of JVM, I recommend you to refer to "<b>Java Performance Fundamental</b>" (Hando Kim, Seoul, EXEM, 2009). The book is written in Korean so it is easy to read.&nbsp;I have referenced this book as well as the JVM specifications to write this article.&nbsp;For English speaking readers, there should be many books covering Java Performance topic.</p><p>By Se Hoon Park, Messaging Platform Development Team, NHN Corporation.</p><p></p>]]></description>
                        <pubDate>Wed, 08 Feb 2012 11:26:37 +0900</pubDate>
                        <category>JVM</category>
                        <category>Java</category>
                        <category>programming</category>
                        <category>VM</category>
                        <category>Virtual Machine</category>
                        <category>Java bytecode</category>
                        <category>Java Virtual Machine</category>
                                    <slash:comments>1</slash:comments>
                    </item>
        										        <item>
            <title>How to Analyze Java Thread Dumps</title>
            <dc:creator>Tae Jin Gu</dc:creator>
            <link>http://www.cubrid.org/blog/dev-platform/how-to-analyze-java-thread-dumps/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/dev-platform/how-to-analyze-java-thread-dumps/</guid>
                        <comments>http://www.cubrid.org/blog/dev-platform/how-to-analyze-java-thread-dumps/#comment</comments>
                                    <description><![CDATA[<p></p><p>When there is an obstacle, or when a Java based Web application is running much slower than expected,&nbsp;we need to use <b>thread dumps</b>. If thread dumps feel like very complicated to you,&nbsp;this article may help you very much. Here I will explain what threads are in Java, their types, how they are created, how to manage them, how you can dump threads from a running application, and finally how you can analyze them and determine the bottleneck or blocking threads. This article is a result of long&nbsp;experience in&nbsp;Java application debugging.</p><h2>Java and Thread</h2><p>A web server uses tens to hundreds of threads to process a large number of concurrent users. If two or more threads utilize the same resources, a <i>contention</i> between the threads is inevitable, and sometimes deadlock occurs.</p><p><b>Thread contention</b> is a status in which one thread is waiting for a lock, held by another thread, to be lifted. Different threads frequently access shared resources on a web application. For example, to record a log, the thread trying to record the log must obtain a lock and access the shared resources.</p><p><b>Deadlock</b> is a special type of thread contention, in which two or more threads are waiting for the other threads to complete their tasks in order to complete their own tasks.</p><p>Different issues can arise from thread contention. To analyze such issues, you need to use the <b>thread dump</b>. A thread dump will give you the information on the exact status of each thread.</p><h2>Background Information for Java Threads</h2><h3>Thread Synchronization</h3><p>A thread can be processed with other threads at the same time. In order to ensure compatibility when multiple threads are trying to use shared resources, one thread at a time should be allowed to access the shared resources by using <i>thread synchronization</i>.</p><p>Thread synchronization on Java can be done using <b>monitor</b>. Every Java object has a single monitor. The monitor can be owned by only one thread. For a thread to own a monitor that is owned by a different thread, it needs to wait in the wait queue until the other thread releases its monitor.</p><h3>Thread Status</h3><p>In order to analyze a thread dump, you need to know the status of threads. The statuses of threads are stated on java.lang.Thread.State.</p><p style="text-align: center;">&nbsp;<img src="http://www.cubrid.org/files/attach/images/220547/971/295/thread-state-diagram.png" alt="Figure 1: Thread Status." width="295" height="288" editor_component="image_link" />
</p><p style="text-align: center;"><b>Figure 1: Thread Status.</b></p><p></p><ul><li><b>NEW</b>: The thread is created but has not been processed yet.</li><li><b>RUNNABLE</b>: The thread is occupying the CPU and processing a task. (It may be in <span style="font-family: monospace; ">WAITING</span> status due to the OS's resource distribution.)</li><li><b>BLOCKED</b>: The thread is waiting for a different thread to release its lock in order to get the monitor lock.</li><li><b>WAITING</b>: The thread is waiting by using a <span style="font-family: monospace; ">wait, join</span> or <span style="font-family: monospace; ">park</span> method.</li><li><b>TIMED_WAITING</b>: The thread is waiting by using a <span style="font-family: monospace; ">sleep</span>, <span style="font-family: monospace; ">wait</span>, <span style="font-family: monospace; ">join</span> or <span style="font-family: monospace; ">park</span> method. (The difference from <span style="font-family: monospace; ">WAITING</span> is that the maximum waiting time is specified by the method parameter, and <i>WAITING</i> can be relieved by time as well as external changes.)&nbsp;</li></ul><p></p><h3>Thread Types</h3><p>Java threads can be divided into two:</p><p></p><ol><li>daemon threads;</li><li> and non-daemon threads.</li></ol><p></p><p><b>Daemon threads</b> stop working when there are no other non-daemon threads. Even if you do not create any threads, the Java application will create several threads by default. Most of them are daemon threads, mainly for processing tasks such as garbage collection or JMX.</p><p>A thread running the '<span style="font-family: monospace; ">static void main(String[] args)</span>’ method is created as a non-daemon thread, and when this thread stops working, all other daemon threads will stop as well. (The thread running this main method is called the <b>VM thread in HotSpot VM</b>.)</p><h2>Getting a Thread Dump</h2><p>We will introduce the three most commonly used methods. Note that there are many other ways to get a thread dump. A thread dump can only show the thread status at the time of measurement, so in order to see the change in thread status, it is recommended to extract them from 5 to 10 times with 5-second intervals.</p><h3>Getting a Thread Dump Using jstack</h3><p>In JDK 1.6 and higher, it is possible to get a thread dump on MS Windows using <b>jstack</b>.</p><p>Use PID via jps to check the PID of the currently running Java application process.</p><p></p><div editor_component="code_highlighter" code_type="Bash" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url('./modules/editor/components/code_highlighter/code.png') no-repeat top right;">[user@linux ~]$ ups -v<br /><br />25780 RemoteTestRunner -Dfile.encoding=UTF-8<br />25590 sub.rmi.registry.RegistryImpl 2999 -Dapplication.home=/home1/user/java/jdk.1.6.0_24 -Xms8m<br />26300 sun.tools.jps.Jps -mlvV -Dapplication.home=/home1/user/java/jdk.1.6.0_24 -Xms8m</div><p></p><p>Use the extracted PID as the parameter of jstack to obtain a thread dump.</p><p></p><div editor_component="code_highlighter" code_type="Bash" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url('./modules/editor/components/code_highlighter/code.png') no-repeat top right;">[user@linux ~]$ jstack -f5824&nbsp;</div><p></p><h3>A Thread Dump Using jVisualVM</h3><p>Generate a thread dump by using a program such as jVisualVM.</p><p style="text-align: center;"><img src="http://www.cubrid.org/files/attach/images/220547/971/295/thread-dump-using-jvisualvm.png" alt="Figure 2: &amp;nbsp;A Thread Dump Using visualvm." width="689" height="520" editor_component="image_link" /><br /></p><p style="text-align: center;"><b>Figure 2: &nbsp;A Thread Dump Using visualvm.</b></p><p>The task on the left indicates the list of currently running processes. Click on the process for which you want the information, and select the thread tab to check the thread information in real time. Click the <span style="font-family: monospace; ">Thread Dump</span> button on the top right corner to get the thread dump file.</p><h3>Generating in a Linux Terminal</h3><p>Obtain the process <span style="font-family: monospace; ">pid</span> by using <span style="font-family: monospace; ">ps -ef</span> command to check the pid of the currently running Java process.</p><p></p><div editor_component="code_highlighter" code_type="Bash" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url('./modules/editor/components/code_highlighter/code.png') no-repeat top right;">[user@linux ~]$ ps - ef | grep java<br /><br />user &nbsp; &nbsp; &nbsp;2477 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp;0 Dec23 ? &nbsp; &nbsp; &nbsp; &nbsp; 00:10:45 ...<br />user &nbsp; &nbsp;25780 25361 &nbsp; 0 15:02 pts/3 &nbsp; &nbsp;00:00:02 ./jstatd -J -Djava.security.policy=jstatd.all.policy -p 2999<br />user &nbsp; &nbsp;26335 25361 &nbsp; 0 15:49 pts/3 &nbsp; &nbsp;00:00:00 grep java</div><p></p><p>Use the extracted pid as the parameter of <span style="font-family: monospace; ">kill –SIGQUIT(3)</span> to obtain a thread dump.</p><h2>Thread Information from the Thread Dump File</h2>

<pre><span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">"pool-1-thread-13"</span> <span style="background-color: rgb(166, 255, 77); color: rgb(0, 0, 0); ">prio=6</span> <span style="background-color: rgb(153, 220, 255); color: rgb(0, 0, 0); ">tid=0x000000000729a000 nid=0x2fb4</span> <span style="background-color: rgb(147, 52, 216); color: rgb(255, 255, 255); ">runnable [0x0000000007f0f000] java.lang.Thread.State: RUNNABLE</span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">at java.net.SocketInputStream.socketRead0(Native Method)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">at java.net.SocketInputStream.read(SocketInputStream.java:129)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">- locked &lt;0x0000000780b7e688&gt; (a java.io.InputStreamReader)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">at java.io.InputStreamReader.read(InputStreamReader.java:167)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">at java.io.BufferedReader.fill(BufferedReader.java:136)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">at java.io.BufferedReader.readLine(BufferedReader.java:299)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">- locked &lt;0x0000000780b7e688&gt; (a java.io.InputStreamReader)
</span></span>
              <span style="background-color: rgb(142, 142, 142); color: rgb(255, 255, 255); "><span style="color: rgb(0, 0, 0); ">at java.io.BufferedReader.readLine(BufferedReader.java:362)</span></span></pre>

<ul><li><span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">Thread name</span>: When using Java.lang.Thread class to generate a thread, the thread will be named Thread-(Number), whereas when using java.util.concurrent.ThreadFactory class, it will be named pool-(number)-thread-(number).</li><li><span style="background-color: rgb(166, 255, 77); color: rgb(0, 0, 0); ">Priority</span>: Represents the priority of the threads.</li><li><span style="background-color: rgb(153, 220, 255); color: rgb(0, 0, 0); ">Thread ID</span>: Represents the unique ID for the threads. (Some useful information, including the CPU usage or memory usage of the thread, can be obtained by using thread ID.)</li><li><span style="background-color: rgb(147, 52, 216); color: rgb(255, 255, 255); ">Thread status</span>: Represents the status of the threads.</li><li><span style="background-color: rgb(142, 142, 142); color: rgb(0, 0, 0); ">Thread callstack</span>: Represents the call stack information of the threads.&nbsp;</li></ul><h2>Thread Dump Patterns by Type</h2>

<h3>When Unable to Obtain a Lock (BLOCKED)</h3>

<p>This is when the overall performance of the application slows down because a thread is occupying the lock and prevents other threads from obtaining it. In the following example, <span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">BLOCKED_TEST pool-1-thread-1</span> thread is running with &lt;<span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); "><span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); ">0x0000000780a000b0</span></span>&gt; lock, while <span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">BLOCKED_TEST pool-1-thread-2</span> and <span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">BLOCKED_TEST pool-1-thread-3</span> threads are waiting to obtain &lt;<span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); "><span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); ">0x0000000780a000b0</span></span>&gt; lock.</p>

<p style="text-align: center;"><img src="http://www.cubrid.org/files/attach/images/220547/971/295/when-unable-to-obtain-lock.png" alt="Figure 3: A thread blocking other threads" width="581" height="84" editor_component="image_link" /></p><p style="text-align: center;"><b>Figure 3: A thread blocking other threads.</b>&nbsp;</p>

<pre>"BLOCKED_TEST pool-1-thread-1" prio=6 tid=0x0000000006904800 nid=0x28f4 runnable [0x000000000785f000]
   java.lang.Thread.State: <span style="background-color: rgb(166, 255, 77); color: rgb(0, 0, 0); ">RUNNABLE</span>
                at java.io.FileOutputStream.writeBytes(Native Method)
                at java.io.FileOutputStream.write(FileOutputStream.java:282)
                at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
                at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
                - locked &lt;0x0000000780a31778&gt; (a java.io.BufferedOutputStream)
                at java.io.PrintStream.write(PrintStream.java:432)
                - locked &lt;0x0000000780a04118&gt; (a java.io.PrintStream)
                at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)
                at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272)
                at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:85)
                - locked &lt;0x0000000780a040c0&gt; (a java.io.OutputStreamWriter)
                at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:168)
                at java.io.PrintStream.newLine(PrintStream.java:496)
                - locked &lt;0x0000000780a04118&gt; (a java.io.PrintStream)
                at java.io.PrintStream.println(PrintStream.java:687)
                - locked &lt;0x0000000780a04118&gt; (a java.io.PrintStream)
                at com.nbp.theplatform.threaddump.ThreadBlockedState.monitorLock(ThreadBlockedState.java:44)
                - locked &lt;<span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); "><span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); ">0x0000000780a000b0</span></span>&gt; (a com.nbp.theplatform.threaddump.ThreadBlockedState)
                at com.nbp.theplatform.threaddump.ThreadBlockedState$1.run(ThreadBlockedState.java:7)
                at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
                at java.lang.Thread.run(Thread.java:662)

   Locked ownable synchronizers:
                - &lt;0x0000000780a31758&gt; (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"BLOCKED_TEST pool-1-thread-2" prio=6 tid=0x0000000007673800 nid=0x260c waiting for monitor entry [0x0000000008abf000]
   java.lang.Thread.State: <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> (on object monitor)
                at com.nbp.theplatform.threaddump.ThreadBlockedState.monitorLock(ThreadBlockedState.java:43)
                - waiting to lock &lt;<span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); "><span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); ">0x0000000780a000b0</span></span>&gt; (a com.nbp.theplatform.threaddump.ThreadBlockedState)
                at com.nbp.theplatform.threaddump.ThreadBlockedState$2.run(ThreadBlockedState.java:26)
                at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
                at java.lang.Thread.run(Thread.java:662)

   Locked ownable synchronizers:
                - &lt;0x0000000780b0c6a0&gt; (a java.util.concurrent.locks.ReentrantLock$NonfairSync)

"BLOCKED_TEST pool-1-thread-3" prio=6 tid=0x00000000074f5800 nid=0x1994 waiting for monitor entry [0x0000000008bbf000]
   java.lang.Thread.State: <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> (on object monitor)
                at com.nbp.theplatform.threaddump.ThreadBlockedState.monitorLock(ThreadBlockedState.java:42)
                - waiting to lock &lt;<span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); "><span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); ">0x0000000780a000b0</span></span>&gt; (a com.nbp.theplatform.threaddump.ThreadBlockedState)
                at com.nbp.theplatform.threaddump.ThreadBlockedState$3.run(ThreadBlockedState.java:34)
                at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
                at java.lang.Thread.run(Thread.java:662)

   Locked ownable synchronizers:
                - &lt;0x0000000780b0e1b8&gt; (a java.util.concurrent.locks.ReentrantLock$NonfairSync)</pre>


<h3>When in Deadlock Status</h3>

<p>This is when <i>thread A</i> needs to obtain <i>thread B</i>'s lock to continue its task, while <i>thread B</i> needs to obtain <i>thread A</i>'s lock to continue its task. In the thread dump, you can see that <span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">DEADLOCK_TEST-1 thread</span> has <span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); ">0x00000007d58f5e48</span> lock, and is trying to obtain <span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); "><span style="background-color: rgb(153, 220, 255); color: rgb(0, 0, 0); ">0x00000007d58f5e60</span></span> lock. You can also see that <span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">DEADLOCK_TEST-2 thread</span> has <span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); "><span style="background-color: rgb(153, 220, 255); color: rgb(0, 0, 0); ">0x00000007d58f5e60</span></span> lock, and is trying to obtain <span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); "><span style="background-color: rgb(166, 255, 77); color: rgb(0, 0, 0); ">0x00000007d58f5e78</span></span> lock. Also, <span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">DEADLOCK_TEST-3 thread</span> has <span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); "><span style="background-color: rgb(166, 255, 77); color: rgb(0, 0, 0); ">0x00000007d58f5e78</span></span> lock, and is trying to obtain <span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); ">0x00000007d58f5e48</span> lock. As you can see, each thread is waiting to obtain another thread's lock, and this status will not change until one thread discards its lock.</p><p style="text-align: center;"><img src="http://www.cubrid.org/files/attach/images/220547/971/295/when-in-deadlock-status.png" alt="Figure 4: Threads in a Deadlock status" width="580" height="91" editor_component="image_link" /><br /></p><p style="text-align: center;"><b>Figure 4: Threads in a Deadlock status.</b></p>

<pre>"DEADLOCK_TEST-1" daemon prio=6 tid=0x000000000690f800 nid=0x1820 waiting for monitor entry [0x000000000805f000]
   java.lang.Thread.State: <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> (on object monitor)
                at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.goMonitorDeadlock(ThreadDeadLockState.java:197)
                - waiting to lock &lt;<span style="background-color: rgb(153, 220, 255); color: rgb(0, 0, 0); ">0x00000007d58f5e60</span>&gt; (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
                at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.monitorOurLock(ThreadDeadLockState.java:182)
                - locked &lt;<span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); ">0x00000007d58f5e48</span>&gt; (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
                at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.run(ThreadDeadLockState.java:135)

   Locked ownable synchronizers:
                - None

"DEADLOCK_TEST-2" daemon prio=6 tid=0x0000000006858800 nid=0x17b8 waiting for monitor entry [0x000000000815f000]
   java.lang.Thread.State: <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> (on object monitor)
                at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.goMonitorDeadlock(ThreadDeadLockState.java:197)
                - waiting to lock &lt;<span style="background-color: rgb(166, 255, 77); color: rgb(0, 0, 0); ">0x00000007d58f5e78</span>&gt; (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
                at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.monitorOurLock(ThreadDeadLockState.java:182)
                - locked &lt;<span style="background-color: rgb(153, 220, 255); color: rgb(0, 0, 0); ">0x00000007d58f5e60</span>&gt; (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
                at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.run(ThreadDeadLockState.java:135)

   Locked ownable synchronizers:
                - None

"DEADLOCK_TEST-3" daemon prio=6 tid=0x0000000006859000 nid=0x25dc waiting for monitor entry [0x000000000825f000]
   java.lang.Thread.State: <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> (on object monitor)
                at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.goMonitorDeadlock(ThreadDeadLockState.java:197)
                - waiting to lock &lt;<span style="background-color: rgb(255, 167, 0); color: rgb(255, 255, 255); ">0x00000007d58f5e48</span>&gt; (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
                at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.monitorOurLock(ThreadDeadLockState.java:182)
                - locked &lt;<span style="background-color: rgb(166, 255, 77); color: rgb(0, 0, 0); ">0x00000007d58f5e78</span>&gt; (a com.nbp.theplatform.threaddump.ThreadDeadLockState$Monitor)
                at com.nbp.theplatform.threaddump.ThreadDeadLockState$DeadlockThread.run(ThreadDeadLockState.java:135)

   Locked ownable synchronizers:
                - None
</pre>

<h3>When Continuously Waiting to Receive Messages from a Remote Server</h3>

<p>The thread appears to be normal, since its state keeps showing as <span style="background-color: rgb(166, 255, 77); color: rgb(0, 0, 0); "><span style="background-color: rgb(147, 52, 216); color: rgb(255, 255, 255); ">RUNNABLE</span></span>.&nbsp;However, when you align the thread dumps chronologically, you can see that <span style="font-family: monospace; ">socketReadThread thread</span> is waiting infinitely to read the socket.</p><p style="text-align: center;"><img src="http://www.cubrid.org/files/attach/images/220547/971/295/when-continuosly-waiting-to-receive-message-from-remote-server.png" alt="Figure 5: Continuous Waiting Status" width="578" height="33" editor_component="image_link" /><br /></p><p style="text-align: center;"><b>Figure 5: Continuous Waiting Status.</b></p>

<pre>"socketReadThread" prio=6 tid=0x0000000006a0d800 nid=0x1b40 runnable [0x00000000089ef000]
   java.lang.Thread.State: <span style="background-color: rgb(147, 52, 216); color: rgb(255, 255, 255); ">RUNNABLE</span>
                at java.net.SocketInputStream.socketRead0(Native Method)
                at java.net.SocketInputStream.read(SocketInputStream.java:129)
                at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
                at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
                at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
                - locked &lt;0x00000007d78a2230&gt; (a java.io.InputStreamReader)
                at sun.nio.cs.StreamDecoder.read0(StreamDecoder.java:107)
                - locked &lt;0x00000007d78a2230&gt; (a java.io.InputStreamReader)
                at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:93)
                at java.io.InputStreamReader.read(InputStreamReader.java:151)
                at com.nbp.theplatform.threaddump.ThreadSocketReadState$1.run(ThreadSocketReadState.java:27)
                at java.lang.Thread.run(Thread.java:662)</pre>

<h3>When Waiting</h3>

<p>The thread is maintaining <span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">WAIT</span> status. In the thread dump, <span style="font-family: monospace; ">IoWaitThread thread</span> keeps waiting to receive a message from <span style="font-family: monospace; ">LinkedBlockingQueue</span>. If there continues to be no message for LinkedBlockingQueue, then the thread status will not change.</p><p style="text-align: center;"><img src="http://www.cubrid.org/files/attach/images/220547/971/295/when-waiting.png" alt="Figure 6: Waiting status" width="580" height="35" editor_component="image_link" /><br /></p><p style="text-align: center;"><b>Figure 6: Waiting status.</b></p><pre>"IoWaitThread" prio=6 tid=0x0000000007334800 nid=0x2b3c waiting on condition [0x000000000893f000]
   java.lang.Thread.State: <span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">WAITING</span> (parking)
                at sun.misc.Unsafe.park(Native Method)
                - parking to wait for  &lt;0x00000007d5c45850&gt; (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
                at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
                at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1987)
                at java.util.concurrent.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:440)
                at java.util.concurrent.LinkedBlockingDeque.take(LinkedBlockingDeque.java:629)
                at com.nbp.theplatform.threaddump.ThreadIoWaitState$IoWaitHandler2.run(ThreadIoWaitState.java:89)
                at java.lang.Thread.run(Thread.java:662)
</pre>

<h3>When Thread Resources Cannot be Organized Normally</h3><p>Unnecessary threads will pile up when thread resources cannot be organized normally. If this occurs, it is recommended to monitor the thread organization process or check the conditions for thread termination.</p><p style="text-align: center;"><img src="http://www.cubrid.org/files/attach/images/220547/971/295/when-thread-resources-cannot-be-organized-normally.png" alt="Figure 7: Unorganized Threads" width="678" height="193" editor_component="image_link" /><br /></p><p style="text-align: center;"><b>Figure 7: Unorganized Threads.</b></p><h2>How to Solve Problems by Using Thread Dump</h2><h3>Example 1: When the CPU Usage is Abnormally High</h3><p></p><ol><li>Extract the thread that has the highest CPU usage.<br /><div editor_component="code_highlighter" code_type="Bash" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url('./modules/editor/components/code_highlighter/code.png') no-repeat top right;">[user@linux ~]$ ps -mo pid.lwp.stime.time.cpu -C java<br /><br />&nbsp; &nbsp; &nbsp;PID &nbsp; &nbsp; &nbsp; &nbsp; LWP &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;STIME &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TIME &nbsp; &nbsp; &nbsp; &nbsp;%CPU<br />10029 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - &nbsp; &nbsp; &nbsp; &nbsp; Dec07 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;00:02:02 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 99.5<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- &nbsp; &nbsp; &nbsp; 10039 &nbsp; &nbsp; &nbsp; &nbsp;Dec07 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;00:00:00 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0.1<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- &nbsp; &nbsp; &nbsp; 10040 &nbsp; &nbsp; &nbsp; &nbsp;Dec07 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;00:00:00 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 95.5</div><p>From the application, find out which thread is using the CPU the most.</p><p>Acquire the <i>Light Weight Process</i> (LWP) that uses the CPU the most and convert its unique number (10039) into a hexadecimal number (0x2737).</p></li>
<li><p>After acquiring the thread dump, check the thread's action.</p><p>Extract the thread dump of an application with a PID of 10029, then find the thread with an <span style="font-family: monospace; ">nid of 0x2737</span>.</p>
<pre>"NioProcessor-2" prio=10 tid=0x0a8d2800 nid=0x2737 runnable [0x49aa5000]
java.lang.Thread.State: RUNNABLE
                at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
                at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:210)
                at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:65)
                at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:69)
                - locked &lt;0x74c52678&gt; (a sun.nio.ch.Util$1)
                - locked &lt;0x74c52668&gt; (a java.util.Collections$UnmodifiableSet)
                - locked &lt;0x74c501b0&gt; (a sun.nio.ch.EPollSelectorImpl)
                at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:80)
                at external.org.apache.mina.transport.socket.nio.NioProcessor.select(NioProcessor.java:65)
                at external.org.apache.mina.common.AbstractPollingIoProcessor$Worker.run(AbstractPollingIoProcessor.java:708)
                at external.org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
                at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
                at java.lang.Thread.run(Thread.java:662)
</pre>
<p>Extract thread dumps several times every hour, and check the status change of the threads to determine the problem.</p></li></ol>

<h3>Example 2: When the Processing Performance is Abnormally Slow &nbsp;</h3>

<p>After acquiring thread dumps several times, find the list of threads with <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> status.</p>

<pre>" DB-Processor-13" daemon prio=5 tid=0x003edf98 nid=0xca waiting for monitor entry [0x000000000825f000]
java.lang.Thread.State: <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> (on object monitor)
                at beans.ConnectionPool.getConnection(ConnectionPool.java:102)
                - waiting to lock &lt;<span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">0xe0375410</span>&gt; (a beans.ConnectionPool)
                at beans.cus.ServiceCnt.getTodayCount(ServiceCnt.java:111)
                at beans.cus.ServiceCnt.insertCount(ServiceCnt.java:43)

"DB-Processor-14" daemon prio=5 tid=0x003edf98 nid=0xca waiting for monitor entry [0x000000000825f020]
java.lang.Thread.State: <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> (on object monitor)
                at beans.ConnectionPool.getConnection(ConnectionPool.java:102)
                - waiting to lock &lt;<span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">0xe0375410</span>&gt; (a beans.ConnectionPool)
                at beans.cus.ServiceCnt.getTodayCount(ServiceCnt.java:111)
                at beans.cus.ServiceCnt.insertCount(ServiceCnt.java:43)

" DB-Processor-3" daemon prio=5 tid=0x00928248 nid=0x8b waiting for monitor entry [0x000000000825d080]
java.lang.Thread.State: <span style="background-color: rgb(147, 52, 216); color: rgb(255, 255, 255); ">RUNNABLE</span>
                at oracle.jdbc.driver.OracleConnection.isClosed(OracleConnection.java:570)
                - waiting to lock &lt;0xe03ba2e0&gt; (a oracle.jdbc.driver.OracleConnection)
                at beans.ConnectionPool.getConnection(ConnectionPool.java:112)
                - locked &lt;0xe0386580&gt; (a java.util.Vector)
                - locked &lt;0xe0375410&gt; (a beans.ConnectionPool)
                at beans.cus.Cue_1700c.GetNationList(Cue_1700c.java:66)
                at org.apache.jsp.cue_1700c_jsp._jspService(cue_1700c_jsp.java:120)
</pre>

<p>Acquire the list of threads with <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> status after getting the thread dumps several times.</p><p>If the threads are BLOCKED, extract the threads related to the lock that the threads are trying to obtain.</p><p>Through the thread dump, you can confirm that the thread status stays <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> because &lt;<span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">0xe0375410</span>&gt; lock could not be obtained. This problem can be solved by analyzing stack trace from the thread currently holding the lock.</p><p>There are two reasons why the above pattern frequently appears in applications using DBMS. The first reason is <b>inadequate configurations</b>. Despite the fact that the threads are still working, they cannot show their best performance because the configurations for DBCP and the like are not adequate. If you extract thread dumps multiple times and compare them, you will often see that some of the threads that were BLOCKED previously are in a different state.</p><p>The second reason is the <b>abnormal connection</b>. When the connection with DBMS stays abnormal, the threads wait until the time is out. In this case, even after extracting the thread dumps several times and comparing them, you will see that the threads related to DBMS are still in a BLOCKED state. By adequately changing the values, such as the timeout value, you can shorten the time in which the problem occurs.</p><h2>Coding for Easy Thread Dump</h2><h3>Naming Threads</h3><p>When a thread is created using <span style="font-family: monospace; ">java.lang.Thread</span> object, the thread will be named <span style="font-family: monospace; ">Thread-(Number)</span>. When a thread is created using <span style="font-family: monospace; ">java.util.concurrent.DefaultThreadFactory</span> object, the thread will be named <span style="font-family: monospace; ">pool-(Number)-thread-(Number)</span>. When analyzing tens to thousands of threads for an application, if all the threads still have their default names, analyzing them becomes very difficult, because it is difficult to distinguish the threads to be analyzed.</p><p>Therefore, you are recommended to develop the habit of naming the threads whenever a new thread is created.&nbsp;</p><p>When you create a thread using <span style="font-family: monospace; ">java.lang.Thread</span>, you can give the thread a custom name by using the creator parameter.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url('./modules/editor/components/code_highlighter/code.png') no-repeat top right;"><p>public Thread(Runnable target, String name);<br />public Thread(ThreadGroup group, String name);<br />public Thread(ThreadGroup group, Runnable target, String name);<br />public Thread(ThreadGroup group, Runnable target, String name, long stackSize);</p></div><p></p><p></p><p>When you create a thread using <span style="font-family: monospace; ">java.util.concurrent.ThreadFactory</span>, you can name it by generating your own <span style="font-family: monospace; ">ThreadFactory</span>. If you do not need special functionalities, then you can use <span style="font-family: monospace; ">MyThreadFactory</span> as described below:</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url('./modules/editor/components/code_highlighter/code.png') no-repeat top right;"><p>import java.util.concurrent.ConcurrentHashMap;<br />import java.util.concurrent.ThreadFactory;<br />import java.util.concurrent.atomic.AtomicInteger;<br /><br />public class MyThreadFactory implements ThreadFactory {<br />&nbsp; private static final ConcurrentHashMap&lt;String, AtomicInteger&gt; POOL_NUMBER =<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;new ConcurrentHashMap&lt;String, AtomicInteger&gt;();<br />&nbsp; private final ThreadGroup group;<br />&nbsp; private final AtomicInteger threadNumber = new AtomicInteger(1);<br />&nbsp; private final String namePrefix;<br />&nbsp;<br />&nbsp; public MyThreadFactory(String threadPoolName) {<br />&nbsp; &nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; if (threadPoolName == null) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new NullPointerException("threadPoolName");<br />&nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp;&nbsp;</p><p>&nbsp; &nbsp; &nbsp; POOL_NUMBER.putIfAbsent(threadPoolName, new AtomicInteger());<br />&nbsp; &nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; SecurityManager securityManager = System.getSecurityManager();<br />&nbsp; &nbsp; &nbsp; group = (securityManager != null) ? securityManager.getThreadGroup() :<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread.currentThread().getThreadGroup();<br />&nbsp; &nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; AtomicInteger poolCount = POOL_NUMBER.get(threadPoolName);<br /><br />&nbsp; &nbsp; &nbsp; if (poolCount == null) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; namePrefix = threadPoolName + " pool-00-thread-";<br />&nbsp; &nbsp; &nbsp; } else {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; namePrefix = threadPoolName + " pool-" + poolCount.getAndIncrement() + "-thread-";<br />&nbsp; &nbsp; &nbsp; }<br />&nbsp; }<br />&nbsp;<br />&nbsp; public Thread newThread(Runnable runnable) {<br />&nbsp; &nbsp; &nbsp; Thread thread = new Thread(group, runnable, namePrefix + threadNumber.getAndIncrement(), 0);<br /><br />&nbsp; &nbsp; &nbsp; if (thread.isDaemon()) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thread.setDaemon(false);<br />&nbsp; &nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; &nbsp; if (thread.getPriority() != Thread.NORM_PRIORITY) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thread.setPriority(Thread.NORM_PRIORITY);<br />&nbsp; &nbsp; &nbsp; }<br /><br />&nbsp; &nbsp; &nbsp; return thread;<br />&nbsp; }<br />}</p></div><h3>Obtaining More Detailed Information by Using MBean</h3><p>You can obtain <span style="font-family: monospace; ">ThreadInfo</span> objects using <span style="font-family: monospace; ">MBean</span>. You can also obtain more information that would be difficult to acquire via thread dumps, by using ThreadInfo.</p><p></p><div editor_component="code_highlighter" code_type="Java" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url('./modules/editor/components/code_highlighter/code.png') no-repeat top right;"><p>ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();<br />long[] threadIds = mxBean.getAllThreadIds();<br />ThreadInfo[] threadInfos =<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mxBean.getThreadInfo(threadIds);<br /><br />for (ThreadInfo threadInfo : threadInfos) {<br />&nbsp; System.out.println(<br />&nbsp; &nbsp; &nbsp; threadInfo.getThreadName());<br />&nbsp; System.out.println(<br />&nbsp; &nbsp; &nbsp; threadInfo.getBlockedCount());<br />&nbsp; System.out.println(<br />&nbsp; &nbsp; &nbsp; threadInfo.getBlockedTime());<br />&nbsp; System.out.println(<br />&nbsp; &nbsp; &nbsp; threadInfo.getWaitedCount());<br />&nbsp; System.out.println(<br />&nbsp; &nbsp; &nbsp; threadInfo.getWaitedTime());<br />}&nbsp;</p></div><p>You can acquire the amount of time that the threads <span style="background-color: rgb(228, 255, 117); color: rgb(0, 0, 0); ">WAITed</span> or were <span style="background-color: rgb(255, 0, 0); color: rgb(255, 255, 255); ">BLOCKED</span> by using the method in ThreadInfo, and by using this you can also obtain the list of threads that have been inactive for an abnormally long period of time.</p><h2>In Conclusion</h2><p>In this article I was concerned that for developers with a lot of experience in multi-thread programming, this material may be common knowledge, whereas for less experienced developers, I felt that I was skipping straight to thread dumps, without providing enough background information about the thread activities. This was because of my lack of knowledge, as I was not able to explain the thread activities in a clear yet concise manner. I sincerely hope that this article will prove helpful for many developers.</p><p></p><p>By Tae Jin Gu, Software Engineer at Web Platform Development Lab, NHN Corporation.</p>]]></description>
                        <pubDate>Thu, 16 Feb 2012 16:13:27 +0900</pubDate>
                        <category>Java</category>
                        <category>programming</category>
                        <category>Threads</category>
                        <category>Debugging</category>
                                    <slash:comments>1</slash:comments>
                    </item>
        										        <item>
            <title>Log Analysis System Using Hadoop and MongoDB</title>
            <dc:creator>Jeong Hyun Lee</dc:creator>
            <link>http://www.cubrid.org/blog/dev-platform/log-analysis-system-using-hadoop-and-mongodb/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/dev-platform/log-analysis-system-using-hadoop-and-mongodb/</guid>
                        <comments>http://www.cubrid.org/blog/dev-platform/log-analysis-system-using-hadoop-and-mongodb/#comment</comments>
                                    <description><![CDATA[<p>I have been searching for a way to process the exponentially increasing service logs at a low cost. For the past several months, the Monitoring System Development Team here at <a href="http://blog.cubrid.org/tags/NHN/" target="_self">NHN</a>&nbsp;has also been looking for a good way to analyze logs. In this article, I want to tell you what we have come up with.</p>
<p>Every day, many developers and database administrators struggle to find ways to complete their tasks. One such task is <strong>statistics</strong>. Let's say that an operator (or a producer) asks you to retrieve some statistics data. It will be a relatively easy task if the size of the data is less than a few million rows, or if your organization has a dedicated backup database from which you can retrieve statistics.</p>
<blockquote class="q1">
<p>But what if you have to retrieve a large amount of data without a backup database?</p></blockquote>
<p>This will be a challenge for most of us. The Monitoring System Development Team has long been searching for better ways to process work involving statistics, and finally found a solution which involves using <a href="http://blog.cubrid.org/tags/MongoDB/" target="_self">MongoDB</a> and <a href="http://blog.cubrid.org/tags/Hadoop/" target="_self">Hadoop</a>. In this article, I will show you what we have done and experienced.</p><a name="more"></a>
<h2>Introduction</h2>
<p>The team is developing and operating monitoring systems such as <span style="FONT-STYLE: italic">xMon</span> (these are common names of the monitoring systems used at NHN: uMon, kMon, cMon, jrMon and ocMon). The storage capacity of the Oracle database used by xMon is 20 TB. This Oracle database stores a large amount of data, such as user-generated content (UGC) metadata (the body or multimedia data are distributed and saved in <strong>OwFS</strong>&nbsp;and the video infrastructure) that have occurred on each <a href="http://blog.cubrid.org/tags/Naver/" target="_self">NAVER</a> service and the related log data for the past six months. The figure below shows the cycle of UGC generation and destruction that generates a log. The company has been using three Oracle DBMS systems with 128 GB memory to process 20 TB of data.</p>
<blockquote class="q1">
<p>OwFS is a distributed file storage system&nbsp;developed by NHN . Each storage is allocated and distributed in the unit of Owner.</p>
<p>Naver is&nbsp;the&nbsp;major search engine service in Korea.</p></blockquote>
<p align="center"><img style="VERTICAL-ALIGN: middle" alt="UGC Generation and Destruction Cycle" src="http://www.cubrid.org/files/attach/images/220547/206/242/ugc-generation-and-destruction-cycle.png" width="555" height="212" editor_component="image_link"/></p>
<p align="center"><strong>Figure 1. UGC Generation and Destruction Cycle.</strong></p>
<p>The environment in which the Oracle DBMS was being used was getting worse as time went by. The amount of UGC was exponentially increasing. We adopted the policy of archiving only six months worth of data in the database, but the amount of data for that six months was getting bigger and bigger, creating a problem for us. Furthermore, the cost for additional Oracle DBMS storage could not be ignored. The table and figure below show the status and trend of the storage usage of xMon.</p>
<h3>xMon Storage Usage</h3>
<table class="blackcap rowbg">
<thead>
<tr>
<td>Classification</td>
<td>Remaining space</td>
<td>Space used</td>
<td>Total space</td>
<td>Usage</td></tr></thead>
<tbody>
<tr>
<td>xmona</td>
<td>4,593 GB</td>
<td>3,506 GB</td>
<td>8,100 GB</td>
<td>43.29%</td></tr>
<tr>
<td>xmonb</td>
<td>2,768 GB</td>
<td>5,619 GB</td>
<td>8,387 GB</td>
<td>66.99%</td></tr>
<tr>
<td>xmonc</td>
<td>1,533 GB</td>
<td>3,018 GB</td>
<td>4,552 GB</td>
<td>66.30%</td></tr></tbody></table>
<p align="center"><img style="VERTICAL-ALIGN: middle" alt="xMon Storage Usage Trend" src="http://www.cubrid.org/files/attach/images/220547/206/242/xmon-storage-usage-trend.png" width="544" height="270" editor_component="image_link"/></p>
<p align="center"><strong>Firgure 2: xMon Storage Usage Trend.</strong></p>
<p>After experiencing some difficulties, the team had to adopt a better system than Oracle DBMS because of the following two key requirements.</p>
<ul>
<li>Requirement 1: Be able to extract the user unit index by utilizing the existing log data.</li>
<li>Requirement 1-1: The index must be extracted at least once a day.</li>
<li>Requirement 2: The extracted user unit index must be immediately available online.</li>
<li>Requirement 2-1: The index extraction must be implemented as a query function in the existing system.</li></ul>
<p>To satisfy the first requirement, the index, which is a form of statistical data, must be extracted from the data as soon as possible. In the company's old system, statistical data was extracted in the following way: a developer would write an SQL and send it to a database administrator; then, the administrator would verify and execute the SQL and send the result back. As you can imagine, this process was far from speedy.</p>
<p>Requirement 2 can be summarized as "<em>Provide index data that can be queried by a Web browser</em>." Under normal circumstances, meeting this requirement is trivial; but when the size of data to be processed is somewhere around the realm of 4 TB, adding the function to the existing Oracle database is a problem. Adding index data to the storage would increase the load, which was already hitting the ceiling due to the load of processing the ever-growing UGC metadata and log data.</p>
<h2>Data Aggregation and Extraction by Utilizing Map-Reduce</h2>
<p>The required table for index extraction is a generic log table with 30 to 60 columns. This simple schema is logically related to the master table, but there is no actual relation. With this information at hand, one could easily conclude that utilizing DBMS or the Map-Reduce method would be the answer.</p>
<p>In my first attempt, I extracted the index from Oracle by writing an SQL. Adding a query function to the system is not much of a problem (if performance is of no concern) when there are already dozens of PL/SQLs and aggregation tables for a variety of statistics data. I divided the date into small chunks in my SQL. This is called the <strong>divide-and-conquer approach</strong>. It was exactly a week later when I got a call from the database admin. The admin. told me that the SQL in question had been executed for 860 minutes and the CPU usage was up to 60% (30-40% is the usual). The admin stopped the process. With that, my first attempt ended. Unfortunately, my first trial was a total failure. The following is part of the SQL code that is actually used in the field to aggregate the size of unreviewed data for last 1 month.</p>
<div style="BORDER-BOTTOM: #666666 1px dotted; BORDER-LEFT: #22aaee 5px solid; PADDING-BOTTOM: 5px; PADDING-LEFT: 5px; PADDING-RIGHT: 5px; BACKGROUND: url(modules/editor/components/code_highlighter/code.png) #fafafa no-repeat right top; BORDER-TOP: #666666 1px dotted; BORDER-RIGHT: #666666 1px dotted; PADDING-TOP: 5px" editor_component="code_highlighter" nocontrols="false" nogutter="false" collapse="false" first_line="1" description="" file_path="" code_type="Sql">
<p>INSERT INTO kpi_total_xxxxxx <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (dd, td,... ) <br />&nbsp;SELECT /*+ index&nbsp;(b CONT_MSTR_CATE_PK) */&nbsp;SUBSTR(v_start_datehour, 1, 8)&nbsp; dd, a.td,...,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SUM(cnt) as cnt,...&nbsp; FROM (<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT /*+ parallel_index&nbsp;(cm 3) index_ss&nbsp;(cm CONT_MSTR_IDX01) */<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TO_CHAR(umon_in_tdt, 'YYYYMMDD') td,&nbsp;COUNT(1) as cnt&nbsp;FROM&nbsp;cont_mstr cm<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; WHERE&nbsp; ...&nbsp;AND cm.umon_in_tdt &gt;=&nbsp;TO_DATE(TO_CHAR(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ADD_MONTHS(SYSDATE, -1), 'YYYYMM')||'01000000',&nbsp;'YYYYMMDDHH24MISS')<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GROUP&nbsp;BY&nbsp;TO_DATE(cm.umon_in_tdt, 'YYYYMMDD'),&nbsp;cm.category_id<br />&nbsp;&nbsp;&nbsp;&nbsp; ) a,&nbsp;cont_mstr_cate b<br />&nbsp;&nbsp;WHERE&nbsp;a.service_code = b.service_code ...&nbsp; GROUP&nbsp; BY a.td;</p></div>
<p>So, I picked <strong>Map-Reduce</strong> as an alternative. Map-Reduce works in the same way as the <strong>Sort/Merge</strong> functions of RBDMS. Map-Reduce is suitable for a batch data analysis for OLAP (On-line Analytical Processing), which tends to deal with a large amount of data. Most people would think of Hadoop when I say Map-Reduce, but other DBs such as MongoDB, HBase, CouchDB and Hypertable offer Map-Reduce as well. Among these, I chose two DBs to test and verify: <strong>Hadoop</strong> for its time-proven performance, and <strong>MongoDB</strong> for its document-orientedness, which makes saving logs in a sequence an easy task.</p>
<p>I extracted the data first because I couldn't access the Oracle if I were to verify the Map-Reduce of Hadoop. I used the <strong>Kettle</strong> of Pentaho, an open-source ETL (Extract, Transform, Load) solution, to extract the data stored in Oracle. For testing purposes, I used <strong>HDFS</strong> and Map-Reduce only, two of the many features of Hadoop.</p>
<p>I configured three different environments for testing. For Hadoop, I configured the standalone operation and the fully-distributed operation using three DataNodes and one NameNode. Then, I compared the resulting performance with the Map-Reduce of MongoDB.</p>
<p>For your information, the system specifications of the testing machines (each machine is identical) are as follows:</p>
<ul>
<li>CPU: Intel(R) Xeon(R) CPU L5420@2.50GHz * 2 (8 cores)</li>
<li>Memory: 32 GB</li>
<li>Disk: 814 GB (300 GB * 6 ea, RAID 0 + 1)</li>
<li>OS: CentOS 5.2 x86_64</li></ul>
<p>I used one server for the standalone operation of Hadoop, 4 for the fully-distributed operation, and 5 for MongoDB. I separated the name node and the data node in the fully-distributed operation of Hadoop. This separation was necessary because the Job Tracker that executes Reduce task and the main controller run on the name node, while the Task Tracker that actually executes the Map task runs on the data node. MongoDB provides functions that are similar to Map-Reduce of Hadoop. I will explain more about MongoDB later.</p>
<p>The figure below shows the cluster configuration of Hadoop, including the data node and the name node. See <a href="#mongodb-cluster-configuration" target="_self">Figure 6</a> below&nbsp;for the shard configuration of MongoDB.</p>
<p align="center"><img style="VERTICAL-ALIGN: middle" alt="Hadoop Cluster Configuration" src="http://www.cubrid.org/files/attach/images/220547/206/242/hadoop-cluster-configuration.png" width="552" height="238" editor_component="image_link"/></p>
<p align="center"><strong>Figure 3: Hadoop Cluster Configuration.</strong></p>
<p>As shown in the table and figure below, standalone operation is suitable for processing small data, while fully-distributed operation is good for processing large data. Processing small data with the fully-distributed operation is undesirable because the time it takes to collect distributed data in the same nodes during a Reduce operation outweighs the advantages of distributing data to each node using Map. In this test, the fully-distributed operation of 10 million rows of data outperformed other test conditions. The test result varies depending on the amount of data and the system specification - you must test the configuration before applying it to the system.</p>
<h3>Comparison of Map-Reduce Performance between Hadoop and MongoDB</h3>
<table class="blackcap rowbg">
<thead>
<tr>
<td rowspan="2">Data count</td>
<td rowspan="2">File size</td>
<td colspan="2">Hadoop</td>
<td rowspan="2">MongoDB<br />Shard 2</td></tr>
<tr>
<td>Standalone</td>
<td>Distributed</td></tr></thead>
<tbody>
<tr>
<td>10,000</td>
<td>2 MB</td>
<td>1 second</td>
<td>23 seconds</td>
<td>1 second</td></tr>
<tr>
<td>100,000</td>
<td>25 MB</td>
<td>3 seconds</td>
<td>22 seconds</td>
<td>12 seconds</td></tr>
<tr>
<td>1,000,000</td>
<td>248 MB</td>
<td>20 seconds</td>
<td>29 seconds</td>
<td>65 seconds</td></tr>
<tr>
<td>10,000,000</td>
<td>2,480 MB</td>
<td>183 seconds</td>
<td>53 seconds</td>
<td>805 seconds</td></tr>
<tr>
<td>System</td>
<td>-</td>
<td>1 ea</td>
<td>4 ea</td>
<td>5 ea</td></tr></tbody></table>
<p align="center"><img style="VERTICAL-ALIGN: middle" alt="Comparison of Map-Reduce Performance between Hadoop and MongoDB" src="http://www.cubrid.org/files/attach/images/220547/206/242/comparison-of-map-reduce-performance-between-hadoop-and-mongodb.png" width="432" height="244" editor_component="image_link"/></p>
<p> </p>
<p align="center"><strong>Figure 4: Comparison of Map-Reduce Performance between Hadoop and MongoDB.</strong></p>
<p>Note that you must compensate for the difference in the number of servers used for the standalone operation and the fully-distributed operation by adjusting the amount of data to be processed. Also note that I did not consider using 4 systems for the standalone operation, because doing so would require a separate data split and collection process, which would require additional development resources. Besides, it is simpler to scale in the fully-distributed operation than it is in the standalone operation, because you can just add a data node without modifying the data split and collection process.</p>
<p>I have tested MongoDB as well, in the hope that I could implement both the aggregation system and the index storage system with MongoDB if its performance was similar to that of Hadoop. To my dismay, the Map-Reduce of MongoDB is quite subpar compared to that of Hadoop, as shown in the table above. In short, <strong>MongoDB is roughly four times slower than Hadoop in fully-distributed mode</strong>. A newer version of MongoDB has become available since the test, but I doubt that it would show a noticeable difference in performance from earlier versions.</p>
<h2>Productivity - What Makes MongoDB Stand Out</h2>
<p>When processing small data, MongoDB is still useful. This is because its productivity outweighs its lack of performance when processing small data. The following is the Map-Reduce method using the Java API in Hadoop.</p>
<div style="BORDER-BOTTOM: #666666 1px dotted; BORDER-LEFT: #22aaee 5px solid; PADDING-BOTTOM: 5px; PADDING-LEFT: 5px; PADDING-RIGHT: 5px; BACKGROUND: url(modules/editor/components/code_highlighter/code.png) #fafafa no-repeat right top; BORDER-TOP: #666666 1px dotted; BORDER-RIGHT: #666666 1px dotted; PADDING-TOP: 5px" editor_component="code_highlighter" nocontrols="false" nogutter="false" collapse="false" first_line="1" description="" file_path="" code_type="Java">
<p>//Map<br />public static class DailyIdCountMapClass extends Map-ReduceBase implements<br />&nbsp;&nbsp;&nbsp; Mapper&lt;LongWritable, Text, Text, IntWritable&gt; {<br />&nbsp;&nbsp;&nbsp; public void map(LongWritable key, Text value, OutputCollector&lt;Text, IntWritable&gt; output, Reporter reporter) throws IOException {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String line = value.toString();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String[] tokens = line.split(UserIdConstants.COLUMN_SEPARATOR); <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String userKey = tokens[0];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; output.collect(new Text(userKey), new IntWritable(1));<br />&nbsp;&nbsp;&nbsp; }<br />}<br />//Reduce<br />public static class DailyIdCountReduceClass extends Map-ReduceBase implements<br />&nbsp;&nbsp;&nbsp; Reducer&lt;Text, IntWritable, Text, IntWritable&gt; {<br />&nbsp;&nbsp;&nbsp; public void reduce(Text key, Iterator&lt;IntWritable&gt; values, OutputCollector&lt;Text, IntWritable&gt; output,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Reporter reporter) throws IOException {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int sum = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (values.hasNext()) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sum += values.next().get();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; output.collect(key, new IntWritable(sum));<br />&nbsp;&nbsp;&nbsp; }<br />}</p></div>
<p>The following is a list of internal commands used in the Map-Reduce of MongoDB:</p>
<div style="BORDER-BOTTOM: #666666 1px dotted; BORDER-LEFT: #22aaee 5px solid; PADDING-BOTTOM: 5px; PADDING-LEFT: 5px; PADDING-RIGHT: 5px; BACKGROUND: url(modules/editor/components/code_highlighter/code.png) #fafafa no-repeat right top; BORDER-TOP: #666666 1px dotted; BORDER-RIGHT: #666666 1px dotted; PADDING-TOP: 5px" editor_component="code_highlighter" nocontrols="false" nogutter="false" collapse="false" first_line="1" description="" file_path="" code_type="Java">
<p>&gt; m = function() { emit(this.user_id, 1); }//Map<br />&gt; r = function(k,vals) { return 1; }//Reduce<br />&gt; res = db.wklog_user.Map-Reduce(m, r);</p></div>
<p>Obviously, the MongoDB commands are far simpler than in Hadoop. This is because the commands of MongoDB take advantage of functional language, such as Scala and Ruby. Of course, Hadoop could be optimized with a script language such as Python.</p>
<p>Despite the outstanding performance of Map-Reduce in Hadoop, debugging it could be a challenge, because the data is displayed across multiple, distributed nodes. Maintenance could also be a hassle, because a jar archive must be created and executed when compiling code. But there is some good news - writing the Map-Reduce function is an easy task if you fully understand the underlying concepts. Although you could go the extra mile to fine-tune its parameters, I will not cover that in this article.</p>
<p>To recap, I tested the data aggregation performance for the following four items:</p>
<ol>
<li>Oracle DBMS;</li>
<li>the standalone operation of Hadoop;</li>
<li>the fully-distributed operation of Hadoop;</li>
<li>and the Map-Reduce of MongoDB.</li></ol>
<p>Out of the four contenders, <strong>the fully-distributed operation of Hadoop</strong> proved to be the winner for its speed and scalability.</p>
<h2>Selecting Aggregation Information Storage: MongoDB vs. Cassandra</h2>
<p>The test I have performed aimed to <strong>find the most efficient Map-Reduce alternative to replace the existing the Group by operation of RDBMS</strong>. Now it is time to select a storage to store, manage and provide the aggregation data. Oracle was eliminated from consideration from the start, because its scalability was limited.</p>
<p>I have chosen two test subjects, based on popularity. The first subject is <strong>Cassandra </strong>from Facebook, which is known for its column family form. According to an <a href="http://highscalability.com/blog/2011/3/22/facebooks-new-realtime-analytics-system-hbase-to-process-20.html" target="_self">article</a>,&nbsp;Facebook has developed an HBase-based real-time analysis system that can handle some 20 billion events a day. That means Facebook uses HBase as their Map-Reduce and storage. I wish I could benchmark HBase in my article.</p>
<p>The other test subject is <strong>MongoDB</strong>, which I paired with Hadoop for comparing the Map-Reduce performance. MongoDB is an intuitive document-oriented data model that offers flexibility in field management, one of the advantages of schema-free databases. In addition, MongoDB offers a <strong>full-text indexing </strong>feature, enabling a quick search against all fields in all documents or an indexing of a specific field. MongoDB has a reputation for good performance and reliability.</p>
<p>It is obvious that the read performance of Cassandra is inferior to that of MongoDB, as shown in the table below. Actually, there is a&nbsp;whole article written by my colleague from Storage System Development Team at NHN called <a href="http://blog.cubrid.org/dev-platform/nosql-benchmarking/" target="_self">NoSQL Benchmarking</a>. Refer to it for deeper results on performance comparison&nbsp;between Cassandra and MongoDB for both READ and WRITE.</p>
<p>After reviewing the code and related documents, I have concluded that the philosophical difference between the two solutions led to the difference in performance. Since MongoDB is a document-oriented model, it processes one row of the database with a single insert operation. On the other hand, Cassandra, a column-based model, processes one column of the database with a single insert operation. For this reason, Cassandra is slower than MongoDB. The data used by the test consists of 30 columns. I assumed that the performance would be different by about 30-fold. But the actual performance showed a difference of 300 times.</p>
<p>The following code shows that the insert operation must be repeated as many times as the number of columns.</p>
<div style="BORDER-BOTTOM: #666666 1px dotted; BORDER-LEFT: #22aaee 5px solid; PADDING-BOTTOM: 5px; PADDING-LEFT: 5px; PADDING-RIGHT: 5px; BACKGROUND: url(modules/editor/components/code_highlighter/code.png) #fafafa no-repeat right top; BORDER-TOP: #666666 1px dotted; BORDER-RIGHT: #666666 1px dotted; PADDING-TOP: 5px" editor_component="code_highlighter" nocontrols="false" nogutter="false" collapse="false" first_line="1" description="" file_path="" code_type="Java">
<p>ColumnPath columnPath1 = new ColumnPath(columnFamily);<br />columnPath1.setColumn(columnName1.getBytes());<br />client.insert("Keyspace1", key, columnPath1, columnValue1.getBytes(),timestamp, ConsistencyLevel.ONE);<br />&lt;omitted&gt;<br />ColumnPath columnPathN = new ColumnPath(columnFamily);<br />columnPathN.setColumn(columnNameN.getBytes());<br />client.insert("Keyspace1", key, columnPathN, columnValueN.getBytes(), timestamp, ConsistencyLevel.ONE);</p></div>
<p>To confirm that the column-based insert operation caused the bad write performance, we have reduced the number of columns in the test. By combining the other columns except for key, we reduced the number of columns to two. As shown in Table 3, the 100,000 write operation performance of Cassandra was significantly faster when the number of columns was two than when it was 30. However, it could not still surpass the write performance of MongoDB.</p>
<h3>Table 3 Comparison of Write/Read Performance of MongoDB vs. Cassandra</h3>
<table class="blackcap rowbg">
<thead>
<tr>
<td>Test Classification</td>
<td>Criteria</td>
<td>MongoDB</td>
<td>Cassandra (30 columns)</td>
<td>Cassandra (2 columns)</td></tr></thead>
<tbody>
<tr>
<td>Write</td>
<td>100,000</td>
<td>3.551</td>
<td>1057.437 seconds</td>
<td>32.980 seconds</td></tr>
<tr>
<td>Read All</td>
<td>100,000</td>
<td>54.362</td>
<td rowspan="2" colspan="2">Not measurable (no response after waiting for 1 hour)</td></tr>
<tr>
<td>Random Read</td>
<td>Searched</td>
<td>1.162</td></tr>
<tr>
<td>CPU</td>
<td>3%</td>
<td>20%</td>
<td>15%</td></tr></tbody></table>
<p>For reference, the schema structure used for Cassandra performance test is as shown in the following figure. We have freely configured the columns in order to include all aggregation information related to one user (in the unit of user_id). Designing it as a hierarchical structure made it easy to add data items to each layer. It allowed a variable schema design, which we thought would be a benefit. However, the test result showed poor performance, so we had to discard it.</p>
<p align="center"><img style="VERTICAL-ALIGN: middle" alt="Cassandra Schema" src="http://www.cubrid.org/files/attach/images/220547/206/242/cassandra-schema.png" width="522" height="222" editor_component="image_link"/></p>
<p align="center"><strong>Figure 5: Cassandra Schema.</strong></p>
<p>When the fully-distributed operation was provided by Cassandra, the read performance of the same key will be better than it is now. However, the test considering N nodes was excluded from the scope of this test due to our internal situation. Therefore, for consistency in comparison, we have configured MongoDB as a standalone operation.</p>
<p>For reference, MongoDB supports write-ahead journaling from version 1.7.5 for recovery from errors and durability of the storage engine. If this journaling option is used, the stability will improve, but the performance measurement result of MongoDB will get worse. Therefore, this option has been excluded from the test scope, as the aggregate data allows easy recovery.</p>
<p>Separately from the above test result, there was another important reason why we have selected MongoDB; <strong>it provides the composite index function</strong>. To utilize various inquiry conditions for aggregate data, we needed to set multiple indexes. MongoDB can create indexes for data of one million cases in just one second. In addition, users familiar with the relational database can more easily access the solution, since it is conceptually similar to SQL. On the other hand, to use Cassandra, users must understand the key-value based tree structure.<br />Based on the performance test of MongoDB and Cassandra, we selected MongoDB by considering the batch write performance and performance of reading various columns. The write/read performance test was carried out based on standalone operation; however, the final configuration of MongoDB was determined as five servers as shown in the following figure.</p>
<p align="center"><img style="VERTICAL-ALIGN: middle" id="mongodb-cluster-configuration" alt="MongoDB Cluster Configuration" src="http://www.cubrid.org/files/attach/images/220547/206/242/mongodb-cluster-configuration.png" width="557" height="270" editor_component="image_link"/></p>
<p align="center"><strong>Figure 6: MongoDB Cluster Configuration.</strong></p>
<p>We underwent two trials configuring as shown above. First, we configured the cluster with four mongod config servers, excluding one arbiter server, but the cluster did not operate. The configuration document specified "one or three servers must be used to configure a cluster," but we missed that point. In addition, when the Shard configuration across several servers is incorrect and there is a network failure, data integrity may not be kept. To solve the problem, an additional arbiter server (cbat005 in the figure) must be configured.</p>
<h2>Final Hadoop &amp; MongoDB Based Aggregation System</h2>
<p>The following figure shows the final configuration of the system. The system may be configured with the Hadoop server and MongoDB in the standalone operation. However, we configured it to enable easy expansion, as the data volume is continuously increasing. Data flows in the order of Oracle, ETL, Hadoop, and MongoDB.</p>
<p align="center"><img style="VERTICAL-ALIGN: middle" alt="System Configuration" src="http://www.cubrid.org/files/attach/images/220547/206/242/system-configuration.png" width="560" height="236" editor_component="image_link"/></p>
<p align="center"><strong>Figure 7: System Configuration.</strong></p>
<p>The operation scenario of the above configuration is illustrated as shown below.</p>
<ol>
<li>Select the target data to aggregate from the database.</li>
<li>Extract data by using ETL tool.</li>
<li>Balance and load the data to the HDFS DataNode of the Hadoop Cluster.</li>
<li>Execute Map-Reduce in the NameNode of the Hadoop Cluster.</li>
<li>The aggregation result is transferred and loaded to the MongoDB by using the transfer application. At this time, L4 is used for load balancing.</li>
<li>Data loaded onto the MongoDB is provided to users via the external modules.</li></ol>
<p>Among the above processes, a natural data flow is shown from the first process to the third process, but in the fourth process, aggregation is executed by using Map-Reduce. In the fifth, the aggregation result is saved through the API provided by the MongoDB. When MongoDB is accessed, it is recommended to distribute load through L4. In addition, the server list (mongos server list) may be described while writing clients. Or, it may be possible to use RequestBroker. When the first to the fifth processes are complete, the user can receive data. As a supplementary explanation of the process to store data in the MongoDB, the client server determines in which server Shard data will be stored through the config server. Data are stored in the master server of Shard and copied to the replication server. MongoDB specifies the arbiter in order to select the master server from among the remaining servers when there is any failed distributed server.</p>
<h2>Conclusion</h2>
<p>We have accomplished the first goal by configuring the system as described. We recommend you consider the following if you are planning to introduce a Map-Reduce or NoSQL solution.</p>
<p>If the data volume is not particularly high and Map-Reduce must be applied, configure the environment to Hadoop standalone operation. If the data volume is large, configure the fully-distributed operation consisting of at least three DataNodes. However, if you are using MongoDB and the data volume is not particularly high, MongoDB Map-Reduce will be useful.</p>
<p>For NoSQL, if multi-index is required, choose MongoDB. If there are many changes in data items and many unique accesses, Cassandra will be better. Since we have not yet tested Hbase, an additional review of that is also required.</p>
<p>After accomplishing the first goal, we are considering the second goal. We are trying to establish long-term measures that can effectively process the continuously increasing Oracle data. To solve the problem, we think that the log data for which coupling to the master data is low and inquiry frequency is also low must be moved to the NoSQL storage. If this problem can be solved using the NoSQL solution, we expect that we can reduce the costs of using relatively-expensive Oracle storage.</p>
<p>The NoSQL solution is being advanced according to various needs. The biggest advantage of the NoSQL solution that I have experienced is Scale-out. And the relatively-fast write/read performance is a bonus. However, there is no such thing as a free lunch; we can lose our precious time in development.</p>
<p>I wanted to share our NoSQL experience in the hope that it can be helpful for you. This is the first article I have posted on this site, so I'm concerned that my poor writing skills may not be sufficiently effective to convey our experience. I hope that more information on the NoSQL solution can be shared in the future. </p>
<p>By Jeong Hyun Lee, Web Service Development Team, NHN Corporation.</p>]]></description>
                        <pubDate>Mon, 28 Nov 2011 16:08:36 +0900</pubDate>
                        <category>NoSQL</category>
                        <category>Hadoop</category>
                        <category>MongoDB</category>
                        <category>Cassandra</category>
                        <category>NHN</category>
                                    <slash:comments>3</slash:comments>
                    </item>
        										        <item>
            <title>What is Nginx?</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/dev-platform/what-is-nginx/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/dev-platform/what-is-nginx/</guid>
                        <comments>http://www.cubrid.org/blog/dev-platform/what-is-nginx/#comment</comments>
                                    <description><![CDATA[<p>Apache which had been at the forefront of web revival is now giving its way to Nginx. Nginx is spreading at a fast pace worldwide, and at <a title="NHN - CUBRID Blog" href="http://blog.cubrid.org/tags/nhn/">NHN</a> as well we have been replacing web servers by Nginx more and more.</p>

<p>Let’s look at what Nginx is and how it differs from Apache Web Server.</p>

<p>In the beginning of 21<sup>st</sup> century as the use of internet became more active, people began to shed more interest on web servers capable of processing more requests. Later the <a title="The C10K problem" href="http://www.kegel.com/c10k.html">C10k problem</a> emerged in this era, in other words to enable each web server to be capable of processing 10,000 clients at the same time. Therefore a need to develop a better Network I/O and Thread management technology was emerged. During this period, far less-developed technology was applied to Linux than previous ones such as <b>epoll</b> and <b>NPTL</b>.</p>

<blockquote><b>epoll</b> was designed for better process of IO events on Linux. kqueue (FreeBSD) and IOCP (Windows) are similar. <b>NPTL</b> is a thread library of Linux loaded on Kernel 206 and up (based on safe version). It provided enormous improvement in thread performance.</blockquote>

<p>It is fair to say that the emergence of several technology was not the result of an effort to tackle C10k problem (as a common problem) but "The C10k problem" succeeded in putting together efforts to enhance performance of network server development. As a result various web servers such as <b>Nginx</b>, <b>Lightpad</b> and <b>Cherokee</b> made with new technology were in the market.</p>

<a name="more"></a>
<p>Nginx was first developed by a Russian guy called Igor Sysoev in 2002. After two years in 2004 it made its debut in the forms of  HTTP server and reverse proxy/IMAP/POP3 server. To respond to C10k problem, Nginx adopted event-driven (asynchronous) structure which is not a conventional way (as in Apache) of processing single client in a single thread. Other than Nginx, various newly developed web servers such as Lightpad, Tornado, Magnum and Aleph have adopted Event-driven structure too.</p>

<h2>Event-driven Architecture (EDA)</h2>

<p>EDA method is capable of handling more number of clients with less threads compared to conventional way (one thread for one client). In Apache each thread is dedicated to handle one client. So, there will be many cases when a certain thread needs to be on hold due to I/O problems until certain data is read from persistence layer in "accept" and delivered to the client. There should be the same number of threads as that of clients.</p>

<p>However, with EDA a method enables event (i.e. when event needs to be created or response result is completed) to be processed every time it takes place by designating each state. In other words, with less thread (or even without any thread) CPU can be used more efficiently.</p>

<p>Nginx provides almost all the functions Apache web server does. For example:</p>

<ul>
  <li>handling of static files</li>
  <li>reverse proxy</li>
  <li>load balancing</li>
  <li>SSL support</li>
  <li>FastCGI</li>
  <li>Virtual Host</li>
  <li>FLV Streaming</li>
  <li>MP4 streaming</li>
  <li>Web page access authentication</li>
  <li>gzip</li>
  <li>URL Rewriting</li>
  <li>Custom Logging</li>
  <li>SSI</li>
  <li>WebDAV</li>
</ul>
<h2>Nginx Use</h2>

<p>According to a research done in April, 2011 by W3Techs.com, Nginx takes up 6.9% in web server market and is on a steady increase. The graph below shows the market share of Nginx in recent 1 year.</p>

<p><a href="http://blog.cubrid.org/wp-content/uploads/2011/09/nginx-usage.png"><img title="Usage of Nginx for Web sites, 18 Apr 2011, W3Techs.com" src="http://blog.cubrid.org/wp-content/uploads/2011/09/nginx-usage.png" width="500" height="281" editor_component="image_link"/></a></p>

<p>We can see that many websites process massive traffic using Nginx. Alexa.com is well known for releasing website ranking according to its traffic. The following list, released on April 18, 2011, illustrates websites from <a title="Top Sites by Alexa.com" href="http://www.alexa.com/topsites">Top 500</a> which use Nginx.</p>

<table class="blackcap rowbg">
<thead>
<tr>
<td width="45">Ranking</td>
<td width="253">Websites</td>
</tr>
</thead>
<tbody>
<tr>
<td width="45">10</td>
<td width="253">qq.com</td>
</tr>
<tr>
<td width="45">15</td>
<td width="253">Taobao.com</td>
</tr>
<tr>
<td width="45">19</td>
<td width="253">WordPress.com</td>
</tr>
<tr>
<td width="45">23</td>
<td width="253">Yandex.ru</td>
</tr>
<tr>
<td width="45">28</td>
<td width="253">163.com</td>
</tr>
<tr>
<td width="45">45</td>
<td width="253">Vkontakte.ru</td>
</tr>
<tr>
<td width="45">54</td>
<td width="253">Soso.com</td>
</tr>
<tr>
<td width="45">63</td>
<td width="253">Wordpress.org</td>
</tr>
<tr>
<td width="45">83</td>
<td width="253">Youporn.com</td>
</tr>
<tr>
<td width="45">109</td>
<td width="253">Twitpic.com</td>
</tr>
<tr>
<td width="45">116</td>
<td width="253">Imageshack.us</td>
</tr>
<tr>
<td width="45">133</td>
<td width="253">Badoo.com</td>
</tr>
<tr>
<td width="45">140</td>
<td width="253">Sourceforge.net</td>
</tr>
<tr>
<td width="45">206</td>
<td width="253">Scribd.com</td>
</tr>
<tr>
<td width="45">259</td>
<td width="253">Hulu.com</td>
</tr>
</tbody>
</table>

<h2>Characteristics of Nginx</h2>

<h3>Non-blocking  event-driven method</h3>

<p>The most notable characteristic of Nginx is that it uses non-blocking event-driven method. All the network connection operates in non-blocking way. Some socket interfaces return results immediately, while some are blocked in certain cases. <b>Socket()</b> and <b>setsockopt()</b> returns results without blocking, whereas <b>connect()</b>, <b>send()</b>, <b>recv()</b> and <b>close()</b> might experience some blocking in certain cases. Nginx calls above mentioned functions only after confirming there will be no lags. In order to prevent blocking, as for <b>connect()</b>, socket is changed in advance to non-blocking using <b>ioctl()</b>.</p>

<p>As for <b>send()</b> and <b>recv()</b>, <b>epoll</b> is used to confirm blocklessness. Codes for calling <b>send()</b> or <b>recv()</b> are composed in event-driven format. Each event is composed of a socket, a socket state and an operating function. Almost all of internal Nginx is operated in event-driven way since web server processes request from web browser through network.</p>

<h3>Single thread</h3>

<p>Nginx is operated by pre-set number of worker processes. Each process operates as a single thread. Also, the need for multi-thread is relatively low since with the use of Non-blocking event-driven allows a single worker process to handle requests by multiple clients.</p>

<h2>Advantage of Nginx</h2>

<h3>High Performance</h3>

<p>Generally Nginx is known to record higher performance than Apache. However, we cannot simply jump to conclusion in terms of better performance since it varies greatly according to workload. Below chart indicates a system function that is called to serve a single <em>favicon.ico</em> using starce. As you can see in the table below Apache called 31 system functions whereas Nginx called 16. Although the system function used here cannot accurately indicate the performance, we can still expect relative performance.</p>

<table class="blackcap rowbg">
<thead>
<tr>
<td width="121" valign="top" class="xe_selected_cell">System Function</td>
<td width="101" valign="top" class="xe_selected_cell">Apache</td>
<td width="83" valign="top" class="xe_selected_cell">Nginx</td>
</tr>
</thead>
<tbody>
<tr>
<td width="121" valign="top" class="xe_selected_cell">accept()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">close()</td>
<td width="101" valign="top" class="xe_selected_cell">2</td>
<td width="83" valign="top" class="xe_selected_cell">2</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">epoll_ctl()</td>
<td width="101" valign="top" class="xe_selected_cell">0</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">epoll_wait()</td>
<td width="101" valign="top" class="xe_selected_cell">0</td>
<td width="83" valign="top" class="xe_selected_cell">2</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">fcntl64()</td>
<td width="101" valign="top" class="xe_selected_cell">6</td>
<td width="83" valign="top" class="xe_selected_cell">0</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">fstat64()</td>
<td width="101" valign="top" class="xe_selected_cell">0</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">getsockname()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">0</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">gettimeofday()</td>
<td width="101" valign="top" class="xe_selected_cell">9</td>
<td width="83" valign="top" class="xe_selected_cell">2</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">ioctl()</td>
<td width="101" valign="top" class="xe_selected_cell">0</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">open()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">poll()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">0</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">read()</td>
<td width="101" valign="top" class="xe_selected_cell">3</td>
<td width="83" valign="top" class="xe_selected_cell">0</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">recv()</td>
<td width="101" valign="top" class="xe_selected_cell">0</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">sendfile64()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">setsockopt()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">0</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">shutdown()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">0</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">stat64()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">0</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">times()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">write()</td>
<td width="101" valign="top" class="xe_selected_cell">0</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">writev()</td>
<td width="101" valign="top" class="xe_selected_cell">1</td>
<td width="83" valign="top" class="xe_selected_cell">1</td>
</tr>
<tr>
<td width="121" valign="top" class="xe_selected_cell">Total</td>
<td width="101" valign="top" class="xe_selected_cell">31</td>
<td width="83" valign="top" class="xe_selected_cell">16</td>
</tr>
</tbody>
</table><div style="text-align: left;">

</div>
<h4 style="text-align: left;">Handling many clients with less process</h4><div style="text-align: left;">

</div><div style="text-align: left;">In case of Apache, one process or thread is needed to handle the one client, whereas Nginx only requires a little memory for the same work. Therefore, with the same amount of resource, Nginx is capable of supporting far more number of clients compared to Apache.</div>
<h3 style="text-align: left;">Disadvantage of Nginx</h3><div style="text-align: left;">

</div>
<h4 style="text-align: left;">Difficult to create module</h4><div style="text-align: left;">

</div><div style="text-align: left;">It is notorious that Nginx gives a hard time when creating modules. There is an interface called Apache Portable Runtime (APR) in Apache Web Server. The Module Creator of Apache Web Server creates a module after reading APR document using the necessary function. However with Nginx, there is no such function as APR, therefore the creator needs to find the function needed for creating the module within the internal code of Nginx.</div>
<h4 style="text-align: left;">Does not support HTTP/1.1 in communication with Backend</h4><div style="text-align: left;">

</div><div style="text-align: left;">HTTP/1.1 is supported for a communication between web browser and Nginx however only HTTP/1.0 is supported between Nginx and Backend server. Luckily, with a recent development of AJP module, it can now replace HTTP/1.0 for connecting Nginx and Tomcat.</div>
<h3 style="text-align: left;">Things to note while using Nginx</h3><div style="text-align: left;">

</div>
<ul><div style="text-align: left;">

</div>
  <li style="text-align: left;">Nginx has a non-blocking event-driven structure. Such structure is desirable for network transmission and reception. However, it could generate blocking when file is being sent and received. But the latest Linux versions support Asynchronous Input-Output (AIO), and Nginx began to support AIO since version 0.8.11.</li><div style="text-align: left;">

</div>
  <li style="text-align: left;">Nginx uses AIO function through <b>eventfd()</b> system function of Linux. However it only works when AIO of Linux is set as <b>DirectIO</b>. Thus, using AIO on Linux disables buffer cache of OS.</li><div style="text-align: left;">

</div>
  <li style="text-align: left;">As in the case of reading the same file over and over again, it reads from disk in the first place however from the second time it can rapidly read stored file on buffer cache. No matter how many times the file is being read, using DirectIO makes it to be read from disk consistently.</li><div style="text-align: left;">

</div>
  <li style="text-align: left;">If a DBMS uses independent buffer, DirectIO might be efficient. However in other cases DirectIO could decrease file input/output performance.</li><div style="text-align: left;">

</div>
  <li style="text-align: left;">If most of the files that Nginx read exist in OS buffer cache, most of file I/O become non-blocking. However if Nginx gets to serve files which do not existent in the buffer cache, the worker process becomes blocked due to file I/O. In this case, you need to increase the number of worker processes in order to prevent the worker process from becoming blocking.</li><div style="text-align: left;">

</div>
</ul><div style="text-align: left;">

</div><div style="text-align: left;">By Heum-geun Kang, Main Service Development Team, NHN Corporation.</div>]]></description>
                        <pubDate>Mon, 13 Feb 2012 11:57:50 +0900</pubDate>
                        <category>Nginx</category>
                        <category>Web Server</category>
                        <category>Apache</category>
                                    <slash:comments>6</slash:comments>
                    </item>
        										        <item>
            <title>New CUBRID 8.4.1 Beta is 70% faster</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/news/new-cubrid-8-4-1--is-70-faster/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/news/new-cubrid-8-4-1--is-70-faster/</guid>
                        <comments>http://www.cubrid.org/blog/news/new-cubrid-8-4-1--is-70-faster/#comment</comments>
                                    <description><![CDATA[<p>We have been waiting for this day for a long time! On behalf of CUBRID Development Lab I am very proud to announce the release of the new CUBRID 8.4.1 Beta which is 70% faster then the previous version!</p><p style="text-align: center;"><b>CUBRID 8.4.1 Beta is available for&nbsp;<a href="/?mid=downloads&amp;item=cubrid&amp;os=detect" target="_self">download</a>&nbsp;right now!</b></p><p>Thanks to all of those who have reported bugs, CUBRID&nbsp;developers have done really great job on improving both the performance and stability of the database server. While performing tests on large amount of transaction, performance of INSERT and UPDATE was improved over 70%.</p><p>Also, according to your requests we have added many new functions and SQL syntaxes to make CUBRID more compatible&nbsp;with MySQL. Moreover, regular expressions are now supported in conditional search, broker parameters are added, and monitoring features have been improved. In addition, approximately 50 major and minor bugs have been fixed.</p>

<p>Below I will list new features and major changes in this new release.</p>

<h3>Improved Performance of INSERT and UPDATE more than 70%</h3>

<p style="text-align: center;"><img src="/files/attach/images/220547/257/287/cubrid-insert-update-performance.png" alt="Improved Performance of INSERT and UPDATE up to 70%" width="727" height="235" editor_component="image_link" /></p><p style="text-align: center;">(<i>y-axis</i> refers to the number of queries per second)</p><p>In CUBRID 8.4.1 we have improved the internal implementation of the Engine to enhance the performance during simultaneous processing of transaction logs,
writing memory buffers to a disk, and performing replication for HA. Consequently, the performance of INSERT
and UPDATE operations was dramatically improved over 70% in comparison with 2008 R4.0 Patch 2 version.</p><p>The following table illustrates the overall performance increase gained in CUBRID 8.4.1.</p>

<table>
<thead>
<tr>
	<th></th>
	<th colspan="3">Throughput (ops/sec)</th>
	<th colspan="3">99th Percentile Latency (ms)</th>
</tr>
<tr>
	<th>Operations</th>
	<th>R4.0 P2</th>
	<th>R4.1</th>
	<th>Performance Ratio</th>
	<th>R4.0 P2</th>
	<th>R4.1</th>
	<th>Performance Ratio</th>
</tr>
</thead>
<tbody>
<tr><td>Insert</td><td>4085</td><td>7090</td><td>174%</td><td>33</td><td>11</td><td>167%</td></tr>
<tr><td>Select</td><td>24477</td><td>24739</td><td>101%</td><td>3</td><td>3</td><td>100%</td></tr>
<tr><td>Update</td><td>4556</td><td>8274</td><td>182%</td><td>28</td><td>13</td><td>154%</td></tr>
<tr><td>Mix</td><td>3929</td><td>4402</td><td>112%</td><td>223</td><td>218</td><td>102%</td></tr>
</tbody></table>

<p>The test has been conducted on large amount of transactions based on YCSB
(Yahoo Cloud Serving Benchmark). For more information on performance test, refer to&nbsp;section 2.2.2&nbsp;in&nbsp;<a href="ftp://ftp.cubrid.org/CUBRID_Docs/Release_Notes/CUBRID2008R4.1_QA_Completion_Report.pdf" target="_self">CUBRID 2008 R4.1 QA Completion Report</a>.</p>

<h3>New SQL Functions and Regular Expression Support</h3>

<p></p><ul><li>In this version we have added new SQL functions:&nbsp;<b>ADDTIME, ASCII, BIN, CONV, FIND_IN_SET, HEX</b>, and <b>SERIAL_NEXT_VALUE (serial_name, number)</b> functions, which can be used to obtain multiple serial values with a single call.</li><li>Added the <b>REGEXP</b> operator in order to allow conditions to be searched with regular expressions.</li><li>DATE, DATETIME, and TIMESTAMP data types now support '0000-00-00',&nbsp;'0000-00-00 00:00:00' lower bound values. This provides more compatibility with MySQL's SQL syntax.</li></ul><p></p>

<h3>More Features</h3><p>The full list of new features,&nbsp;improvements, and fixes can be found the in <a href="ftp://ftp.cubrid.org/CUBRID_Docs/Release_Notes/CUBRID2008R4.1_Release_Note_en.pdf" target="_self">CUBRID 2008 R4.1 Release Note</a>.</p>]]></description>
                        <pubDate>Wed, 01 Feb 2012 19:22:09 +0900</pubDate>
                        <category>New Release</category>
                        <category>New Features</category>
                                </item>
        										        <item>
            <title>phpMyEdit for CUBRID - Video Tutorial</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/cubrid-trainings-channel/phpmyedit-for-cubrid-video-tutorial/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/cubrid-trainings-channel/phpmyedit-for-cubrid-video-tutorial/</guid>
                        <comments>http://www.cubrid.org/blog/cubrid-trainings-channel/phpmyedit-for-cubrid-video-tutorial/#comment</comments>
                                    <description><![CDATA[<p>Here is one more video tutorial from <a title="CUBRID Trainings Channel" href="http://www.youtube.com/user/cubrid" target="_blank">CUBRID Trainings Channel</a>. The&nbsp;previous episodes&nbsp;introduced us the client GUI for CUBRID DBMS called <a title="CUBRID Manager - Video Tutorial" href="http://blog.cubrid.org/cubrid-manager/intro-to-cubrid-manager-by-cubrid-trainings-channel/" target="_self">CUBRID Manager</a>, and <a title="Uniform Server - CUBRID Video Tutorial" href="http://blog.cubrid.org/cubrid-trainings-channel/uniform-web-server-video-tutorial/" target="_self">Uniform Server</a>, a Windows-Apache-CUBRID-PHP software bundle. The current episode will&nbsp;introduce phpMyEdit customized for working with CUBRID DBMS. To dissolve the further misunderstanding about what phpMyEdit is used for, I would like to emphasize that it is not a database administration tool.</p>

<p>Simply put, phpMyEdit is an open source instant <strong>database table editing tool</strong>. It generates PHP code for you that you might need to display or make the necessary changes in the database tables through your web site interface. What you need is just copy the generated code and paste it into your web application's back-end code. You can customize it to fit your web site layout. It will make sure everything looks like as if you created this code yourself.</p>

<a name="more"></a>

<p>So this video will explain you what phpMyEdit is, how it works, and how to use it. You will learn how to use the code generated by phpMyEdit to&nbsp;do certain database operations. phpMyEdit&nbsp;includes a&nbsp;huge set of&nbsp;table manipulation functions (record&nbsp;addition, change, view, copy, and&nbsp;removal), table&nbsp;sorting, filtering, table&nbsp;lookups, and&nbsp;more.</p>

<p></p><p style="text-align: center;"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true"/><param name="allowscriptaccess" value="always"/><param name="src" value="http://www.youtube.com/v/PqDPo9tYSDM&amp;hl=en_US&amp;fs=1&amp;"/><param name="allowfullscreen" value="true"/><embed type="application/x-shockwave-flash" width="480" height="385" src="http://www.youtube.com/v/PqDPo9tYSDM&amp;hl=en_US&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"/></object></p>

<p>Fortunately, now phpMyEdit, a&nbsp;powerful database table editing tool, is available also for CUBRID. You can download it from CUBRID SF.net project site <a title="phpMyEdit for CUBRID" href="http://sourceforge.net/projects/cubrid/files/CUBRID-AppsTools/phpMyEdit/phpMyEdit-5.7.1-cubrid.zip/download" target="_blank">http://sourceforge.net/projects/cubrid/files/CUBRID-AppsTools/phpMyEdit/phpMyEdit-5.7.1-cubrid.zip/download</a>.</p>

<p>It&nbsp;will save you a great deal of your precious time when developing a PHP code which needs a database interactions.&nbsp;For more information, visit phpMyEdit Official Community Web Site at <a title="phpMyEdit Community site" href="http://www.phpmyedit.org/" target="_blank">http://www.phpmyedit.org/</a>.</p>

<p>Later we will be uploading more videos. If you want to be up to date and follow our video tutorials, subscribe to our&nbsp;<a title="Subscribe to CUBRID Blog" href="http://blog.cubrid.org/feed/" target="_self">CUBRID Blog</a> or&nbsp;<a title="CUBRID Trainings Channel" href="http://www.youtube.com/user/cubrid" target="_blank">CUBRID Trainings Channel</a>, follow us on&nbsp;<a title="CUBRID on Facebook" href="http://www.facebook.com/cubrid" target="_blank">Facebook</a> or&nbsp;<a title="CUBRID on Twitter" href="http://twitter.com/cubrid" target="_blank">Twitter</a>. &nbsp;We will make sure you get the latest news and updates about CUBRID.</p>]]></description>
                        <pubDate>Wed, 12 May 2010 10:43:01 +0900</pubDate>
                        <category>CUBRID</category>
                        <category>CUBRID Tools</category>
                        <category>CUBRID Trainings Channel</category>
                        <category>Training Videos</category>
                        <category>phpMyEdit</category>
                        <category>CUBRID Apps&amp;Tools</category>
                        <category>PHP</category>
                                </item>
        										        <item>
            <title>CUBRID ADO.NET Driver Stable 1.0 version has been released</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/cubrid-appstools/cubrid-ado-net-driver-stable-1-0-version/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/cubrid-appstools/cubrid-ado-net-driver-stable-1-0-version/</guid>
                        <comments>http://www.cubrid.org/blog/cubrid-appstools/cubrid-ado-net-driver-stable-1-0-version/#comment</comments>
                                    <description><![CDATA[<p style="text-align: center;"><img src="/files/attach/images/220547/135/263/dot-net-logo.png" alt="dot-net-logo.png" width="328" height="81" editor_component="image_link"/><br /></p><p>Last month we&nbsp;<a href="/blog/cubrid-appstools/official-ado-dot-net-driver-for-cubrid/" target="_self">announced</a>&nbsp;the first beta version of official ADO.NET driver for CUBRID. Today, we are happy to announce the stable <b>1.0</b> version release of the driver.</p><p></p><ul><li>The ADO.NET driver, developed by&nbsp;CUBRID&nbsp;community contributors, has now over 70 test scenarios.</li><li>The driver is released with 100% fully-managed code under the terms of <a href="/bsd_license" target="_self">BSD license</a>.</li><li>All main classes of ADO.NET model have been implemented.</li><li>Extended classes implementation (SchemaProvider, CommandBuilder, etc.).</li><li>It implements the (socket) communication protocol of the latest version of CUBRID 8.4.0.</li><li>Supports BLOB/CLOB data types and CUBRID Collections.</li><li>Localization support is built in. For now, only English messages are released. Feel free to contribute the translation of your own language.</li><li>Various source code, demos, examples (UI, VB.NET, NHibernate) are available on the&nbsp;<a href="/wiki_apis/entry/cubrid-ado-net-driver" target="_self">project Wiki page</a>.</li></ul><h3>Download</h3><p>You can download CUBRID ADO.NET driver from&nbsp;<a href="/?mid=downloads&amp;item=ado_dot_net_driver&amp;os=windows">http://www.cubrid.org/?mid=downloads&amp;item=ado_dot_net_driver&amp;os=windows</a>.</p><p>There are 3 ways you can install the driver.</p><p></p><ol><li>The easiest way is to use the&nbsp;<b>auto-installer</b>&nbsp;(available on the downloads page).</li><li>Download the compiled library.</li><li>Install from the source code.</li></ol><p></p><p>For detailed instructions of each installation method refer to&nbsp;<a href="/wiki_apis/entry/cubrid-ado-net-driver-installation-guide" target="_self">CUBRID ADO.NET Driver Installation Guide</a>&nbsp;and <a href="/wiki_apis/entry/cubrid-ado-net-tutorials" target="_self">ADO.NET Tutorials</a>.</p><p>The complete driver documentation is available at&nbsp;<a href="/manual/api/ado.net/1.0/Index.html">http://www.cubrid.org/manual/api/ado.net/1.0/Index.html</a>.</p><h3>Additional resources</h3><p></p><ul><li><a href="/wiki_apis/entry/cubrid-ado-net-driver-v1-0-release-note" target="_self">v1.0 Release Note</a></li><li><a href="/wiki_apis/entry/cubrid-ado-net-driver" target="_self">CUBRID ADO.NET Driver project page</a></li><li><a href="http://jira.cubrid.org/browse/APIS/component/10404" target="_self">Issue Tracker</a></li></ul><p></p><p></p>]]></description>
                        <pubDate>Mon, 16 Jan 2012 10:36:17 +0900</pubDate>
                        <category>ado.net</category>
                        <category>drivers</category>
                        <category>oledb</category>
                        <category>odbc</category>
                        <category>NHibernate</category>
                        <category>programming</category>
                                </item>
        										        <item>
            <title>Optimization and Distribution of Static Files on the Web Using Maven</title>
            <dc:creator>Young Eun Oh</dc:creator>
            <link>http://www.cubrid.org/blog/dev-platform/optimization-and-distribution-of-static-files-on-the-web-using-maven/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/dev-platform/optimization-and-distribution-of-static-files-on-the-web-using-maven/</guid>
                        <comments>http://www.cubrid.org/blog/dev-platform/optimization-and-distribution-of-static-files-on-the-web-using-maven/#comment</comments>
                                    <description><![CDATA[<p><img src="/files/attach/images/220547/895/263/maven-css-js.png" style="float:left;margin-right:10px" alt="maven-css-js.png" width="305" height="154" editor_component="image_link"/>The distribution of a Web application is as important as its development. Distribution methods can enhance the user experience or&nbsp;cause a failure. In this article, I will explain how we distribute static files at&nbsp;<b>Knowledge Shopping</b> Service department here at <a href="/blog/tags/NHN/" target="_self">NHN</a>.&nbsp;</p><h2>Difficulty of Distributing Static Files</h2><p>When static files such as the CSS and JavaScript are allowed to be cached on the client side by a browser, users can experience an increased speed and the server can be relieved from the burden of serving those resources. However, once the content of these static files changes,&nbsp;instead of using files stored in the cache,&nbsp;the browser must download the latest versions from the Web server. The most common method used to achieve this is by <b>adding a query string-type timestamp to the name of a static file</b> like <i>common.css?t=20110405</i>. The&nbsp;timestamp value used here can represent either the&nbsp;build time of the file, or the start time of the&nbsp;Web server,&nbsp;or the revision number of a repository. However, these solutions may cause some issues. I will explain them below.</p><p style="text-align: center;"><img src="/files/attach/images/220547/895/263/server-before-after-distribution.png" alt="server-before-after-distribution.png" width="461" height="306" editor_component="image_link"/><br /></p><p style="text-align: center;"><b>Figure 1: Server Before and After Distribution.</b></p><h3>Inconsistent distribution</h3><p>For example, if a user accesses a Web page and obtains an HTML file from Server A (post-distribution) but CSS files used in this HTML files are served from Server B (pre-distribution), the user will end up using the new HTML file and the old CSS file, which may result in broken layout of the page or site malfunction.</p><p></p><ol><li>To prevent this kind of problem, it is necessary to change the name of a newly distributed file making sure that the old HTML file refers to the old CSS file, and the new HTML file refers to the new CSS file.</li><li>If several Web servers are used for file distribution, the static files may be distributed in advance to prevent CSS or JavaScript files from being distributed to only some of the servers.</li></ol><p></p><p>By using the method above, most problems that can occur while distributing static files can be prevented.</p><h3>Decreased Performance</h3><p>However, if the number of static files referred by a Web page is large, the performance may suffer.</p><p></p><ol><li>For instance, in case a file has not been cached on the client side, it must be downloaded whenever it is requested.</li><li>On the other hand, if a file has been cached, a "304 Not Modified" will be received whenever a user accesses the server, incurring a DNS resolve cost and a socket connection cost.</li><li>Even when you merge the static files to reduce their number, unnecessary blanks and long variable names tend to increase the size of the transferable data.</li><li>More than that, the size of the transferrable data will grow when static files are distributed to the Web server, as cookies included in an HTTP request message will be transferred as well.</li></ol><p></p><h3>Proposed Solution</h3><p>Though it would seem tempting to have a single person manage all of the static files written during the development process, it often proves inefficient due to an increased management cost. Therefore, <b>the distribution process must be automated to the greatest extent possible</b>, and the following rules must be kept for the automatic and efficient distribution of static files.</p><p></p><ol><li>Add the timestamp value to the query string.</li><li>Manage the versions of CSS JavaScript files.</li><li>Reduce the number of files.</li><li>Minify file content.</li><li>Distribute CSS and JavaScript files from a cookie free domain.</li></ol><p></p><h2>Optimization by Using Apache Web Server Configuration</h2><p></p><ol><li>Compress the static files using the <b>deflate module</b> of the Apache Web server and transfer the compressed file. Add the deflate module configuration to the Apache configuration file, as shown below:</li>
<div editor_component="code_highlighter" code_type="Plain" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p># Add the deflate module<br />LoadModule deflate_module modules/mod_deflate.so<br /><br /># Compression level<br />DeflateCompressionLevel 1<br /><br /># Set the compression level based on MIME type<br />AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml text/javascript<br /><br /># Add the MIME type&nbsp;<br />AddType text/javascript .js<br />AddType text/css .css</p></div><br />
<li>Then, add the <b>expire module</b> to allow the browser to cache the static file.</li>
<div editor_component="code_highlighter" code_type="Plain" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p># Add the expires module<br />LoadModule expires_module modules/mod_expires.so<br /><br />ExpiresActive On<br /><br /># Set the default expires to one year<br />ExpiresDefault "access plus 1 years"</p></div>
</ol>

<h2>HOW TO manage static files</h2><p>Assume that JavaScript files are located in <b>/web/js</b> directory and <b>main.js</b>&nbsp;and <b>detail.js</b> files referred in a Web page are located in that&nbsp;<b>/web/js</b> directory.</p><p style="text-align: center;"><img src="/files/attach/images/220547/895/263/directory-structure.png" alt="directory-structure.png" width="199" height="164" editor_component="image_link"/><br /></p><p style="text-align: center;"><b>Figure 2: Directory Structure.</b></p><blockquote class="q1"><p>For an easy version control, mark each JavaScript file with its version (ex: main_v1.js, detail_v1.js).</p></blockquote><h3>How can I add a JavaScript file without describing the version and timestamp on each Web page?</h3><p></p><p></p>When a Web application is loaded...<br /><ol><li>...&nbsp;<b>scan the subdirectory files</b> including /web/js;</li><li>and <b>create a list of files</b> with the highest version;</li><li>then <b>mark the file path</b> by using the custom tag as shown below:<br /><div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;">&lt;link:js prefix="/js/main.js"/&gt;</div></li></ol><p>The following code will be displayed in the HTML:</p><p></p><div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;">&lt;script type="text/javascript" src="/js/main_v1.js?t=2011040512"&gt;&lt;/script&gt;</div><p></p><p>To add new content or modify the existing one that does not support backward compatibility, get a higher version (ex: main_v1.js &nbsp;main_v2.js). The script will load the latest version.</p><h3>What are the potential issues which can arise when using this solution?</h3><p>If static files have been distributed in advance, all Web servers will have both <i>main_v1.js</i> file and <i>main_v2.js</i> file. Therefore, no problem would occur during the distribution.</p><p>On the Web server <i>after distribution</i>, a new Web page will be linked to a new JavaScript file (main_v2.js), and on the Web server <i>before distribution</i>, the existing Web page will be linked to the existing JavaScript file (main_v1.js).</p><h3>During the Web page development process, the development versions of static files are used (external URL). What should I do in this case?</h3><p>Modify the custom tag to describe the development URL like:</p><p></p><div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;">&lt;link:js prefix="/js/main.js" devOnlyUrl="http://svn.nhndesign.com/service/main_20110404.js" /&gt;</div><p></p><p>While developing the Web application, use <b>devOnlyUrl</b>. After completing the development, use the highest version of the main.js file. Of course, there should be a way to set the development status of the file.</p><h3>If a CSS or a JavaScript file is provided from a domain that does not use cookies, will there be any problem?</h3><p>If a user-defined cookie is used in the JavaScript file, that file must exist in the path within the Web server. To achieve this, an additional setting such as <b>needCookie</b> is required in the custom page.</p><p></p><div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;">&lt;link:js prefix="/js/cookie.js" needCookie="true" /&gt;</div><p></p><h2>HOW TO merge static files</h2><p>So far, I have described how to manage static file versions and how to describe files being developed. Now, I will explain how to bind the main.js file and the detail.js file to one core.js file to reuse their number. Write the configuration file as shown below:</p><p></p><div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />&lt;compression&gt;<br />&nbsp; &nbsp; &lt;file target="/js/core.js"&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;include&gt;/js/main&lt;/include&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;include&gt;/js/detail&lt;/include&gt;<br />&nbsp; &nbsp; &lt;/file&gt;<br />&lt;/compression&gt;</p></div><p></p><p></p><h3>How do I manage the versions of the created files?</h3><p></p><ol><li>If you have bound <i>main_v1.js</i>&nbsp;and&nbsp;<i>detail_v1.js</i> files to create one <b>core_v1.js</b> file, and there is no change in those files, keep the file name as '<b>core_v1.js</b>'.</li><li>When the content or the version of the main_v1.js or the detail_v1.js file is changed, the core_v1.js file must be changed to the core_v2.js file. To do this, you must manage the name, size, and checksum of each file that is part of the file to be created.</li></ol><p></p><p></p><div editor_component="code_highlighter" code_type="Plain" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>version=1<br />encoding=UTF-8<br />file./js/main_v1.js=945,UTF-8,ac3fecacd0a6ecf74a0c711180582a8c<br />file./js/detail_v1.js=22572,UTF-8,ee2565f0938bfd1baa21c73afa633c81</p></div><p>Now, you should minify the bound files. There are a lot of libraries related to optimization, but I will use the most popular one, <b>YUI Compressor</b>.</p><h3>When should I create or optimize the files? At runtime or at build time?</h3><p>To provide static files from CDN (Content Delivery Network) or a separate server, I recommend creating or minifying the file at build time. I have implemented a file creation and minification function as a Maven plug-in for that specific purpose. The following code is an example of the pom.xml file:</p><p></p><div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>&lt;build&gt;<br />&nbsp; &lt;plugins&gt;<br />&nbsp; &nbsp; &lt;plugin&gt;<br />&nbsp; &nbsp; &nbsp; &lt;groupId&gt;com.naver.shopping.maven&lt;/groupId&gt;<br />&nbsp; &nbsp; &nbsp; &lt;artifactId&gt;maven-compress-plugin&lt;/artifactId&gt;<br />&nbsp; &nbsp; &nbsp; &lt;version&gt;1.0.12&lt;/version&gt;<br />&nbsp; &nbsp; &nbsp; &lt;configuration&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;webDirectory&gt;web&lt;/webDirectory&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;fileEncoding&gt;UTF-8&lt;/fileEncoding&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;configLocation&gt;web/WEB-INF/compression.xml&lt;/configLocation&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;repository&gt;http://xxx.shopping.naver.net/static/&lt;/repository&gt;<br />&nbsp; &nbsp; &nbsp; &lt;/configuration&gt;<br />&nbsp; &nbsp; &lt;/plugin&gt;<br />&nbsp; &lt;/plugins&gt;<br />&lt;/build&gt;</p></div><p></p><p></p><h2>Distribution with BDS</h2><p>NHN distributes Web applications using its in-house developed Build Distribution System (BDS). The following figure illustrates the existing deployment process in a simple manner.</p><p style="text-align: center;"><img src="/files/attach/images/220547/895/263/deployment-with-bds.png" alt="deployment-with-bds.png" width="654" height="278" editor_component="image_link"/>&nbsp;</p><p style="text-align: center;"><b>Figure 3: Deployment with BDS.</b></p><p>The following figure shows the process of CSS and JavaScript file compression and the existing deployment process.</p><p style="text-align: center;"><img src="/files/attach/images/220547/895/263/deployment-minifying-css-javaScript-file.png" alt="deployment-minifying-css-javaScript-file.png" width="650" height="395" editor_component="image_link"/>&nbsp;</p><p style="text-align: center;"><b>Figure 4: Deployment for Minifying CSS and JavaScript File.</b></p><p></p><ol><li><b>Compressed file creation</b>: When you build a Web application using Maven, create a compressed file by reading the compression.xml file.</li><li><b>Version file creation</b>: By using the information described in the compression.xml file, create a version file and save it in the version file repository (the repository described in the pom.xml file).</li><li><b>CSS and JavaScript file copy</b>: By using the PostScript function of BDS, copy the CSS file and the JavaScript file to the CDN or the cookie free domain server.</li></ol><p></p><h2>How to Configure and Use</h2><p></p><ol><li>Create a <b>compression.xml</b> file and save it in the web/WEB-INF directory.</li><li>For Web projects that use Lucy, set the Lucy plug-in as shown below:</li>
<div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>&lt;lucy:plug-in name="compress" class="com.naver.shopping.common.compress.web.CompressPlugIn"&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;lucy:param name="configLocation" value="/WEB-INF/compression.xml"/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&lt;lucy:param name="devOnly" value="false"/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &lt;lucy:param name="baseUrl" value="http://static.shopping.naver.net/f"/&gt;<br />&lt;/lucy:plug-in&gt;</p></div>
<p>For Spring MVC-based Web projects, register Bean as shown below:</p>
<div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; ">&lt;bean class="com.naver.shopping.common.compress.web.CompressBean"&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="configLocation" value="/WEB-INF/compression.xml"/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="devOnly" value="false"/&gt;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;property name="baseUrl" value="http://static.shopping.naver.net/f"/&gt;<br />&lt;/bean&gt;</p></div><br />
<li>Add the Maven plug-in settings to the pom.xml file.</li><li>Describe the following in the jsp file:</li>
<div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>&lt;link:js prefix="/js/lib.js"/&gt;<br />&lt;link:js prefix="/js/ac.js" needCookie="true"/&gt;<br />&lt;link:js prefix="/js/notexists.js"/&gt;</p></div></ol><p></p><p></p><p>What I have described in the above steps will result in the following. Among the static files, the JavaScript file that requires cookies is served from the Web server itself, and the CSS file and the JavaScript file that does not require cookies are served from the cookie free domain or the CDN.</p><p></p><div editor_component="code_highlighter" code_type="Xml" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>&lt;script type="text/javascript" src="http://static.shopping.naver.net/f/js/ lib_v1.js"&gt;&lt;/script&gt;<br />&lt;script type="text/javascript" src="/js/ac_v1.js"&gt;&lt;/script&gt;<br />&lt;script type="text/javascript" src="http://static.shopping.naver.net/f/js/ notexists_v2.js?t=2011040512"&gt;&lt;/script&gt;</p></div><p></p><p></p><p>The <b>/js/notexists.js</b> file is not defined in the compression.xml file. In this case, the file is returned with the file name and timestamp of the highest version that starts with notexists under the /js directory.</p><h2>Conclusion</h2><p>In this article, I have briefly explained how we distribute and deploy static files at <b>Knowledge Shopping</b> service department here at NHN. The method I have described is not new. But I am making, what used to be an insider-only tip, public so that more people are aware of a better way to distribute static files and share their thoughts.</p><p>I would be really glad if you shared in the comments below how you distribute static files. Perhaps there are better ways to do this.</p><p>By Young-eun Oh, Shopping Service Development Team, NHN Corporation.</p><p></p><p>


</p>]]></description>
                        <pubDate>Wed, 18 Jan 2012 11:54:09 +0900</pubDate>
                        <category>Web development</category>
                        <category>JavaScript</category>
                        <category>CSS</category>
                        <category>Optimization</category>
                        <category>Static File Distribution</category>
                        <category>Maven</category>
                        <category>NHN</category>
                        <category>Web</category>
                                </item>
        										        <item>
            <title>CUBRID Perl Driver 8.4.0 Stable is now available</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/cubrid-appstools/cubrid-perl-driver-8-4-0-stable-is-now-available/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/cubrid-appstools/cubrid-perl-driver-8-4-0-stable-is-now-available/</guid>
                        <comments>http://www.cubrid.org/blog/cubrid-appstools/cubrid-perl-driver-8-4-0-stable-is-now-available/#comment</comments>
                                    <description><![CDATA[<p><img src="/files/attach/images/220547/279/266/perl-logo.png" alt="CUBRID Perl Driver" style="float:left;margin-right:10px" width="98" height="120" editor_component="image_link"/>On behalf of CUBRID API development team I am proud to announce the first official stable 8.4.0 release of <a href="/wiki_apis/entry/cubrid-perl-driver" target="_self">Perl Driver for CUBRID</a>.</p><p>The driver supports all Perl::DBI methods, including:</p><p></p><ul style="padding-left:124px"><li>Driver handlers</li><li>Database handlers</li><li>Statement handlers</li><li>Statement handler attributes</li><li>LOB data manipulation methods</li></ul><p></p><p>The full list of available functions and latest changes can be found in <a href="/wiki_apis/entry/cubrid-perl-driver-8-4-0-release-note" target="_self">Release Notes</a>.</p><p>The Perl driver for CUBRID is available from CPAN and can be installed using the following commands in the terminal:</p><p></p><div editor_component="code_highlighter" code_type="Bash" file_path="" description="" first_line="1" collapse="false" nogutter="false" nocontrols="false" style="border: #666666 1px dotted; border-left: #22aaee 5px solid; padding: 5px; background: #FAFAFA url(/modules/editor/components/code_highlighter/code.png) no-repeat top right;"><p>cpan<br />install DBD::cubrid</p></div><p></p><p></p><p>For more details see <a href="/wiki_apis/entry/cubrid-perl-driver-build-guide" target="_self">Installation Instructions</a>.</p><p>The source code of CUBRID Perl driver is available at&nbsp;<a href="/?mid=downloads&amp;item=perl_driver&amp;os=detect">http://www.cubrid.org/?mid=downloads&amp;item=perl_driver&amp;os=detect</a>&nbsp;under the terms of BSD open source license.</p><h3>Additional resources</h3><p></p><ul><li><a href="/wiki_apis/entry/cubrid-perl-driver-8-4-0-release-note" target="_self">8.4.0 Release Note</a></li><li><a href="/wiki_apis/entry/cubrid-perl-driver-development" target="_self">Development Notes</a></li><li><a href="/wiki_apis/entry/cubrid-perl-driver" target="_self">CUBRID Perl driver project page</a></li><li><a href="http://jira.cubrid.org/browse/APIS/component/10326" target="_self">JIRA Issue Tracker</a></li><li><a href="/questions" target="_self">Questions and Answers</a></li></ul><p></p><p>


</p>]]></description>
                        <pubDate>Wed, 25 Jan 2012 12:10:54 +0900</pubDate>
                        <category>Perl</category>
                        <category>drivers</category>
                        <category>programming</category>
                                    <slash:comments>2</slash:comments>
                    </item>
        										        <item>
            <title>Will the use of SSD increase the speed of DBMS?</title>
            <dc:creator>Ki Yeul Lee</dc:creator>
            <link>http://www.cubrid.org/blog/dev-platform/will-the-use-of-ssd-increase-the-speed-of-dbms/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/dev-platform/will-the-use-of-ssd-increase-the-speed-of-dbms/</guid>
                        <comments>http://www.cubrid.org/blog/dev-platform/will-the-use-of-ssd-increase-the-speed-of-dbms/#comment</comments>
                                    <description><![CDATA[<p></p><p>SSD is faster than HDD.&nbsp;Then, <b>would it be better to switch the storage medium from HDD to SSD?&nbsp;</b>Let's learn about the <b>DBMS buffering</b> first, before considering the switch.&nbsp;</p><h3>Data Buffering</h3><p>SSD has faster reading/writing speed than HDD. So replacing HDD with SDD will speed up the performance of a number of programs, including the OS. <b>The performance improvement in the DBMS by replacing the storage medium from HDD to SSD, however, is minimal to none.</b></p><p>This is because data buffering (page buffering) is used in the DBMS. <b>Data buffering</b> is a sort of caching, and can decrease the storage medium I/O. In an environment where data buffering is running efficiently (i.e. the <b>hit ratio</b> is high for the caching system), the I/O performance of the storage medium become relatively less important.</p><p>So, if you want to improve the performance by switching from HDD to SSD, you should check if the DBMS' data buffering is operating properly before making the decision. <b>You may get the improvements you wanted just by data buffering and without switching the storage medium to SSD.</b></p><p>In this article, we will look at the data buffering efficiency in both HDD and SSD environment and how the TPS changes accordingly, to find out the efficient way to configure the data buffering size and the best way to select the storage medium.&nbsp;</p><h2>HDD Structure and IO Features</h2><p>HDD records data on a revolving platter (magnetic disc). HDD is composed of several platters, which all revolve together instead of revolving independently from one another. As you can see from Figure 1 below, the concentric circle in the middle of the platter is called a <b>track</b>, and the track found in the same location as several platters (same track number) is called a <b>cylinder</b>. The head reads and writes magnetic data on the platter, and since data can be recorded on both sides of the platter, <b>each platter has two heads</b>. This head is attached to the end of the disc arm.&nbsp;</p><p style="text-align: center;"><img src="/files/attach/images/220547/470/269/hdd-cylinder-heads.png" alt="Figure 1:  HDD's Track/Cylinder, Sector and Heads." width="258" height="275" editor_component="image_link"/><br /></p><p style="text-align: center;"><b>Figure 1: &nbsp;HDD's Track/Cylinder, Sector and Heads.</b></p><p>Data is recorded by block in a consecutive order on the cylinder of the rapidly spinning platter. This allows easy access to the consecutively recorded data with a single movement (platter rotation and disc arm movement).</p><p style="text-align: center;"><img src="/files/attach/images/220547/470/269/inside-hdd.png" alt="Figure 2:  Inside the HDD." width="300" height="214" editor_component="image_link"/><br /></p><p style="text-align: center;"><b>Figure 2: &nbsp;Inside the HDD.</b></p><p>So, the <b>IO time for a HDD</b> refers to the total "<b>seek time</b> where the disc arm moves to the relevant cylinder," "<b>rational latency</b> where the platter rotates until it reached the relevant block (sector)" and "<b>data transfer time</b> where the head reads or writes data."&nbsp;</p><p>As the seek time and rational latency are much higher than data transfer time (<i>seek time &gt;&gt; rational latency &gt; data transfer time</i>), the OS generally uses the optimized IO scheduling type, which minimizes the head movement and the platter rotation.</p><p>However, IO scheduling effects cannot always be counted upon because the application's IO request for OS is very frequent and the OS cannot predict the timing.</p><blockquote class="q1"><p>When creating an application, make sure that it requests a small number of large-volume read/write operations rather than frequently requesting a large number of small-volume read/write operations. Doing so can increase the system performance by allowing an effective IO scheduling at the OS level.</p></blockquote><p><b>CUBRID lumps disc IOs by page</b>. In addition, IO requests that do not affect response time are internally sorted and processed by their page numbers so that the OS could minimize the seek time and rational latency for a faster scheduling. The difference in performance depends on whether to apply this or not.</p><p>In HDD, time for the head to read and write data is relatively very short. Because of this, when it comes to improving disc IO performance, shortening seek time and rational latency becomes crucial. Sometimes the sequential writing shows better performance than SSD.</p><h2>The Solid State Disk Structure and IO Features</h2><p>Solid State Disk (SSD) is a disc that uses flash memory as the storage medium. Flash memory is a type of EEPROM that can read, write or erase the memory content electronically.</p><p style="text-align: center;"><img src="/files/attach/images/220547/470/269/inside-ssd.png" alt="Figure 3:  Inside the SSD." width="200" height="146" editor_component="image_link"/><br /></p><p style="text-align: center;"><b>Figure 3: &nbsp;Inside the SSD.</b></p><p>When the memory is initialized, all bits are set to 1, whereas certain bits can be changed to 0 if programmed by page. Though the programmed pages can be reprogrammed, changing the bit from 0 to one is impossible while changing from 1 to 0 is possible.&nbsp;</p><p>Because of this, in order to be used globally, you must erase and initialize all bits in a specific area to 1 before any data can be recorded again in same area.&nbsp;</p><p>For HDD, it takes about the same time for the head to read and write data, but SSD has different reading and writing performance. Though this varies with each product, if the page reading time is about a few hundred nanoseconds (ns), the writing time is in microseconds (us) and erasing time is in milliseconds (ms).</p><p>Erasing an area happens simultaneously, and it usually takes the same amount of time to erase the entire chip or just a few pages. So, it is usually organized to process erase by sector (or block), which is the collection of several pages.</p><p>For a flash memory, there is a limit on how many times a certain sector can be erased. (The limit is usually about tens of thousands to hundreds of thousands.) Because of this, physical block addresses are mapped differently from logical block addresses so that there will be no frequent renewals in certain areas like FAT, and the number of erasing is set evenly in each sector. This process is called <b>wear leveling</b>. &nbsp;</p><p>An additional effect of wear leveling is that, if the content of a certain page needs to be moved, the erasing and writing tasks need to be processed, but if the content needs to be moved to, and written in a different physical location (and if that page has been erased already), then writing can be performed without erasing. However, if empty spaces cannot be secured at the right time, this may also reach its limit.</p><p>For these reasons, IO of SSD is very different from HDD. When reading, as SSD only requires data transfer time, unlike HDD which also requires seek time and rational latency, a constant response speed can be guaranteed even for random reading.</p><p>But when writing, if there is no empty spaces in the middle of wear leveling, then it will be erased by sector while IO tasks for the corresponding sector will be all put on hold.&nbsp;</p><h2>DBMS - Data Buffering</h2><p>The data buffering of DBMS is a type of caching. As the memory is fast and the disk is much slower in comparison, and recently and frequently used data may be used more often for a certain period of time in the future, frequently used data are stored to be read from the memory instead of the disk.</p><p>Buffering from DBMS can be processed with consideration of the transactions, which is different from disc cache of the OS. Additionally, though it was built based on <a href="http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used" target="_self">LRU Caching Algorithm</a>, by separating hot zone and cold zone, LRU management cost is cut down dramatically.</p><p>The overall processing time for an IO request from DBMS can be explained as the followings.</p><blockquote class="q5"><p>total access time = A * HR + B * (1 - HR)</p><p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;A = Access time of memory<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;B = Average access time of storage<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;HR = Biffer Hit Ratio</p></blockquote><p>Therefore, the difference of processing time of HDD and SSD, B * (1-HR), will decrease as the hit ratio gets bigger. Common DBMSs have a hit ratio of 95% or higher.&nbsp;</p><h2>Test Environment and Scenario</h2><p>This is the specifications of the DBMS server used for our tests:</p><p></p><ul><li>CPU: Xeon® CPU L5650 (2.27GHz 2*6 cores)</li><li>Memory: 16G bytes</li><li>HDD: 300G * 2</li><li>SSD: 64G * 4</li><li>OS: CentOS 5.3 x86_64</li><li>DBMS: CUBRID 2008 R4.1 (8.4.1.0516) (64bit release build for linux_gnu)</li></ul><p></p><p>YCSB (Yahoo! Cloud Serving Benchmark) program,&nbsp;created by Yahoo to benchmark cloud service storages,&nbsp;was used as the load generator. You can set different query patterns or distributions for analysis. In this test, the latest distribution (modified zipfian distribution and a high density pattern) sends the select request to DBMS. 60 transactions were processed at the same time for this test.</p><p>We measured TPS, hit ratio and the number of IO requests processed per second, as we changed the storage medium from HDD to SSD in the same equipment, and the data buffer from 2G to 12G, 1G at a time.</p><h2>Test Results</h2><p>The below are the results from this test.</p><p></p><p style="text-align: center;margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; ">&nbsp;<img src="/files/attach/images/220547/470/269/tps-by-buffer-size.png" alt="Graph 1:  TPS Progress by Buffer Size." width="500" height="294" editor_component="image_link"/>
</p><p style="text-align: center;margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; "><b>Graph 1: &nbsp;TPS Progress by Buffer Size.</b></p><p></p><p>As the data buffer for DBMS is increased, the TPS is increased as well, for both SSD and HDD. As HDD is relatively slow, once the page buffer size is increased for HDD, the TPS is increased as well.&nbsp;</p><p>The graph for SSD demonstrates a simple proportional relationship outside of sections 2G - 4G in the middle.</p><p>On the other hand, the graph for HDD shows an S-shaped curve, with an inflection point around 10 G.</p><p>Graph 2 below is the collection of stat dumps from CUBRID, which shows the progress of IO requests made from DBMS to the OS.</p><p>The result of the IO request when using SSD shows an exponential function shape that simply decreases according to the buffer size. On the other hand, when using HDD, it shows a graph with an inflection point similar to the TPS graph, except that the inflection point is around 6G.</p><p style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; text-align: center; "><img src="/files/attach/images/220547/470/269/io-by-buffer-size.png" alt="io-by-buffer-size.png" width="500" height="304" editor_component="image_link"/><br /></p><p style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; text-align: center; "><b>Graph 2: IO request Progress by Buffer Size.</b></p><p>The hit ratio graph of the DBMS data buffer is as shown in Figure 3. As it was tested with the same distribution, SSD and HDD show the same shape. And though the hit ratio is the same, due to the difference in process speed, IO request shows a different shape, as in Graph 2.</p><p style="text-align: center;"><img src="/files/attach/images/220547/470/269/hit-ratio-by-buffer-size.png" alt="hit-ratio-by-buffer-size.png" width="541" height="272" editor_component="image_link"/><br /></p><p style="text-align: center;"><b>Graph 3: Hit Ratio Progress According to the Buffer Size.</b></p><p>The graph has the shape of an exponential function with its tangent at 100%, and its incline becomes more gradual as the buffer size increases.</p><h2>Result Analysis and Implications</h2><p>As the test results indicate, <b>the performance of DBMS is very sensitive to the hit ratio of the data buffer</b>.&nbsp;</p><p>Therefore, to improve the performance of DBMS, it is crucial for the data buffer to maintain an adequate hit ratio.</p><p>The data buffer should be configured to the appropriate size to include the main working set. Also, the DBMS schema and application pattern should be designed to compose the main working set.</p><p>If a good hit ratio cannot be maintained in this way, then consider switching to SSD to maintain the performance above a certain level.&nbsp;</p><p>Let's analyze this proposition in detail, using the test results.</p><p>The application used for the test was <b>zipfian distribution</b>, which is a model with a well-composed working set.</p><p>Now, the DBMS data buffer must be composed to adequately cover the working set. The graph for hit ratio changes by data buffer is the same shape as Graph 3.</p><p>The incline of the graph changes according to the distribution of the working set, but tends to have the same shape as Graph 3 (exponential function with 100% as the tangent). In this case, the buffer size and the cost are directly proportional, but the incline of the hit ratio decreases. Therefore, the data buffer's extension cost and performance ratio start to decrease.</p><p>So, 8G, where the graph's incline becomes more gradual, should be the right data buffer size.</p><p>Intuitively, the TPS can be predicted to be proportional with the hit ratio graph, but as you can see in Graph 1, it shows different patterns depending on the IO features of the storage medium.</p><p>As SSD "reads" fast, the TPS shows a gradual decline.</p><p>HDD, however, shows a pattern with an inflection point. In Graph 1, the areas in the square show that the performance ratio for SSD and HDD are proportional, but after that area, the TPS performance of HDD starts to decline steeply, and then declines gradually.</p><p>This phenomenon can be linked with the IO request development in Graph 2. The HDD is more than able to process the IO request that increases with the smaller hit ratio in section A (between 10 G~12 G). So the TPS graph above only shows the difference in physical performance compared to SSD.</p><p>But once the buffer size becomes equal to or smaller than 10 G (section B), HDD cannot process the increased IO requests within the set time and starts to stall. The slowdown in IO requests causes a steep decline in the TPS graph.</p><p>This would be the state in which the IO scheduling from the OS is not functioning well, as we have seen before.&nbsp;</p><p>On the other hand, as the data buffer grows smaller (section C), the number of processing IO requests starts to increase within the set time, which means the OS' IO scheduling is working efficiently as the accumulated IO requests increase. This causes the TPS drop to flatten. However, even when IO requests increase, the hit ratio decreases, and the overall TPS decreases as well.</p><p>Gathering all results, the hit ratio starts changing gradually around 8G, but TPS incline grows steeply and reaches the inflection point at 10G. Because of this, the data buffer's performance improvement compared to the cost is maximized around 8G - 10G.</p><p>So in such environment, it would be more efficient cost-wise to install the data buffer to around 10 G instead of changing the storage medium to SSD. &nbsp;</p><p></p><p>By Ki Yeul Lee, Senior Engineer, DBMS Development Lab, NHN Corporation.</p><p>


</p>]]></description>
                        <pubDate>Mon, 30 Jan 2012 13:08:57 +0900</pubDate>
                        <category>SSD</category>
                        <category>HDD</category>
                        <category>performance</category>
                        <category>DBMS</category>
                        <category>data buffering</category>
                        <category>buffer hit ratio</category>
                                </item>
        										        <item>
            <title>CUBRID vs. MySQL: SSD Performance Test Results</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/cubrid-comparison/cubrid-vs-mysql-ssd-performance-test-results/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/cubrid-comparison/cubrid-vs-mysql-ssd-performance-test-results/</guid>
                        <comments>http://www.cubrid.org/blog/cubrid-comparison/cubrid-vs-mysql-ssd-performance-test-results/#comment</comments>
                                    <description><![CDATA[<p></p><p style="text-align: left;"><a href="http://blog.cubrid.org/wp-content/uploads/2010/8-/TPS_change_web.png"><img title="TPS Change" src="http://blog.cubrid.org/wp-content/uploads/2010/8-/TPS_change_web.png" width="519" height="275" editor_component="image_link"/></a>Today CUBRID revealed its latest internal <a title="CUBRID vs. MySQL performance test results before and after the SSD usage" href="/ssd_performance_test" target="_blank">performance test results</a> conducted using the latest CUBRID 3.0 Beta and the latest MySQL 5.1.47 (innoDB) database servers. The results are quite surprising for both database systems.</p><p></p>

<p>In this experiment&nbsp;CUBRID and MySQL database systems are tested to reveal their performance results&nbsp;in two different situations:</p>

<p></p><ol>
	<li> when the databases run on the HDD (Hard Disk Drive) equipped server</li>
	<li>and, when the databases run on the SSD (Solid State Disk)&nbsp;equipped server</li>
</ol>
To run the test, each database system (CUBRID and MySQL) has been installed on two separate server machines: one equipped with the HDD, the other with the SSD. None of the databases were specifically tuned. The default settings were used for the test.&nbsp;The performance improvements in TPS (Transactions Per Second) have been constantly recorded throughout the experiment.<p></p>

<a name="more"></a>

<p>The test confirmed that TPS levels of CUBRID and MySQL database systems increase on SSD equipped machines. During the I/O Bound workload CUBRID had 4.2 times increase in TPS, while MySQL had 2.8 fold improvement.</p>

<p><strong>Follow the link below to read the full report</strong></p>

<p><a href="/ssd_performance_test">http://www.cubrid.org/ssd_performance_test</a></p>]]></description>
                        <pubDate>Sat, 21 Aug 2010 09:29:34 +0900</pubDate>
                        <category>MySQL</category>
                        <category>CUBRID</category>
                        <category>benchmark</category>
                        <category>CUBRID Comparison</category>
                        <category>performance</category>
                        <category>SSD</category>
                        <category>HDD</category>
                                </item>
        										        <item>
            <title>What&apos;s New in CUBRID Community</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/news/whats-new-in-cubrid-community/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/news/whats-new-in-cubrid-community/</guid>
                        <comments>http://www.cubrid.org/blog/news/whats-new-in-cubrid-community/#comment</comments>
                                    <description><![CDATA[<p>Greetings to everyone!</p>

<p>Today we have several good news we would like to share with all of you! Most of the times we post the latest activities of our community through&nbsp;<a title="Follow CUBRID on Twitter" href="http://twitter.com/cubrid" target="_blank">Twitter</a> and <a title="Become CUBRID Fan on Facebook" href="http://www.facebook.com/cubrid" target="_blank">Facebook</a>. So make sure you follow us. For the last two months there have been quite an impressive amount of work accomplished at CUBRID Community. We have pushed the <a title="Install CUBRID Connector for Ruby" href="http://rubygems.org/gems/cubrid" target="_blank">CUBRID gem</a> to RubyGems.org, updated our <a title="JDBC &amp; Java Programming with CUBRID" href="/cubrid_java_programming" target="_blank">tutorials for JDBC &amp; Java Programming</a>, released the <a title="Python Programming with CUBRID" href="/python_programming" target="_blank">Python Connector</a>, published <a title="PECL :: Package :: CUBRID" href="http://pecl.php.net/package/CUBRID">PHP API</a> to Official PHP.net PECL Repository, released the CUBRID 3.0 Beta, and started Joomla CMS porting.&nbsp;Let's see in more details...</p>

<a name="more"></a>

<p><strong>CUBRID-Ruby Gem</strong></p>

<p><a title="Install CUBRID Connector for Ruby" href="http://rubygems.org/gems/cubrid" target="_blank">CUBRID account</a> at RubyGems.org was created on July 11th, 2010. The CUBRID Connector testing has been started since then. Windows OS compatible <em>cubrid-0.6-x86-mswin32-60.gem </em>was first pushed to RubyGems.org on July 11th. Later on July 27th with slight changes in the <em>extconf.rb</em> gem installer file the&nbsp;<em>cubrid-0.61-x86-mswin32.gem</em> has been refreshed. Then, we have created the detailed <a title="Ruby Programming with CUBRID" href="/wiki_apis/entry/cubrid-ruby-api-documentation" target="_blank">tutorial and API documentation</a> for the Connector. And finally <a title="CUBRID Connector for Windows Users is Available Now" href="http://twitter.com/cubrid/status/19721360995" target="_blank">announced</a> to the community about these changes.</p>

<p>Later we received some <a title="Twitter: @fredwu talk on CUBRID-Ruby Connector" href="http://twitter.com/fredwu/status/20136015846" target="_blank">user comments</a> to host the CUBRID-Ruby source code on Github. After <a title="Where to host the Ruby Project Source Code" href="http://www.ruby-forum.com/topic/214476#931238" target="_blank">some conversation</a> we decided to create Github account and upload the source code of the connector. On August 9th, 2010 we pushed <em>cubrid-0.64.gem</em> to Rubygems.org which is now cross-platform, i.e. can be installed both on Linux and Windows. Use the following command in the terminal to install the CUBRID gem for Ruby.</p>

<p></p><p style="text-align: center;"><img title="Install CUBRID gem" src="/files/attach/images/49/454/001/gem_install_cubrid_web.png" width="699" height="123" editor_component="image_link"/></p><p></p>

<p><strong>Java Tutorial</strong></p>

<p>The main database connector for CUBRID is the JDBC Driver. Most external applications like CUBRID Manager connect to CUBRID through JDBC. To help users get started with Java Programming for CUBRID faster, we have created a <a title="Java Programming with CUBRID" href="/cubrid_java_programming" target="_blank">tutorial</a> with several detailed examples users can just copy and paste to get them up and running. Beside that there are <a title="JDBC &amp; Java Programming with CUBRID" href="/cubrid_java_programming" target="_blank">numerous other manuals and documentations</a> CUBRID users can refer to when building applications around CUBRID.</p>

<p><strong>Python Programming with CUBRID</strong></p>

<p>Python is an established programming language. It has been used by many professional web developers worldwide to create sophisticated web applications. Now Python developers can use the CUBRID-Python Connector to create the Web applications which use CUBRID as a back-end database management system. We encourage users to <a title="Download Python Connector for CUBRID" href="/python_programming" target="_blank">download the Python Library</a> and read the <a title="Wiki: Python Programming with CUBRID" href="/wiki_apis/entry/cubrid-python-api-documentation" target="_blank">API Documentation and Tutorial</a>.</p>

<p><strong>CUBRID API on PHP.net</strong></p>

<p>This is probably one of the most important moves we make toward making the CUBRID Database more open to global users. We have contacted with the PECL members and received the approval for <a title="CUBRID on PHP PECL" href="http://pecl.php.net/package/CUBRID" target="_blank">a new account for CUBRID</a>. After several comments from PECL users we have made quite a lot modifications to the PHP API for CUBRID.&nbsp;Entire code has been reviewed and rewritten to comply with latest Zend Engine 2 API.</p>

<p></p><ul>
	<li>Added more than 20 new APIs, see the&nbsp;<a title="CUBRID PHP API Documentation" href="http://docs.php.net/manual/en/book.cubrid.php">PHP API Documentation</a> for more details.</li>
	<li>Added two new schema types for cubrid_schema: CUBRID_SCH_DIRECT_SUPER_CLASS and CUBRID_SCH_PRIMARY_KEY.</li>
	<li>More data types support for cubrid_bind, the following types are added: CHAR, VARCHAR, BIGINT, MONETARY, VARBIT and DATETIME.</li>
	<li>Fix a bug in cubrid_get: If parameter attr is given and its type is string, and the function returns successfully, then there will be memory leak.</li>
</ul>
<strong>CUBRID 3.0 Beta</strong><p></p>

<p>On July 19th, 2010, we have <a title="New CUBRID 2008 3.0 Beta has been released!" href="http://blog.cubrid.org/news/new-cubrid-2008-r3-0-beta-has-been-released/">announced</a> the latest CUBRID 3.0 Beta release. Overall we have fixed 42 bugs, and introduced 62 new SQL syntax extensions and other enhancements. Now users can leave most of their MySQL compatible SQL statements as they are without any modifications. With CUBRID 3.1 and 3.2 we plan to reach 95% MySQL syntax compatibility, thus providing users not only the increased performance but also&nbsp;the ease of porting their Web applications to CUBRID. As a matter of fact, we have started porting the most popular Content Management System in the world - the Joomla! CMS. Below you can see the current status and the brief explanations about&nbsp;how we leverage the CUBRID MySQL compatibility and optimizations for Web applications to make Joomla CMS porting faster and easier.</p>

<p><strong>Porting Joomla! CMS to CUBRID</strong></p>

<p>These days we are porting the most popular content management system – the Joomla! CMS. Until now none of other database system providers managed porting Joomla to seamlessly work with their system. Previously there were attempts by Postgres and MS SQL communities but stalled before reaching the implementation phase, while Joomla porting for CUBRID already has the feasible results. We estimate that by the end of this month we might have the Joomla&nbsp;alpha release for CUBRID. The project contributors mention that Joomla will have higher performance on CUBRID because of CUBRID's numerous Web optimizations. At this moment we have completed several large tasks like SQL parsing, Joomla Installer. Only a few details remained to get polished. Hope soon we will have another tool to make our users even happier!</p>

<p>You can join the discussions forum of Joomla for CUBRID at SF.net</p>

<p><a title="Joomla CMS Porting" href="https://sourceforge.net/projects/cubrid/forums/forum/1030991/topic/3803020" target="_blank">https://sourceforge.net/projects/cubrid/forums/forum/1030991/topic/3803020</a></p>]]></description>
                        <pubDate>Tue, 21 Sep 2010 07:46:00 +0900</pubDate>
                        <category>News</category>
                        <category>CUBRID Life</category>
                        <category>CUBRID</category>
                        <category>New Release</category>
                        <category>PHP</category>
                        <category>Java</category>
                        <category>Ruby</category>
                                </item>
        										        <item>
            <title>PHP API for CUBRID Database - Video Tutorial</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/cubrid-trainings-channel/php-api-for-cubrid-video-tutorial/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/cubrid-trainings-channel/php-api-for-cubrid-video-tutorial/</guid>
                        <comments>http://www.cubrid.org/blog/cubrid-trainings-channel/php-api-for-cubrid-video-tutorial/#comment</comments>
                                    <description><![CDATA[<p>Greetings to everyone from CUBRID Trainings Channel!</p>

<p>As PHP is something almost all websites are being created in, in this article you will learn how to create PHP applications with CUBRID Database running on the back-end.</p>

<p>This video is a part of Development Series of CUBRID Trainings Channel. You will learn what kind of support CUBRID provides for developing Web applications in PHP, how to install and configure PHP Extension, which is used to establish connections with CUBRID Database. Additionally, in this video tutorial you will see the examples how to request the data from CUBRID Database, how to fetch them, and display in the browser. Here I want to remind that last week <a title="New CUBRID 2008 R3.0 Beta has been released!" href="http://blog.cubrid.org/news/new-cubrid-2008-r3-0-beta-has-been-released/" target="_blank">CUBRID 2008 R3.0 Beta version has been released</a>, which brings lots of MySQL Compatible features such as identical SQL syntax, operators, and same SQL embedded functions. Now on users do not have to worry much that they need to change the entire SQL queries to port their Web applications to work with CUBRID Database. Now almost all your code remains as it is. For more, read <a title="Port MySQL Compatible PHP Applications to CUBRID" href="/wiki_tutorials/entry/Port_MySQL_Compatible_PHP_Applications_to_CUBRID" target="_blank">How to Port MySQL compatible PHP apps to CUBRID</a>.</p>

<a name="more"></a>
<p>In the continuation of this video tutorial, you will learn where to download the PHP Library for CUBRID as well as its source code, how to enable CUBRID Database Extension in <strong>php.ini</strong> configuration file. As an example you will see how to verify that PHP extension has successfully been configured.&nbsp;We spent sleepless nights to ensure that our users have the great ease-of-use and convenience in developing applications with CUBRID Database. Thus, connecting to CUBRID database is as easy as replacing the "<em>mysql</em>" prefix in "mysql_connect" function to "<em>cubrid</em>", as a result calling <strong>cubrid_connect</strong>.</p>

<p>The video will last less than 10 minutes, so afterwards we highly recommend you to visit <a title="PHP API for CUBRID" href="/php_api_for_cubrid" target="_blank">PHP Programming with CUBRID</a> page we have specifically created for PHP Developers. This is the primary page you will be looking for PHP tips and links you will need throughout your PHP Development with CUBRID Database.</p>

<p></p><p style="text-align: center;"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true"/><param name="allowscriptaccess" value="always"/><param name="src" value="http://www.youtube.com/v/zGiQZPvVQSI&amp;hl=en&amp;fs=1"/><param name="allowfullscreen" value="true"/><embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/zGiQZPvVQSI&amp;hl=en&amp;fs=1" allowscriptaccess="always" allowfullscreen="true"/></object></p>

<p>See the related blogs:</p>

<p></p><ul>
	<li><a title="PHP from Zero to Hero!" href="http://blog.cubrid.org/cubrid-appstools/php-from-zero-to-hero-cubrid-documentation/" target="_self">PHP from Zero to Hero!</a></li>
	<li><a title="Installing WordPress for CUBRID" href="http://blog.cubrid.org/cubrid-appstools/installing-wordpress-for-cubrid/" target="_self">Installing WordPress for CUBRID</a></li>
	<li><a title="phpMyEdit for CUBRID" href="http://blog.cubrid.org/cubrid-trainings-channel/phpmyedit-for-cubrid-video-tutorial/" target="_self">phpMyEdit for CUBRID</a></li>
</ul><p></p>]]></description>
                        <pubDate>Tue, 27 Jul 2010 03:51:33 +0900</pubDate>
                        <category>MySQL</category>
                        <category>CUBRID</category>
                        <category>CUBRID Tools</category>
                        <category>CUBRID Trainings Channel</category>
                        <category>Training Videos</category>
                        <category>CUBRID Tutorial</category>
                        <category>Tutorials</category>
                        <category>PHP</category>
                        <category>mysq</category>
                                </item>
        										        <item>
            <title>PHP from Zero to Hero! - CUBRID Documentation</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/cubrid-appstools/php-from-zero-to-hero-cubrid-documentation/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/cubrid-appstools/php-from-zero-to-hero-cubrid-documentation/</guid>
                        <comments>http://www.cubrid.org/blog/cubrid-appstools/php-from-zero-to-hero-cubrid-documentation/#comment</comments>
                                    <description><![CDATA[<p>Today we would like to provide a list of PHP resources which our CUBRID users can refer to when building their web applications using PHP. This blog is intended to provide all the necessary links to the actual tutorial articles which will lead readers from the installation stage to practical ready-to-copy-and-paste examples.</p>

<p>In order to successfully install and use most Web applications like well-known Wordpress or phpBB, it is required to have PHP installed besides database and web servers. Below is a list of these step by step tutorials. Let's get started!</p>

<a name="more"></a>
<p></p>

<p></p><ol>
	<li>There are three software we have to install before we can use any application written in PHP. One is a Database Server. Second - Web Server. Third is PHP. Since you are going to run your website with some web applications,&nbsp;it is recommended to install CUBRID as your Database Server. CUBRID is developed and highly optimized for web applications. It is exactly what you need.<p></p>

<p>For this purpose we have create very easy-to-understand quick tutorial which will explain where you can download CUBRID from and how to install it and prepare for the Web.</p>

<p>Read <a title="Getting Started with CUBRID" href="/tutorials#getting-started" target="_blank">Getting Started with CUBRID</a>.</p></li>
	<li>Second, you need to install a Web Server. In our case we will use most popular and widely used Apache HTTP Web Server. In this tutorial you will learn how to download, install and quickly configure your Apache Server.<p></p>

<p>Read <a title="Preparing Apache Web Server" href="/using_cubrid_with_apache_php_in_linux" target="_blank">Preparing Apache Web Server</a>.</p></li>
	<li>Third, you need to install PHP engine itself. PHP installation is very easy, indeed. The latest version provides easy installation tool which will automatically&nbsp;adjust your Apache Web Server's configuration file to correctly run PHP.<p></p>

<p>Refer to <a title="Install PHP" href="/wiki_tutorials/entry/Install_PHP" target="_blank">Install PHP</a> article to get PHP installed.</p></li>
	<li>At this moment you should have almost everything you need. However, there is one more thing before we get started with Web application's installation. In order to be able to connect to CUBRID Database Server using PHP, there should something like a <em>bridge </em>to let them communicate with each other. This bridge is called <strong>PHP Connector</strong> or <strong>CUBRID PHP Library</strong>. This type of PHP Connector is typical to every database server. In our case CUBRID PHP Library will provide different kinds of PHP functions which you can use to let your web application&nbsp;communicated with CUBRID Database Server to retrieve data from the database, insert, update, and accomplish lots of other tasks.<p></p>

<p>The tutorial below will show where to download CUBRID PHP Library from and how to install it. In fact, there is no need to install. It's a matter of copying the Library file to PHP extensions directory. It will also explain how you can configure the library for your needs.</p>

<p>Read&nbsp;<a title="Install PHP Library for CUBRID" href="/php_api_build_guide" target="_blank">Install PHP Library for CUBRID</a>.</p></li>
	<li><span style="font-size: 13.3333px;">Once you install everything, you might want to test your PHP. In the tutorial provided below you will see several PHP examples which you can copy &amp; paste, then run them. Adjust any code according to your needs.<p></p>

<p>Read <a title="PHP Sample Codes" href="/manual/840/en/PHP%20Sample" target="_blank">PHP Sample Codes</a>.</p>

<p></p></span></li>
	<li><span style="font-size: 13.3333px;">If you have already developed your PHP application for other databases and would like to use them with CUBRID, you might want to port them. This tutorial will explain in details all the CUBRID conventions, data types and SQL syntax which are important to be followed when porting PHP applications. Here you will see practical examples of how to port MySQL compatible PHP applications to CUBRID.<p></p>

<p>Read <a title="Port MySQL Compatible PHP Applications to CUBRID" href="/wiki_tutorials/entry/Port_MySQL_Compatible_PHP_Applications_to_CUBRID" target="_blank">Port MySQL Compatible PHP Applications to CUBRID</a>.</p>

<p></p></span></li>
	<li><span style="font-size: 13.3333px;">Besides porting PHP applications to CUBRID you will highly likely need to migrate your data from other databases to CUBRID. If so, we have written very comprehensive and at the same time very easy-to-understand tutorial for Data Migration. In addition, this blog provides a video lesson for the same tutorial which will show a step-by-step migration process.<p></p>

<p>Read and watch&nbsp;<a title=" Video Tutorial: How to use Apache DdlUtils &amp; Scriptella to migrate databases to CUBRID" rel="nofollow" href="/ddlutils_for_cubrid" target="_self">Video Tutorial: How to use Apache DdlUtils &amp; Scriptella to migrate databases to CUBRID</a>.</p>

<p></p></span></li>
	<li><span style="font-size: 13.3333px;">All these tutorials are aggregated and explained in <a title="PHP Tutorial - CUBRID Documentation" href="/manual/840/en/PHP%20API" target="_blank">PHP Tutorial</a>.</span></li>
</ol>
At this point you will have learnt everything you practically need to get started with PHP programming for CUBRID. All these tutorials should be more than enough to install your applications without running into any errors.<p></p>

<p>If you think there is something else we could have covered, please let us know. We will do our best to make your CUBRID deployment easy and fast!</p>]]></description>
                        <pubDate>Tue, 29 Jun 2010 07:21:00 +0900</pubDate>
                        <category>MySQL</category>
                        <category>CUBRID</category>
                        <category>CUBRID Tools</category>
                        <category>CUBRID Apps&amp;Tools</category>
                        <category>CUBRID Tutorial</category>
                        <category>Tutorials</category>
                        <category>Apache</category>
                        <category>PHP</category>
                                </item>
        										        <item>
            <title>Official CUBRID Forum</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/news/official-cubrid-forum/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/news/official-cubrid-forum/</guid>
                                    <description><![CDATA[<p>Hello everyone!</p>

<p>As most of you know, CUBRID was born and has been actively developed and maintained in South Korea for over 15 years. This creates a question why very few people know about CUBRID? The reason is CUBRID DBMS has been developed and maintained only inside of Korea all these years. The support and documentation was available only in Korean.</p>

<p>Then, we became an Open Source database server engine provider two years ago, late in 2008. We built CUBRID system in English, Chinese, and Japanese. After that, CUBRID enters the year of 2010 with a big news. It&nbsp;<a href="http://blog.cubrid.org/news/cubrid-participates-at-the-mysql-conference/" target="_self">announces</a> it will go abroad and create a Global Open Source Community around CUBRID. We opened our global community web site recently on&nbsp;<a href="/" alt="CUBRID">CUBRID.org</a>. Added&nbsp;<a href="http://www.cubrid.org/blog">CUBRID.blog</a>,&nbsp;<a href="http://www.cubrid.org/dev_zone">CUBRID.wiki</a>, and our new&nbsp;<a href="http://www.cubrid.org/forum">CUBRID.forum</a>.</p>

<a name="more"></a>
<p>Please get registered and engage in our CUBRID Open Source Community Collaboration. We will do our best to keep track of all issues you enter here. We will open dedicated forum branches for each type of question, like MySQL Compatibility branch or PHP, or Web applications. If you have any suggestions, feel free to post your request/advice/need/issue in the appropriate forum branch. We will make sure our DBAs and our large Open Source Community of Korea gets to you and addresses your requests quickly.</p>

<p>Wish you all productive work and easy deployment with CUBRID!</p>

<p>Have fun with the new&nbsp;<a title="CUBRID Forum" href="http://forum.cubrid.org" target="_blank">CUBRID forum</a>!</p>]]></description>
                        <pubDate>Fri, 16 Apr 2010 22:51:57 +0900</pubDate>
                        <category>News</category>
                        <category>forum</category>
                        <category>CUBRID</category>
                        <category>development</category>
                                </item>
        										        <item>
            <title>CSQL - Command Line SQL Interpreter</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/cubrid-life/csql-interpreter/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/cubrid-life/csql-interpreter/</guid>
                        <comments>http://www.cubrid.org/blog/cubrid-life/csql-interpreter/#comment</comments>
                                    <description><![CDATA[<p>I decided to update this CSQL Interpreter Tutorial to make it clearer why it is a must-know tool for database administrators.</p>

<p>Once a user has installed CUBRID database server on their machine, the first thing they need to do is to connect to the database server, and then create the necessary databases, table, and so forth. There are several ways for CUBRID users to establish the successful database connection. First, you can use&nbsp;<a title="What is CUBRID Manager?" href="http://blog.cubrid.org/cubrid-manager/what-is-cubrid-manager/" target="_self">CUBRID Manager</a>, a GUI database administration tool. Second, there are various third party applications such as <a href="http://blog.cubrid.org/cubrid-appstools/cubrid-through-quantumdb-eclipse-plugin/">Eclipse QuantumDB plug-in</a> which you can also use just like CM (CUBRID Manager) to administer your databases. QuantumDB connects to CUBRID using JDBC driver. To learn more about third party applications, read <a href="http://blog.cubrid.org/cubrid-story/cubrid-support-tools/">CUBRID Administration Tools</a>. Third, and the classic way to create and manage the databases, alter tables and grand user permissions, and briefly everything else you can handle with CSQL – a command line SQL interpreter. So, today we will talk about CSQL.</p>

<a name="more"></a>
<p></p>

<p><strong>What is CSQL?</strong></p>

<p>As I have already mentioned CSQL is a command line tool to administer CUBRID database server and run SQL statements. It is a basic path through which a user can communicate with CUBRID.</p>

<p><strong>Why CSQL?</strong></p>

<p>CSQL is mainly used for the following two purposes:</p>

<p></p><ol>
	<li>To execute SQL commands.</li>
	<li>As a path for receiving tasks performed by a DBA for administration.</li>
</ol>

<p>While the first purpose can be satisfied using the various 3rd party tools, the second purpose can only be achieved using CSQL provided solely for CUBRID.</p>

<p><strong>What is the difference between CSQL and <a title="CUBRID Manager" href="http://blog.cubrid.org/cubrid-manager/what-is-cubrid-manager/" target="_self">CUBRID Manager</a> clients, or&nbsp;other&nbsp;various 3rd party tools?</strong></p>

<p><em>CSQL connects to the DB without going through the Broker. For this reason, any problems occurring in the Broker will not affect the CSQL connection at all.</em></p>

<p>Now, let's look at the basic approach of connecting to CUBRID using CSQL.</p>

<p>First, in order to connect to any CUBRID database we have to use <strong>csql</strong> command with a given user account (if any) and a database name.</p>

<p><em>Shell &gt; csql database_name</em></p>

<p>CSQL provides many options you can use when launching it. For details on these options, see&nbsp;<a title="CSQL Startup Options" href="/manual/840/en/CSQL%20Startup%20Options" target="_blank">CSQL Startup Options</a>.</p>

<p><em>Shell &gt; csql demodb</em><em></em></p>

<p>This is how a user has to connect to&nbsp;<em>demodb</em>, a demonstration database provided by default in CUBRID DBMS with the public account (empty password). When you connect to a database, you will see the following window.</p>

<p></p><p style="text-align: center;"><img title="sql_interpreter" src="http://blog.cubrid.org/wp-content/uploads/2010/4-/sql_interpreter1.jpg" width="500" height="300" editor_component="image_link"/></p><p></p>

<p>At any time in order to learn what command you have to run for in certain cases, you type <strong>;help</strong> command. There are several rules when running CSQL commands.</p>

<p></p><ol>
	<li>All CSQL commands must come after a semi-colon <strong>(;)</strong>. For instance, in order to request help, you type <strong>;help</strong>.</li>
	<li>After executing any query, go to a new line and execute&nbsp;<strong>;x</strong> or&nbsp;<strong>;ru</strong> to see the result.<p></p>

<p></p><ol>
	<li><strong>;x</strong> deletes the query in the buffer after execution,</li>
	<li>while <strong>;ru</strong> leaves the query in the buffer to be reused later after the execution.</li>
</ol>
</li>
	<li>To reuse queries, use&nbsp;<strong>;edit</strong>. This will start a&nbsp;<em>vi editor</em>, where you will see the queries that have been executed previously.</li>
</ol>

<p>CSQL is a very powerful command line interpreter. You are recommended to read&nbsp;our online Wiki <a title="CSQL Interpreter" href="/manual/840/en/Introduction%20to%20Cubrid%20Manual-CSQL%20Interpreter" target="_blank">CSQL Interpreter Tutorial</a>. You will learn about reading, saving, and appending SQL statement, Shell command execution/registration, transaction processing, outputting schema information/syntax rules and examples, parameter setting, etc, which are beyond those provided by CUBRID Manager or other simple query editor tools.</p>

<p>If you have any questions regarding CSQL, please post them on our&nbsp;<a title="Scriptella Forum for CUBRID Users" href="/forum" target="_blank">CUBRID Forum</a>.</p>

<p>If you want to be up to date and learn more about CUBRID, subscribe to our&nbsp;<a title="Subscribe to CUBRID Blog" href="/blog/rss/" target="_self">CUBRID Blog</a> or&nbsp;<a title="CUBRID Trainings Channel" href="http://www.youtube.com/user/cubrid" target="_blank">CUBRID Trainings Channel</a>, follow us on&nbsp;<a title="CUBRID on Facebook" href="http://www.facebook.com/pages/CUBRID/300271972317" target="_blank">Facebook</a> or&nbsp;<a title="CUBRID on Twitter" href="http://twitter.com/cubrid" target="_blank">Twitter</a>. &nbsp;We will make sure you are up to date with every news and updates about CUBRID.</p>]]></description>
                        <pubDate>Wed, 07 Jul 2010 03:00:27 +0900</pubDate>
                        <category>Blogroll</category>
                        <category>CUBRID Story</category>
                        <category>CUBRID</category>
                        <category>CUBRID Manager</category>
                        <category>CSQL</category>
                        <category>CUBRID Apps&amp;Tools</category>
                        <category>CUBRID Tutorial</category>
                        <category>QuantumDB</category>
                        <category>Eclipse Plugin</category>
                        <category>Tutorials</category>
                                </item>
        										        <item>
            <title>Famous Online Game and Online Word Processor use CUBRID Database</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/news/famous-online-game-and-online-word-processor-use-cubrid-database/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/news/famous-online-game-and-online-word-processor-use-cubrid-database/</guid>
                        <comments>http://www.cubrid.org/blog/news/famous-online-game-and-online-word-processor-use-cubrid-database/#comment</comments>
                                    <description><![CDATA[<p><p style="text-align: left;"><a href="http://blog.cubrid.org/wp-content/uploads/2010/9-/naverword-web.png"><img title="Online Web Processor run on CUBRID" src="http://blog.cubrid.org/wp-content/uploads/2010/9-/naverword-web.png" width="544" height="305" editor_component="image_link"/></a></p></p>

<p><p style="text-align: left;">Today is a Big day at&nbsp;<a title="No.1 Search Portal, Naver.com" href="http://naver.com" target="_blank">Naver.com</a>, Korea's No.1 Search Portal with 34 million subscribers and 17 million daily unique visitors. Today Naver launches its new Online Word Processor Service&nbsp;backed up by CUBRID Database Server in an&nbsp;<em>Open Beta</em> state. The Word Processor service runs on CUBRID 2008 R2.2 with High-Availability feature ON. There is an approximate estimate that CUBRID Database will process several million batch requests every day.</p></p>

<p><p style="text-align: left;">NaverWord&nbsp;is now available within Naver's most famous&nbsp;<a title="nDrive: Online File Management Service" href="http://ndrive.naver.com" target="_blank">nDrive Web Service</a> for storing and managing personal files. Users can now create Word Documents with advanced Tables, Charts, and Images, store them online, and access them from almost anywhere they want, including iPhone and Android phones, PC, Mac, and iPad.</p></p>

<a name="more"></a>

<p><p style="text-align: left;">Another famous online service which uses CUBRID as a back-end database management system is&nbsp;<a title="A-War Online Game" href="http://aw.mgame.com/event/2010/0715_grandopen/default.mgame" target="_blank">A-War Online Game</a>. The below is a Game Trailer created for a Grand Open Ceremony day.</p></p>

<p><p style="text-align: center;"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="532px" height="452px" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="http://image.mgame.com/mgamezzang/contents/ucc/2010_0315_movieplayer.swf?linkURL=http://liveucc.mgame.com/ucc_bbs/ucc_content.mgame?idx=30036"/><param name="allowfullscreen" value="true"/><embed type="application/x-shockwave-flash" width="532px" height="452px" src="http://image.mgame.com/mgamezzang/contents/ucc/2010_0315_movieplayer.swf?linkURL=http://liveucc.mgame.com/ucc_bbs/ucc_content.mgame?idx=30036" allowfullscreen="true"/></object></p></p>

]]></description>
                        <pubDate>Thu, 02 Sep 2010 07:48:14 +0900</pubDate>
                        <category>News</category>
                        <category>CUBRID</category>
                        <category>performance</category>
                        <category>Game</category>
                        <category>NaverWord</category>
                        <category>Mgame</category>
                        <category>CUBRID Big Users</category>
                        <category>A-War</category>
                                </item>
        										        <item>
            <title>NHN I&amp;S uses CUBRID for its Search Results Monitoring System</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/cubrid-life/nhn-is-uses-cubrid-for-its-search-results-monitoring-system/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/cubrid-life/nhn-is-uses-cubrid-for-its-search-results-monitoring-system/</guid>
                        <comments>http://www.cubrid.org/blog/cubrid-life/nhn-is-uses-cubrid-for-its-search-results-monitoring-system/#comment</comments>
                                    <description><![CDATA[<p><strong><img src="/files/attach/images/220547/392/221/nhn-is-logo.png" alt="NHN I&amp;S Logo" style="float:left;margin-right:10px" width="200" height="91" editor_component="image_link"/>A short notice!</strong> One of the largest users of the CUBRID Database Management System expressed their willingness to have a brief interview with us. Mr. Kim Kee Jeong is a team leader at NHN Information &amp; Services which deploys CUBRID as a backend database management system. The conversation was about which services rely on CUBRID, for how long, and the reason for this choice.</p>

<p>He says that "when choosing a DBMS for critical Web services, they do not go for the reputation or the brand". Mr. Kim emphasized on the "importance of&nbsp;the performance, of how the solution can be optimized for their services". "CUBRID has many features designed specifically for the Internet services, which is why we chose CUBRID," says Mr. Kim Kee Jeong, a team leader at NHN I&amp;S.</p>

<p>To see the full text of the interview, visit <a title="NHN I&amp;S uses CUBRID for its Search Results Monitoring System" href="/interview_nhn_information_services" target="_self">http://www.cubrid.org/interview_nhn_information_services</a>.</p>

<a name="more"></a>]]></description>
                        <pubDate>Fri, 24 Dec 2010 09:37:24 +0900</pubDate>
                        <category>CUBRID Story</category>
                        <category>CUBRID</category>
                        <category>Interview</category>
                        <category>NHN</category>
                                </item>
        										        <item>
            <title>Spring Goes Cloud</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/dev-platform/spring-goes-cloud/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/dev-platform/spring-goes-cloud/</guid>
                        <comments>http://www.cubrid.org/blog/dev-platform/spring-goes-cloud/#comment</comments>
                                    <description><![CDATA[<p><img src="/files/attach/images/220547/958/221/spring09_logo.png" style="float:left;margin-right:10px" alt="Spring logo" width="240" height="50" editor_component="image_link"/>"What does Spring have to do with Cloud?" - you have probably asked yourself when you first saw this article. I will explain this.</p>

<p>In 2009, VMware <a title="VMware to Acquire SpringSource" href="http://www.vmware.com/company/news/releases/springsource.html">acquired</a> SpringSource, "<em>the innovator and driving force behind some of the most popular and fastest growing open source developer communities, application frameworks, runtimes, and management tools</em>",&nbsp;for approximately $362 million in cash and equity plus the assumption of approximately $58 million of unvested stock and options.</p>

<p>There were quite hot discussions around why VMware would acquired Spring.&nbsp;It seems that it's high time to look into the relationship between Spring and Cloud, as <a title="Cloud computing: still unattainable?" href="http://blog.cubrid.org/web-2-0/cloud-computing-still-unattainable/">Cloud computing</a> is on the rise.</p>

<p></p><h2>Spring and Cloud</h2><p></p>

<p>In the same news release&nbsp;SpringSource, the developer of the Spring framework, and VMware, its parent company, claim that Spring is a technology suitable for the Cloud environment. Currently, Cloud platforms related to Spring include <strong><em>vFabric</em></strong>, <strong><em>Cloud Foundry</em></strong>, <strong><em>VMForce</em></strong> and <strong><em>Google App Engine</em></strong>.</p>

<p></p><ul>
	<li><strong>vFabric</strong><p></p>

<p>A solution for private Cloud offered by VMware, which provides a technology stack consisting of, among other things, the virtualization solution of VMware and the middleware, framework and development tools of SpringSource.</p></li>
	<li><strong>Cloud Foundry</strong><p></p>

<p>A <a title="CLOUD FOUNDRY" href="http://www.cloudfoundry.com/">Cloud service</a> operated by SpringSource, which uses Amazon’s AWS and provides middleware including Tomcat.</p></li>
	<li><strong>VMForce</strong><p></p>

<p>A <a title="VMforce" href="http://www.vmforce.com/ ">Cloud service</a> offered jointly by VMware and Salesforce.com, which uses Force.com database and encompasses VMware’s solutions such as Spring, Tomcat and vSphere.</p></li>
	<li><strong>Google App Engine</strong><p></p>

<p>As the result of a partnership between Google and VMware, SpringSource’s development tools now support Google App Engine. A plug-in is provided, which allows the development of an application that uses Google App Engine at Spring Roo.</p></li>
</ul>
<p>At the SpringOne conference held in October 2010, the promotion of Cloud was notable. Spring was combined with diverse Cloud solutions, including vFabric, CloudFoundry, VMForce and even Google App Engine.&nbsp; Two of the three platinum sponsors for SpringOne 2010 were Google and Salesforce.com.</p>

<p>"<em>Spring is just an application framework. What does it have to do with Cloud?</em>" - you would ask. "<em>Aren't the core technologies of Cloud the virtualization and the distributed storage? Why would not Struts or Google Guice run in a Cloud environment instead of Spring, if JVM is correctly in place? These days, any technology that involves multiple servers is called Cloud. Isn’t Spring just one of these?</em>" All we know at this moment is that these questions are not groundless.</p>

<p>Instead of dismissing such moves by major vendors as part of their promotion strategies, it will be useful in understanding the trend in technologies if we look into <strong><em>why VMware, Google and Salesforce.com are trying to accommodate Spring</em></strong>.</p>

<a name="more"></a>
<p></p><h2>Last 10 years and profitable models</h2><p></p>

<p>As it is widely known, Spring started as an alternative technology to the Java EE standard in the early EJB era.</p>

<p>Rob Johnson, the founding father of Spring, addressed the challenges in the early EJB era and developed his own framework, whose code was later disclosed in his book “<em>Expert one to one J2EE development.</em>” The code received such a positive response from developers that it became an open-source project. The Spring framework became popular enough for nine out of the ten top global banks to <a title="PDF: The Ubiquity of Spring in Banking" href="http://www.springsource.com/files/uploads/all/pdf_files/news_event/Spring-and-Tomcat-The-Perfect-Match.pdf">adopt</a> it, and as a result, core developers founded a business entity to receive venture capital.</p>

<p>SpringSource must have thought a lot about its profit model since its foundation.&nbsp; <strong><em>How can a mere application framework bring in money?</em></strong> The company once considered devising something called an enterprise service, in which minor patch versions would be offered to license purchasers.</p>

<p>SpringSource started to use M&amp;A to secure products other&nbsp;than the framework. The first firm it had <a title="Some Decisions are Easy – Like SpringSource Acquiring Covalent" href="http://blog.springsource.com/2008/01/29/some-decisions-are-easy-–-like-springsource-acquiring-covalent/">acquired</a> was Covalent, where the core developers of Tomcat and Apache HTTPD are employed. The decision to acquire Covalent must have come out of a recognition that despite a pretext to integrate framework and middleware, a framework alone would not be enough for profit generation.</p>

<p>To everybody’s surprise, SpringSource itself was acquired by VMware for about 420 million dollars in 2009. The price was startling, as it was worth 530 thousand servers costing one thousand dollars each, but more startling was the buyer, VMware.&nbsp; It was not a middleware vendor like Oracle or IBM, which Java developers are familiar with, but a virtualization solution vendor, which on the surface seems distant from Java.</p>

<p>Rod Johnson had <a title="Ronald Wayne, The “Third Founder” of Apple" href="http://gotocon.com/dl/jaoo-brisbane-2010/slides/RodJohnson_bKeynotebThingsIWishIdKnown.pdf">looked</a> for a business model with scalability. A business model based on consulting and training only would end up being a profit structure based on labor cost. So a model to sell products and services was required. Yet the big difference between the commercial version and the open source version would lead to criticism that the company was treating the open-source community poorly. SpringSource was offering Tomcat reinforced with tc Server, and if bugs are found in Tomcat that did not exist in tc Server, it would face huge criticism. Such restrictions in product selling probably made Rod Johnson decide to go for Cloud service, which is a scalable business model. That is why VMware was the buyer.</p>

<p>Apart from the business background, it is necessary to look into whether combining Spring and Cloud makes technological&nbsp;sense and what efforts had to be made for the combination.</p>

<p></p><h2>Expansion of Spring portfolio and Cloud</h2><p></p>

<p>Spring has picked up speed in evolution since its acquisition by VMware. Looking at projects, such as Spring-Android and Spring-Hadoop these days, it is hard to think of an area in which Spring has not had a hand.</p>

<p>Technologies associated with Cloud can be classified as follows:</p>

<p><strong>First</strong>, there are technologies whose middleware for processing large volume was taken over from Spring directly. RabbitMQ, an AMQP (Advanced Message Queuing Protocol) based MQ solution, and GemFire, a datagrid technology, are two examples. Asynchronous processing and data cache will be more widely used in a Cloud environment, where large volume processing takes place frequently.</p>

<p><strong>Second</strong>, there are technologies which provide API wrapping for distributed storage.</p>

<p>There are many projects for storage ongoing, under a project called Spring-data. Redis, Riak, CouchDB , MongoDB, Neo4j and more are already supported. There is no problem, of course, in using such storage without support from Spring. The objective of such projects is to ensure that the storage API facilitates convenient and consistent use of the API with Spring’s setting and programming method, just as Spring-jdbc is used instead of the direct use of JDBC. Storage APIs will not be as inconvenient as JDBC, but there will be some room for improvement, including a reduction in repeated Try-catch caused by Template-callback pattern.</p>

<p>Cache abstraction in Spring 3.1 facilitates the convenient use of distributed cache solutions. It allows designation of the objects to cache and the keys with Annotation, which is similar to the transaction processing method. Implementations for EhCache are provided by default, and diverse caches can be used to this specification once tuned to the SPI (Service Provider Interface).</p>

<p><strong>Third</strong>, there are monitoring technologies. In a Cloud environment, many server and middleware instances are actually used, even if the user does not pay much attention to the physical server. The use of resources may need to be checked, since you only pay for what you use. A quick understanding of the use pattern is also useful in determining the cost and benefit. That is why monitoring is much more highly emphasized than in traditional systems. SpringSource’s acquisition of Hyperic, a monitoring tool, and development of tools like Spring-insight, can be understood in such context. In Spring-insight, Spring-specific information including Controller information for Spring MVC is provided, which is probably to highlight the benefits realized with Spring.</p>

<p>MQ data storages, cache and monitoring technologies can be installed and used in the existing environment, but can also be included in the technology stack offered as part of a Cloud service. Default solutions are an important part of the competitive edge, even in Cloud service. Amazon’s Cloud includes SQA (Simple Queue Service) as MQ and SimpleDB as storage, while Google App engine has Memcache as cache and BigTable-based DataStore as storage. vFabric, a Cloud solution offered by VMware, uses Gemfire for session clustering for the tc Server, and carries out monitoring with Hyperic.</p>

<p>A large portion of the recent expansion of Spring is related to technology investment in line with the cloud era.</p>

<p></p><h2>Spring and Cloud portability</h2><p></p>

<p>At SpringOne 2010, there was a demonstration in which an application running in VMware’s Cloud was run in Google's App Engine in exactly the same way. This is not surprising in a way, considering the portability of JVM. <strong><em>What is the implication of this?</em></strong></p>

<p>One who intends to adopt Cloud should take into account what will happen over time. For example, an application may need to be transferred from a legacy server to Cloud, from Cloud to another Cloud, or from Cloud to a non-cloud. The greater the part of the application is dependent on a specific running environment, the more burdened the owner of the application will feel. Tying an application to a specific Cloud may seem to be an advantage for Cloud vendors, but it will hinder expansion of the user base because it can deter prospective users from adopting Cloud in its early stages. Existing applications will not be uploaded if it is expensive to move to Cloud. The user will be at a disadvantage in negotiation over pricing if it is difficult for him to exit even after moving-out. Consequently, when trying to expand the market, it will be to the advantage of Cloud vendors to emphasize that Cloud users can upload existing applications with minor modifications, and move out easily.</p>

<p><strong>Meanwhile, <em>will the Cloud environment accommodate existing applications as they are</em>?</strong> This is not an easy task even for WAS, which Web applications are loaded onto. In Cloud services, only a small number of WASes are available. Google App Engine uses a variant of Jetty and Cloud Foundry, VMForce and vFabric, all of which are operated by VMware, and needless to say, use tc Server, a commercial version of Tomcat.&nbsp; Moreover, JVM and WAS used in Cloud have limitations in their functions.</p>

<p>In Google App Engine, no file can be written directly, and no thread or socket can be created. In Servlet spec, the method used to call <span style="font-family: mono;">ServletContext.getNamedDispatcher</span> and find out the name of the default Servlet does not work properly, either. All of this means that elements with the risk of security breach or abuse are not supported. When a legacy system is transferred to a Cloud environment, it is highly likely that the two WASes in the legacy system and in the Cloud are different. This is even more likely if the existing WAS is a Java EE server. Moreover, the function to call from WAS itself or the application will be restricted as well.</p>

<p>Here, Spring can be a big help for Cloud vendors. It can compensate for the weakness of a Cloud service, which offers WAS that supports WAS designated for the Cloud user, especially one that supports Servlet spec only. For example, life cycle management, dependency injection and declarative transaction for objects can be written with Tomcat only when there is no server that supports the JavaEE spec. Even when a JavaEE server is available, the data source and transaction service, among others, offered by the server, can be used by way of Spring. Indirect use of Java EE spec via Spring will require only minor modifications to applications at the time of switching to Tomcat or Jetty as a new WAS.</p>

<p>For example, you just need to change data source lookup with JNDI to DBCP, and instruct the Bean declaration to use <span style="font-family: mono;">DataSourceTransactionManager</span> instead of <span style="font-family: mono;">JtaTransationManager</span>. For this reason, applications using Spring have higher inter-WAS portability and a wider choice of WAS. It can be said that Spring acts as a buffer zone for WAS.</p>

<p>At this point, one can argue that though it is true that Spring reduces dependency on middleware such as WAS, it increases dependency on the framework itself, which in turn will reduce portability. Given such two options only, I would choose dependency on the framework rather than on WAS. A framework can co-exist with others on top of one single WAS, making it easy to change gradually. It also makes sense to have applications dependent on a framework instead of WAS in terms of flexibility. This is because version upgrade or library change for framework is easier than upgrading WAS. When it comes to changing jar files, for example, framework upgrade is done simply by changing a few lines of version declaration at pom.xml of Maven. WAS upgrade, in contrast, is burdensome compared to framework upgrade unless there is the automatic installation of AWS in place. In addition, Spring offers many methods that allow the writing of codes not dependent on it. A standard annotation such as @Inject is an example. The proper use of these methods can help reduce dependency on framework.</p>

<p>Salesforce.com, Google and VMware, the owner of SpringSource, all emphasize Cloud portability through Spring. The reason they speak with one voice while competing with each other is probably that for now, the initial market expansion is the most important priority. They also seem to share a belief that allowing transfer among services, instead of binding users to their own platforms, will be more beneficial in the long run. It can also be understood that all of them are confident in their core competencies, including infrastructure technologies.</p>

<p></p><h2>Spring as a technology portal</h2><p></p>

<p>Another reason why Spring and Cloud are linked is that Spring acts as a sort of portal in the Java technology ecosystem.</p>

<p>Internet portals receive a lot of visits from users and provide consistent UX for them by combining diverse information. CPs (Contents Providers) and portals enter into partnerships for contents sharing because the former can have an opportunity to make its contents widely known while the latter can bring in more visitors by offering them richer contents. User can access a wide variety of contents via portals’ consistent access routes and UX. For example, oil prices available on Naver.com, Korea's #1 search portal operated by <a title="NHN at CUBRID Official Blog" href="http://blog.cubrid.org/tags/nhn/">NHN</a>, are in fact provided by Opinet operated by Korea Oil Corporation, but users can easily access the information in the same way and style as other types of information.</p>

<p>Likewise, Spring is a technology used by many developers and offers a consistent setting method, annotation rules and API style by coordinating various technologies. Just as the user interface of a portal is what the user sees, the API at framework and library is the interface developers see.&nbsp; Companies with component technologies who partner with Spring will have a chance to increase their user base by making their technologies more widely known, just as CPs do. SpringSource, on the other hand, can benefit from a richer technology ecosystem related to Source.</p>

<p>Spring provides flexibility by abstracting diverse technologies into the same API, or organizing them into a similar style to reduce the initial learning cost for developers. For example, GemfireTransactionManager, which is adapted to Spring’s DB transaction management interface can be offered in Gemfire, a datagrid. Even for recently added projects like Spring-amqp, the class names, interface names and method names look familiar to anyone who knows Spring well.</p>

<p>VMware’s acquisition of SpringSource, partnership with Salesforce.com and Spring’s link storages like Neo4j and Terracotta and cache technologies work in some respect to pursue technological synergy. These events, however, could happen because Spring was already widely-known enough to attract people. The acquisition of SpringSource seems to have done a lot to raise awareness, since VMware is now far more familiar to Java developers. Now what needs to be done is to go beyond raising awareness to offering a synergy that users can feel.</p>

<p></p><h2>Non-intrusive design and the Cloud era</h2><p></p>

<p>Obviously, Spring was not intended for the Cloud era when it was first created. The rapidly changing environment requires the adaptation of Spring as well, and it has received plenty of love letters from Cloud vendors so far.&nbsp; The popularity of Spring is partly because it is well-known, and thus useful for publicizing. But mostly, it is the technology’s flexibility and portability that is deemed valuable, even in Cloud, which have attracted such plentiful investment and partnerships.</p>

<p>One of the fundamental reasons for Spring’s popularity is the technology’s design philosophy of ensuring that infrastructure related codes and business logic codes are not mutually intrusive.&nbsp; Spring’s POJO (Plain Old Java Object) approach ensures that Java codes not dependent on any conventions are used for core logic, so that codes less dependent on the running environment are created.</p>

<p>For example, infrastructure-related codes, such as codes for transaction processing, can use conventions like JTA (Java Transaction API) provided by WAS. Putting codes dependent on specific middleware together in a single place will require less modification when the middleware is replaced.&nbsp; In Spring, JTA-neutral transaction API (PlatformTransactionManager) is created and used via AOP to get codes using JTA together in one place, so that the modification of just a couple of lines can allow a switch to another method. As another example, Spring’s security <a title="Spring Security in Google App Engine" href="http://blog.springsource.com/2010/08/02/spring-security-in-google-app-engine/">can be used</a> for logon verification in Google App Engine, probably because the part dependent on the infrastructure for user data storage is well abstracted.</p>

<p>Design must take into account, first of all, how to minimize modifications when there is a need for change in the system, instead of calling it "Cloud Portability." Design with clearly distinguished roles and responsibilities goes beyond time and environments. Eventually, flexibility and portability are the results of good modularization, and do not necessarily require special technologies. Spring’s AOP, Dependency Injection and so on only exist to support this. Before and after Spring, modularization is important, and the power behind Spring’s prosperity in the Cloud era can be attributed to having honored such universal design principles.</p>

<p><strong><em>How different will application development be in the Cloud era?</em></strong> Infrastructure, like the storages and middleware required, will be a lot different. Adaptability to new components introduced into Cloud will determine productivity, at least in the early stage. Still, I don’t think the way of developing applications will be significantly different. A well-modularized code with clear roles and responsibilities will survive the new wave and exist even beyond the era, causing lower cost of modification and addition. This will be the case for whatever code is used, whether it is a framework code or application code written by an app developer.</p>

<p><strong><em>How can one demonstrate that he or she has created a code with clear roles and responsibilities?</em></strong> Just write a test code. It will be difficult to write a test code if the code for infrastructure management and the code for business rules are mixed. Such a code will required more and more costs for modification, and eventually will not survive. Use of a specific framework does not necessarily lead to a good design. The best way to determine whether Spring is optimally utilized will be to see whether you write a code that allows the easy writing of a test code.</p>

<p></p><h2>Conclusion</h2><p></p>

<p>The increased investment by SpringSource in Cloud-related technologies was part of its plan to identify a scalable model, and has already produced some tangible results through a reinforced portfolio and partnerships. Spring can be an asset for Cloud that provides limited WAS due to its scalability, and is recognized for its role as a portal for a technology ecosystem with a wide user base. However, the fundamental reason for the prosperity and adaptation of Spring in the Cloud era is that it is a technology that allows the separate design of application core logic and infrastructure.</p>

<p>There will be a rush of news about Spring throughout the year, and most of it will be related to Cloud. I hope their strategies will unfold in a way that benefits all participants in the Java ecosystem.</p>

<p><span style="color: #000080;">By Jung Sang Hyuk, Manager, Productivity Innovation Team, NHN Business Platform Corp.</span></p>]]></description>
                        <pubDate>Thu, 05 May 2011 10:37:13 +0900</pubDate>
                        <category>NHN</category>
                        <category>Web 2.0</category>
                        <category>Google</category>
                        <category>Amazon</category>
                        <category>Spring</category>
                        <category>SpringSource</category>
                        <category>VMware</category>
                        <category>Salesforce.com</category>
                        <category>Neo4j</category>
                        <category>Terracotta</category>
                        <category>Dev Platform Blog</category>
                                </item>
        										        <item>
            <title>Comprehensive Overview of Top 14 Content Management Systems</title>
            <dc:creator>Esen Sagynov</dc:creator>
            <link>http://www.cubrid.org/blog/dev-platform/comprehensive-overview-of-top-14-content-management-systems/</link>
            <guid isPermaLink="true">http://www.cubrid.org/blog/dev-platform/comprehensive-overview-of-top-14-content-management-systems/</guid>
                        <comments>http://www.cubrid.org/blog/dev-platform/comprehensive-overview-of-top-14-content-management-systems/#comment</comments>
                                    <description><![CDATA[<p><strong>Update: </strong>added the <em>Distinguished clients</em> for DotNetNuke.</p>

<p>These days many websites (<em>in fact, millions</em>) are implemented by the use of popular open source content management systems (CMS). I would say, for <em>everything</em> <em>you would imagine your site doing</em>, there is one or another CMS which can do that. Thus, the reason for choosing a particular one depends on the tasks you want to accomplish. For blogs there is a common sense of using WordPress blog management system, for large scale websites Drupal CMS is perceived to be a better fit, while Joomla CMS is easier to learn for newbies. .NET developers prefer alternative DonNetNuke or umbraco CMS. Besides these, CMS Made Simple and Liferay are amongst the most popular content management systems based on the number of the number of downloads. Elgg and MODx are amongst the rising stars.</p>

<p>I will not tell you what a CMS is. If you want to learn, see the <a title="Wikipedia: Content management system" href="http://en.wikipedia.org/wiki/Content_management_system" target="_blank">CMS Wikipedia page</a>. In this blog I will give a comprehensive overview of top 14 content management systems based on the number of weekly downloads, installations, and brand familiarity. The full statistical data can be found in the 2010 OPEN SOURCE CMS MARKET SHARE REPORT by water&amp;stone (2010). The report is distributed under the <a title="Creative Commons Attribution-Noncommercial License (3.0)" href="http://creativecommons.org/licenses/by-nc/3.0/" target="_blank">Creative Commons Attribution-Noncommercial License</a> (3.0).</p>

<p>Today we will cover <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#drupal">Drupal</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#joomla">Joomla</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#modx">MODx</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#wordpress">WordPress</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#dotnetnuke">DotNetNuke</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#umbraco">umbraco</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#liferay">Liferay</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#typo3">TYPO3</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#cmsmadeeasy">CMS Made Simple</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#movabletype">MOVABLE TYPE</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#plone">Plone</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#ezpublish">eZ Publish</a>, <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#concrete5">concrete5</a>, and <a href="http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#alfresco">Alfresco</a> content management systems. You might already be familiar with some of these, while some can be new to you. I bet you will be surprised to learn that some unknown for you systems suit your requirements much better than those you have got to use so far (my personal experience). So, let's learn about each of them, and <em>do not forget to leave your comments below on what other CMS should have been included in this list and why</em>.</p>

<a name="more"></a>
<p></p>

<p></p><blockquote><strong>Note:</strong><em> the order of the CMS does not represent its quality, performance, or superiority over the other. They are numbered to give a better perception to readers. The users feedback and opinions are retrieved from Stack Overflow, thus can be subjective as they are based on personal views and preferences.</em></blockquote><p></p>

<p></p><h2># 1: Drupal</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://drupal.org/" target="_blank"><img title="Drupal" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/drupal.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site:</strong> <a title="Drupal - Open Source CMS" href="http://drupal.org/" target="_blank">http://drupal.org/</a></p>

<p>1% of all websites on the Internet are based on this platform.  An estimated 7.2 million sites were powered by Drupal as of July 2010. Drupal started out in 2001. In one year from May 2007 to April 2008, Drupal was downloaded from their official site more than 1.4 million times, an increase of approximately 125% from the previous year.</p>

<p><strong>Weekly downloads:</strong> 33,671 (<em>ranked #3 after Joomla and before DotNetNuke</em>).</p>

<p><strong>Installations:</strong> 575 according to the survey (<em>#3 after WordPres and before DotNetNuke</em>), but 1.4% (<em>#3 after Joomla and before Typo3</em>) of Alexa Top 1 million sites.</p>

<p><strong>Brand Familiarity:</strong> Drupal is known to be <em>the #3 most familiar content management system</em>.</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>You can manage multiple sites with Drupal in multiple languages. You can use it for blogging site, corporate site, personal site, gallery, briefly, whatever you imagine.</li>
	<li>You can easily manage your site users, providing standard registration, including OpenID support. You can set various access control rules to limit the activity of your site users.</li>
	<li>Provides multiple-level menu system, template customization, advanced search, RSS feed aggregator.</li>
	<li>Officially Drupal supports several databases including MySQL, PostgreSQL, MariaDB, and SQLite.</li>
	<li>To increase its performance, you can use caching. At the same time it provides high security with notifications about the new update releases.</li>
	<li>Provides Search Engine Friendly descriptive URLs.</li>
	<li>Powered by jQuery JavaScript framework.</li>
</ul>
<strong>Extensions:</strong> over 7,000 free community-contributed addons, known as contrib modules.<p></p>

<p><strong>Distinguished Clients:</strong></p>

<p></p><ul>
	<li><a title="The White House of the United States of America" href="http://www.whitehouse.gov/" target="_blank">http://www.whitehouse.gov/</a></li>
	<li><a href="http://data.gov.uk/" target="_blank">http://data.gov.uk/</a></li>
	<li><a href="http://www.ubuntu.com/" target="_blank">http://www.ubuntu.com/</a></li>
	<li><a href="http://www.alrc.gov.au/" target="_blank">http://www.alrc.gov.au/</a></li>
	<li><a href="http://www.nysenate.gov/" target="_blank">http://www.nysenate.gov/</a></li>
	<li><a href="http://london.gov.uk/" target="_blank">http://london.gov.uk/</a></li>
	<li><a href="http://www.rutgers.edu/" target="_blank">http://www.rutgers.edu/</a></li>
	<li><a href="http://www.economist.com/" target="_blank">http://www.economist.com/</a></li>
	<li><a href="http://wfp.org/" target="_blank">http://wfp.org/</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>More difficult to master especially for newbies. It's more for advanced users. Though the new Drupal 7 claims to provide significantly improved usability (<em>maybe more toward WordPress style</em>). To achieve this, they hired web designers to specifically address the UX problems it had in previous versions.</li>
	<li>New major releases are not quite backward compatible. More focus on new features and functionality. External module developers should take care of compatibility themselves, except for data representation, which Drupal is intended to keep same.</li>
	<li>Drupal is often compared with Joomla and is perceived to be a bit slower. Though this depends on the type of website you develop. However, leveraging its caching and gzipping technologies, it is possible to achieve quite impressive results.</li>
	<li>jQuery, the default JavaScript framework in Drupal, allows to use alternative Mootools framework at the same time.</li>
</ul>
<h2># 2: Joomla</h2><p></p>

<p><a title="Joomla" href="http://www.joomla.org/" target="_blank"><img title="Joomla" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/joomla.png" width="701" height="325" editor_component="image_link"/></a></p>

<p><strong>Official site:</strong> <a href="http://www.joomla.org/" target="_blank">http://www.joomla.org/</a></p>

<p>Joomla is the result of a fork of Mambo CMS on August 17, 2005. Within its first year of release, Joomla had been downloaded 2.5 million times.</p>

<p><strong>Weekly downloads:</strong> 113,836 (<em>ranked #2 after WordPress and before Drupal</em>).</p>

<p><strong>Installations:</strong> 1,297 according to the survey (<em>#1 before WordPress</em>), but 2.5% (<em>#2 after WordPress and before Drupal</em>) of Alexa Top 1 million sites.</p>

<p><strong>Brand Familiarity:</strong> Joomla is known to be <em>the #1 most familiar content management system</em>.</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>You can manage multiple site with Joomla in multiple languages natively (since Joomla 1.6). You can use it for blogging site, corporate site, personal site, gallery, briefly, whatever you imagine.</li>
	<li>You can easily manage your site users, providing standard registration, including Google OpenID support. Full support for Access Control List.</li>
	<li>Provides Multiple-level menu and content category system, template customization, advanced search, RSS feed aggregator.</li>
	<li>Officially supports only MySQL.</li>
	<li>Page cashing for increased performance.</li>
	<li>Provides moderate descriptive URLs (<em>still not fully customizable as you can do in WordPress</em>).</li>
	<li>Powered by MooTools JavaScript framework.</li>
</ul>
<strong>Extensions:</strong> There are over 6,000 free and commercial plugins available from the official site.<p></p>

<p><strong>Distinguished Clients:</strong></p>

<p></p><ul>
	<li><a href="http://www.linux.com/" target="_blank">http://www.linux.com/</a></li>
	<li><a href="http://www.itwire.com/" target="_blank">http://www.itwire.com/</a></li>
	<li><a href="http://www.quizilla.com/" target="_blank">http://www.quizilla.com</a></li>
	<li><a href="http://www.ihop.com/" target="_blank">http://www.ihop.com</a></li>
	<li><a href="http://gsas.harvard.edu/" target="_blank">http://gsas.harvard.edu</a></li>
	<li>Citibank (Financial institution      intranet) - Not publicly accessible</li>
	<li><a href="http://www.greenmaven.com/" target="_blank">http://www.greenmaven.com</a></li>
	<li><a href="http://www.outdoorphotographer.com/" target="_blank">http://www.outdoorphotographer.com</a></li>
	<li><a href="http://www.playshakespeare.com/" target="_blank">http://www.playshakespeare.com</a></li>
	<li><a href="http://www.sensointeriors.co.za/" target="_blank">http://www.sensointeriors.co.za</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>More intuitive and easy to use than Drupal, though still not like WordPress.</li>
	<li>Powerful. Fully-fledged content management system, so you can create whatever site you want.</li>
	<li>Really strong security. If security problems found, immediately fixed.</li>
	<li>The new Joomla 1.6 release is expected to be faster, more convenient, with more features.</li>
	<li>Its strong dependency on Mootools JavaScript framework sometimes bothers users as Joomla does not give easy workaround to disable it and use jQuery instead.</li>
	<li>Support of only one database, limits Joomla a lot in terms of the number of users. However, this is a compromise for high optimizations for MySQL, thus increased overall performance.</li>
	<li>Does not allow to fully customize URLs - a must feature for CMS.</li>
</ul>
<h2>#3: modx</h2><p></p>

<p><a title="modx" href="http://www.modxcms.com/" target="_blank"><img title="modx" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/modx.png" width="701" height="325" editor_component="image_link"/></a></p>

<p><strong>Official site: </strong><a href="http://www.modxcms.com/" target="_blank">http://www.modxcms.com/</a></p>

<p><strong>modx</strong> is not just an open source CMS but also a web application framework. Raymond Irving and Ryan Thrash began the MODx CMS project in 2004 as a fork of Etomite. In 2008 MODx users created a new logo and branding for the project. Now MODx allows for full segregation of content (plain HTML), appearance and behavior (standards compliant CSS and JavaScript) and logic (PHP, snippets).</p>

<p><strong>Weekly downloads:</strong> 4,500 (<em>ranked #11 after umbraco and before Tiki</em>).</p>

<p><strong>Installations:</strong> 58 according to the survey (<em>#12 after eZ Publish and before umbraco</em>), has less than 0.1% among the Alexa Top 1 million sites.</p>

<p><strong>Brand Familiarity:</strong> #14 (<em>before Liferay and after eZ Publish</em>).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>As with Joomla, modx officially supports only MySQL database.</li>
	<li>Not just CMS but a PHP framework for Web.</li>
	<li>Freedom to choose jQuery, Mootools, ExtJS, Prototype or any other JavaScript library.</li>
	<li>Supports PHP 4.3.11 and above.</li>
	<li>Complete control of all metadata and URL structure for SEO (Search Engine Optimization).</li>
	<li>Unlimited hierarchical page depth.</li>
	<li>Can create custom fields and widgets for templates.</li>
	<li>Role-based permissions for the Manager.</li>
	<li>Ability to customize the Manager on a per-deployment basis.</li>
	<li>Ecommerce integration via Foxy Cart.</li>
</ul>
<strong>Extensions:</strong> 622, also known as add-ons.<p></p>

<p><strong>Distinguished Clients:</strong></p>

<p></p><ul>
	<li><a href="http://www.pippatoledo.com/" target="_blank">http://www.pippatoledo.com/</a></li>
	<li><a href="http://www.aquevix.com/" target="_blank">http://www.aquevix.com/</a></li>
	<li><a href="http://www.not1bug.com/" target="_blank">http://www.not1bug.com/</a></li>
	<li><a href="http://everlight-uva.com/" target="_blank">http://everlight-uva.com/</a></li>
	<li><a href="http://www.tritopora.ru/" target="_blank">http://www.tritopora.ru/</a></li>
	<li><a href="http://www.strategische-webloesungen.de/" target="_blank">http://www.strategische-webloesungen.de/</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>Good to have a choice for favorite JavaScript framework.</li>
	<li>Light CMS solution (but not necessarily the fastest).</li>
	<li>PHP 4 support for developers mean that a lot of compromises had to be made in terms of OOP (Object Oriented Programming) in order to offer PHP 4 support .</li>
	<li>Nice to have freedom to set custom URL.</li>
</ul>
<h2>#4: WordPress</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://wordpress.org/" target="_blank"><img title="WordPress" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/wordpress.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site:</strong> <a href="http://wordpress.org/" target="_blank">http://wordpress.org/</a></p>

<p>WordPress was first released on May 27, 2003, by Matt Mullenweg as a fork of b2/cafelog. As of August 2010, version 3.0 had been downloaded over 12.5 million times. Nowadays, known as the #1 CMS for blogging.</p>

<p><strong>Weekly downloads:</strong> 983,625 (<em>ranked #1 before Joomla</em>).</p>

<p><strong>Installations:</strong> 1,012 according to the survey (<em>#2 after Joomla and before Drupal</em>), but 12.9% of the Alexa Top 1 million sites (<em>#1 before Joomla</em>).</p>

<p><strong>Brand Familiarity:</strong> #2 (<em>after Joomla and before Drupal</em>).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Highly optimized for blogging.</li>
	<li>Custom and easy to switch themes.</li>
	<li>Users can re-arrange widgets without editing PHP or HTML code.</li>
	<li>Official support for only MySQL.</li>
	<li>Custom URL, clean permalink structure, excellent for SEO.</li>
	<li>Nested, multiple categories to articles.</li>
	<li>Support for tagging. Advanced search by tags.</li>
	<li>Highly intuitive UI (User Interface).</li>
	<li>jQuery JavaScript framework.</li>
	<li>Supports the Trackback and Pingback standards for displaying links to other sites that have themselves linked to a post or article.</li>
	<li>Rich plugin architecture which allows users and developers to extend its functionality beyond the features that come as part of the base install.</li>
</ul>
Native applications exist for Android, iPhone/iPod Touch,<a href="http://en.wikipedia.org/wiki/WordPress#cite_note-6" target="_blank"></a> and BlackBerry which provide access to some of the features in the WordPress Admin panel and work with WordPress.com and many WordPress.org blogs.<p></p>

<p><strong>Extensions:</strong> 12,780 plugins and 1,315 themes.</p>

<p><strong>Distinguished Clients:</strong></p>

<p></p><ul>
	<li><a href="http://www.nytimes.com/interactive/blogs/directory.html" target="_blank">http://www.nytimes.com/interactive/blogs/directory.html</a></li>
	<li><a href="http://tmagazine.blogs.nytimes.com/" target="_blank">http://tmagazine.blogs.nytimes.com/</a></li>
	<li><a href="http://crowdfavorite.com/" target="_blank">http://crowdfavorite.com/</a></li>
	<li><a href="http://blog.broadband.gov/" target="_blank">http://blog.broadband.gov/</a></li>
	<li><a href="http://blogs.america.gov/" target="_blank">http://blogs.america.gov/</a></li>
	<li><a href="http://www.number10.gov.uk/" target="_blank">http://www.number10.gov.uk/</a></li>
	<li><a href="http://www.speaker.gov/" target="_blank">http://www.speaker.gov/</a></li>
	<li><a href="http://allthingsd.com/" target="_blank">http://allthingsd.com/</a></li>
	<li><a href="http://politicalticker.blogs.cnn.com/" target="_blank">http://politicalticker.blogs.cnn.com/</a></li>
	<li><a href="http://stylenews.peoplestylewatch.com/" target="_blank">http://stylenews.peoplestylewatch.com/</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>Perhaps, the most convenient, easy to use and intuitive CMS (<em>or BMS</em>) in the world. Perfect for blog sites. But if you need to develop a dynamic site with various components, perhaps, other CMS would fit better, though, WordPress provides enough plugins to accomplish almost all tasks.</li>
	<li>I would avoid Wordpress as a CMS in a professional environment. As stated earlier, it's a great blogging platform, but doesn't generally offer the robustness that most professional environments require.</li>
	<li>Availability of jQuery makes the plugin development a lot easier for external developers and site owners.</li>
	<li>Endless themes - no need to worry about the new design for your site, unless you really need something special.</li>
</ul>
<h2>#5: DotNetNuke</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://www.dotnetnuke.com/" target="_blank"><img title="DotNetNuke" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/dotnetnuke.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site:</strong> <a href="http://www.dotnetnuke.com/" target="_blank">http://www.dotnetnuke.com/</a></p>

<p>DotNetNuke is an open source platform for building web sites based on Microsoft .NET technology. It is written in VB.NET and distributed under both a Community Edition BSD-style license <a href="http://en.wikipedia.org/wiki/DotNetNuke#cite_note-autogenerated1-2" target="_blank"></a>and a commercial proprietary license. The Community Edition is a popular web content management (WCM) system and application development framework for ASP.NET, with over 6 million downloads and 600,000 production web sites as of October 2010. More than 8,000 DotNetNuke apps are available for purchase on Snowcovered.com. DotNetNuke.com has over 800,000 registered members as of October 2010.</p>

<p><strong>Weekly downloads:</strong> 13,000 (<em>ranked #4 after Drupal and before CMS Made Simple</em>).</p>

<p><strong>Installations:</strong> 402 according to the survey (<em>#4 after Drupal and before Liferay</em>), but 0.2% of the Alexa Top 1 million sites (<em>#4 after Typo3 and before MOVABLE TYPE</em>).</p>

<p><strong>Brand Familiarity:</strong> #4 (<em>after Drupal and before Typo3</em>).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Distinguishes between community (common features) and enterprise (full set of features) editions.</li>
	<li>Various modules, and data providers.</li>
	<li>Provides language packs for about 60 languages.</li>
	<li>Customizable through skins and templates.</li>
</ul>
<strong>Distinguished&nbsp;clients:</strong><p></p>

<p></p><ul>
	<li><a href="http://www.chamberlain.edu/" target="_blank">http://www.chamberlain.edu/</a></li>
	<li><a href="http://magenic.com/" target="_blank">http://magenic.com/</a></li>
	<li><a href="http://www.graphiksolutions.ca/" target="_blank">http://www.graphiksolutions.ca/</a></li>
	<li><a href="http://www.marly.com/" target="_blank">http://www.marly.com/</a></li>
	<li><a href="http://www.dotcomsoftwaresolutions.com/" target="_blank">http://www.dotcomsoftwaresolutions.com</a></li>
	<li><a href="http://www.cityplaceascent.com/" target="_blank">http://www.cityplaceascent.com/</a></li>
	<li><a href="http://sites.kiwanis.org/kiwanis/en/home.aspx" target="_blank">http://sites.kiwanis.org/kiwanis/en/home.aspx</a></li>
	<li><a href="http://www.zonediet.com/" target="_blank">http://www.zonediet.com/</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>A little bit difficult to create modules.</li>
	<li>It is perceived as a little bit bulky CMS.</li>
	<li>Does not provide extensive documentation and user guides.</li>
	<li>Similar to most CMS, does not provide full backward compatibility in its new major releases.</li>
	<li>Unlike its enterprise edition, the community edition is not tested and certified by the DotNetNuke Corporation.</li>
	<li>Even if it provides the language packs, the sites cannot be created to support multiple languages. Third party module should be used to enable this feature.</li>
	<li>Auto-upgrade, Advanced Site Search, Page Cashing, and many must-have features are not included in the Community edition, only in Professional or Enterprise editions.</li>
</ul>
<h2>#6: Umbraco</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://umbraco.org/" target="_blank"><img title="umbraco" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/umbraco.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site: </strong><a href="http://umbraco.org/" target="_blank">http://umbraco.org/</a></p>

<p>Umbraco is also an open source content management system. It was developed by Niels Hartvig in 2000 and released as open source software in 2004<a href="http://en.wikipedia.org/wiki/Umbraco#cite_note-history-1" target="_blank"></a>. It is written in C# and can be deployed on Microsoft based infrastructure. In 2010, with about <strong>1,000 downloads a day</strong>, Umbraco was in the Top 5 most popular downloads via the <em>Microsoft Web Platform Installer</em>, two places below its main rival DotNetNuke.</p>

<p><strong>Weekly downloads:</strong> 5,420 (<em>ranked #10 after Alfresco and before MODx</em>).</p>

<p><strong>Installations:</strong> 57 according to the survey (<em>#13 after MODx and before e107</em>), but less than 0.1% of the Alexa Top 1 million sites.</p>

<p><strong>Brand Familiarity:</strong> #16 (after Liferay and before e107).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Can be deployed with several databases, including MySQL, SQL Server, and VistaDB.</li>
	<li>SEO-friendly URLs.</li>
</ul>
<strong>Extensions:</strong><span style="font-weight: normal;"> 310 add-on modules.</span><p></p>

<p><strong>What users say:</strong></p>

<p></p><ul>
	<li>Limited number of extensions.</li>
	<li>Official support for Windows OS only.</li>
	<li>Umbraco is oriented to small low-cost sites.</li>
	<li>Video trainings have to be purchased.</li>
	<li>Many must-have features have to purchased.</li>
</ul>
<h2>#7: Liferay</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://www.liferay.com/" target="_blank"><img title="Liferay" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/liferay.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site: </strong><a href="http://www.liferay.com/" target="_blank">http://www.liferay.com/</a></p>

<p><strong>Liferay </strong>Portal is a free and open source enterprise portal written in Java and distributed under the GNU Lesser General Public License. It allows users to set up features common to websites. It is fundamentally constructed of functional units called portlets. Liferay is sometimes described as a content management framework or a web application framework. It comes with certain portlets preinstalled. These comprise the core functionality of the portal system.</p>

<p><strong>Weekly downloads:</strong> 9,435 (<em>ranked #6 after CMS Made Simple and before TYPO3</em>).</p>

<p><strong>Installations:</strong> 154 according to the survey (<em>#5 after DotNetNuke and before TYPO3</em>), but less than 0.1% of the Alexa Top 1 million sites.</p>

<p><strong>Brand Familiarity:</strong> #15 (after MODx and before Umbraco).</p>

<p><strong>Major Features/ Portlets:</strong></p>

<p></p><ul>
	<li>Can tag and categorize contents.</li>
	<li>Document Library Manager, Recent Documents.</li>
	<li>Alfresco, Documentum, and other document library integration.</li>
	<li>User management based on various roles and groups (ACL).</li>
	<li>WebDAV Integration (Web-based Distributed Authoring and Versioning which allows users to collaboratively edit and manage files on remote web servers).</li>
	<li>Nested Portlets</li>
	<li>User Directory</li>
	<li>LDAP Integration</li>
	<li>Microsoft Office Integration</li>
	<li>Calendar/Chat/Mail/Message Boards/Polls</li>
	<li>Wiki (supports Creole as well as MediaWiki syntax)</li>
	<li>Alerts and Announcements</li>
	<li>Knowledge Base</li>
	<li>Social Equity</li>
	<li>Can create multi-language sites.</li>
	<li>Asset Publisher to publish many contents, tagged by a specific term, at once.</li>
</ul>
<strong>Extensions:</strong> 27 official plugins and 208 community developed plugins.<p></p>

<p><strong>Distinguished Clients:</strong> It is primarily used to power corporate business sites.</p>

<p></p><ul>
	<li><a href="http://developer.cisco.com/" target="_blank">http://developer.cisco.com</a></li>
	<li><a href="http://www.t-mobile.cz/" target="_blank">http://www.t-mobile.cz</a></li>
	<li><a href="http://www.betavine.net/" target="_blank">http://www.betavine.net</a></li>
	<li><a href="http://www.foxchannel.de/" target="_blank">http://www.foxchannel.de/</a></li>
	<li><a href="http://www.ixarm.com/" target="_blank">http://www.ixarm.com</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>It is mostly used by enterprise companies rather than for powering personal or community sites, though it has social and collaboration features.</li>
	<li>More professional developers driven project (<em>backed by Liferay Inc.</em>) rather than the community driven.</li>
	<li>Provide paid Enterprise edition.</li>
	<li>All features are available in Community edition (<em>except for support and customization related</em>).</li>
</ul>
<h2>#8: Typo3</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://typo3.org/" target="_blank"><img title="TYPO3" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/typo3.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site:</strong> <a href="http://typo3.org/" target="_blank">http://typo3.org/</a></p>

<p><strong>TYPO3</strong> is a free and open source CMS released under the GNU General Public License oriented to small to mid size enterprise-class users. TemplaVoila is an alternative template engine extension for TYPO3. A graphical mapping tool for creating templates is included, an alternative page module, the ability to create flexible content elements and an API for developers. New content element types can be created without programming. TemplaVoila facilitates more flexibility for maintaining web pages than TYPO3's standard templating, while making it possible to enforce a strict corporate design and allowing editors to work with content more intuitively.</p>

<p><strong>Weekly downloads:</strong> 7,461 (ranked #7 after Liferay and before eZ Publish).</p>

<p><strong>Installations:</strong> 122 according to the survey (#6 after Liferay and before Tiki), 0.6% of the Alexa Top 1 million sites (#4 after Drupal and before DotNetNuke).</p>

<p><strong>Brand Familiarity:</strong> #5 (after DotNetNuke and before OpenCMS).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Supports MySQL, Oracle, MS-SQL, PostgreSQL, ODBC, LDAP - virtually any external data source.</li>
	<li>You can undo any change you make on the site.</li>
	<li>Can create multiple sites with multiple domains for each.</li>
	<li>Can have multiple template per site.</li>
	<li>User management.</li>
	<li>Able to switch from administrator user to general user to check permissions.</li>
	<li>Sandbox: administrators can set up a section within the system to test new features without disturbing the main site.</li>
	<li>Versioning of content pages.</li>
	<li>Advanced caching: template, navigation or page level.</li>
	<li>Link management.</li>
	<li>Multi-language content.</li>
	<li>Search Engine friendly URLs.</li>
</ul>
<strong>Extensions:</strong> more than 4,500 pluggable extensions are available for TYPO3.<p></p>

<p><strong>Distinguished clients:</strong></p>

<p></p><ul>
	<li><a href="http://www.volkswagen-ir.de/" target="_blank">http://www.volkswagen-ir.de</a></li>
	<li><a href="http://www.eadssecureuk.com/" target="_blank">http://www.eadssecureuk.com</a></li>
	<li><a href="http://www.geveriwise-eu.com/" target="_blank">http://www.geveriwise-eu.com</a></li>
	<li><a href="http://www.rewe-xxl.de/" target="_blank">http://www.rewe-xxl.de</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>The administrator's UI (User Interface) is not user-friendly, though intuitive and functional.</li>
	<li>It is extremely powerful which provide more enterprise level features, but the learning curve is <em>incredibly</em> steep.</li>
	<li>Great ease of multi-lingual site management.</li>
	<li>Difficult to customize templates. Need to learn TypoScript and TemplaVoila, two TYPO3-specific systems.</li>
</ul>
<h2>#9: CMS Made Simple</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://www.cmsmadesimple.org/" target="_blank"><img title="CMS Made Simple" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/cms-made-simple.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site: </strong><a href="http://www.cmsmadesimple.org/" target="_blank">http://www.cmsmadesimple.org/</a></p>

<p>CMS Made Simple is an open source cms built using PHP with support for MySQL and PostgreSQL. The template system is driven using the Smarty Template Engine.</p>

<p><strong>Weekly downloads:</strong> 9,948 (ranked #5 after DotNetNuke and before Liferay).</p>

<p><strong>Installations:</strong> 72 according to the survey (#7 after Tiki and before Alfresco), 0.1% of the Alexa Top 1 million sites (#8 after Xoops and before eZ Publish).</p>

<p><strong>Brand Familiarity:</strong> #12 (after Xoop and before Ez Publish).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Officially supports MySQL and PostgreSQL.</li>
	<li>Search Engine Friendly URLs.</li>
	<li>Users management and group based permissions system.</li>
	<li>Content tagging.</li>
	<li>Site localization is available in 20 languages.</li>
</ul>
<strong>Extensions:</strong> unknown, but many.<p></p>

<p><strong>What users say:</strong></p>

<p></p><ul>
	<li>It is oriented more toward professional users.</li>
	<li>It does not provide many templates, so coding knowledge is a must.</li>
</ul>
<h2><strong>#10: Movable Type</strong></h2><p></p>

<p></p><p style="text-align: center;"><strong><a href="http://movabletype.org/" target="_blank"><img title="MOVABLETYPE" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/movabletype.png" width="701" height="325" editor_component="image_link"/></a> </strong></p><p></p>

<p><strong>Official site: </strong><a href="http://movabletype.org/" target="_blank">http://movabletype.org/</a></p>

<p><strong>Movable Type</strong> is a weblog publishing system, similar to WordPress, developed by the Six Apart company in Perl programming language. At various times, this company maintained three other publishing systems - TypePad, Vox, and LiveJournal. Movable Type was publicly announced on September 3, 2001. Version 1.0 was publicly released on October 8, 2001, thus it is a blogging system older than WordPress. On 12 December 2007, Movable Type was relicensed as free software under the GNU General Public License. Based on the list of its customers, Movable Type is quite credible CMS.</p>

<p><strong>Weekly downloads:</strong> unavailable.</p>

<p><strong>Installations:</strong> 30 according to the survey (#17 after Silverstripe and before OpenCMS), 0.1% of the Alexa Top 1 million sites (#6 after DotNetNuke and before Xoops).</p>

<p><strong>Brand Familiarity:</strong> #8 (after Plone and before Alfresco).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Convenient blogging system with social community features.</li>
	<li>Since version 5 officially supports only MySQL. PostgreSQL and SQLite can be used via plugins. Databases such as Oracle can be integrated with Movable Type Enterprise edition.</li>
	<li>Manage user roles. OpenID support.</li>
	<li>Multiple site hosting.</li>
	<li>Easily customizable templates.</li>
	<li>Revision history.</li>
	<li>Can add custom fields.</li>
	<li>Content tags and categories.</li>
	<li>Feeds and trackback links.</li>
	<li>Available localization and internationalization.</li>
	<li>Can generate static pages (updated whenever the content of the site is changed).</li>
</ul>
<strong>Extensions:</strong> about 1,000 plugins.<p></p>

<p><strong>Distinguished clients:</strong></p>

<p></p><ul>
	<li><a href="http://www.britneyspears.com/" target="_blank">http://www.britneyspears.com/</a></li>
	<li><a href="http://www.barackobama.com/" target="_blank">http://www.barackobama.com/</a></li>
	<li><a href="http://boeingblogs.com/" target="_blank">http://boeingblogs.com/</a></li>
	<li><a href="http://blogs.oracle.com/" target="_blank">http://blogs.oracle.com/</a></li>
	<li><a href="http://gehealthcare.typepad.com/" target="_blank">http://gehealthcare.typepad.com/</a></li>
	<li><a href="http://www.spd.org/" target="_blank">http://www.spd.org/</a></li>
	<li><a href="http://blog.ted.com/" target="_blank">http://blog.ted.com/</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>Users often deploy Movable Type for their blog sites, newspaper or other type of publishing sites.</li>
	<li>A powerful alternative for WordPress.</li>
</ul>
<h2>#11: Plone</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://plone.org/" target="_blank"><img title="Plone" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/plone.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site: </strong><a href="http://plone.org/" target="_blank">http://plone.org/</a></p>

<p><strong>Plone</strong>, a free and open source CMS, started in 1999 by Alexander Limi, Alan Runyan, and Vidar Andersen. It was made as a usability layer on top of the Zope content management framework, thus Plone is written in Python. The first version was released in 2001. In 2004, Plone 2.0 was released. This release brought more customizable features to Plone, and enhanced the add-on functions. In 2007, Plone 3 was released. This new release brought inline editing, an upgraded visual editor, and strengthened security, among many other enhancements. Recently in 2010, Plone 4 was released with major improvements in performance.</p>

<p><strong>Weekly downloads:</strong> unavailabe.</p>

<p><strong>Installations:</strong> 34 according to the survey (#15 after e107 and before Silverstripe), 0.1% of the Alexa Top 1 million sites (#10 after eZ Publish).</p>

<p><strong>Brand Familiarity:</strong> #7 (after OpenCMS and before Movable Type).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Inline editing - no need to reload the page for editing.</li>
	<li>Localized into 40 languages.</li>
	<li>Plone can be integrated with Active Directory, Salesforce, LDAP, SQL, Web Services, and Oracle.</li>
	<li>Working Copy support - keep the old version of a content published until you publish a new version.</li>
	<li>Cut/copy/paste operations on content.</li>
	<li>Link and reference integrity checking - no more broken links within your site.</li>
	<li>Can create workflows - useful for organizations.</li>
	<li>LiveSearch - instant site search powered by AJAX.</li>
	<li>Full-text indexing of Word and PDF documents.</li>
	<li>Wiki support</li>
	<li>Collaboration and sharing</li>
	<li>Automatic locking and unlocking</li>
	<li>Versioning, history and reverting content</li>
	<li>Authentication back-end</li>
	<li>Collections</li>
	<li>Multilingual content management</li>
	<li>Automatic previous/next navigation</li>
	<li>Human-readable URLs</li>
	<li>Caching proxy integration</li>
	<li>Drag and drop reordering of content</li>
	<li>Adjustable templates on content</li>
	<li>RSS feed support</li>
	<li>Automatic image scaling and thumbnail generation</li>
	<li>Comment capabilities on any content</li>
	<li>WebDAV and FTP support</li>
	<li>Hot -backup support</li>
</ul>
<strong>Extensions:</strong> 1490 add-ons.<p></p>

<p><strong>Distinguished clients:</strong></p>

<p></p><ul>
	<li><a href="http://www.amnesty.ch/en" target="_blank">http://www.amnesty.ch/en</a></li>
	<li><a href="http://www.brasil.gov.br/" target="_blank">http://www.brasil.gov.br/</a></li>
	<li><a href="http://www.chicagohistory.org/" target="_blank">http://www.chicagohistory.org/</a></li>
	<li><a href="http://ccnmtl.columbia.edu/" target="_blank">http://ccnmtl.columbia.edu/</a></li>
	<li><a href="http://cnx.org/" target="_blank">http://cnx.org/</a></li>
	<li><a href="http://discovermagazine.com/" target="_blank">http://discovermagazine.com/</a></li>
	<li><a href="http://www.ece.rice.edu/" target="_blank">http://www.ece.rice.edu/</a></li>
	<li><a href="http://www.engagemedia.org/" target="_blank">http://www.engagemedia.org/</a></li>
	<li><a href="http://science.nasa.gov/" target="_blank">http://science.nasa.gov/</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>It has a lot of features (<em>several times more than listed above</em>) built-in.</li>
	<li>To become a Plone expert is long and expensive. It has a steep learning curve.</li>
	<li>Plone is backed by Zope framework which is very powerful with support for caching, rollback, etc. - everything what your organization might need.</li>
	<li>Plone is really complex to deeply tweak.</li>
	<li>Plone is known for its high security.</li>
	<li>Plone runs slow if you don't know how to optimize it.</li>
</ul>
<h2>#12: eZ Publish</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://ez.no/" target="_blank"><img title="eZ Publish" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/ez.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site: </strong><a href="http://ez.no/" target="_blank">http://ez.no/</a></p>

<p>eZ Publish is an open source enterprise CMS developed by the Norwegian company eZ Systems in 1999 using PHP programming language. eZ Publish is freely available under the GPL licence, as well as under proprietary licenses that include commercial support. eZ Publish supports the development of customized web applications. Typical applications range from a personal homepage to a multilingual corporate website, which include role-based multi-user access, e-commerce functions and online communities.</p>

<p><strong>Weekly downloads:</strong> 7,031 (ranked #8 after TYPO3 and before Alfresco).</p>

<p><strong>Installations:</strong> 60 according to the survey (#11 after Concrete5 and before MODx), 0.1% of the Alexa Top 1 million sites (#9 after CMS Made Simple and before Plone).</p>

<p><strong>Brand Familiarity:</strong> #13 (after CMS Made Simple and before MODx).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Advanced Search feature is available in only Enterprise Edition.</li>
	<li>Online image editor.</li>
	<li>Can create building blocks for the site and later reuse them in several pages.</li>
</ul>
<strong>Distinguished clients:</strong><p></p>

<p></p><ul>
	<li><a href="http://www.schemexpert.com/" target="_blank">http://www.schemexpert.com/</a></li>
	<li><a href="http://www.ticotimes.net/" target="_blank">http://www.ticotimes.net/</a></li>
	<li><a href="http://jp.wsj.com/" target="_blank">http://jp.wsj.com/</a></li>
	<li><a href="http://www.laborange.fr/" target="_blank">http://www.laborange.fr/</a></li>
	<li><a href="http://canalstreet.canalplus.fr/" target="_blank">http://canalstreet.canalplus.fr/</a></li>
	<li><a href="http://www.hks.harvard.edu/" target="_blank">http://www.hks.harvard.edu/</a></li>
	<li><a href="http://www.vogue.com.au/" target="_blank">http://www.vogue.com.au/</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>The documentation is a bit limited especially there is almost no documentation for module development.</li>
</ul>
<h2>#13: Concrete 5</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://www.concrete5.org/" target="_blank"><img title="concrete5" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/concrete5.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site: </strong><a href="http://www.concrete5.org/" target="_blank">http://www.concrete5.org/</a></p>

<p><strong>Concrete5</strong> is an open source CMS started in 2003 as a rapid-design approach to building the now-defunct LewisAndClark200.org, the official site for the Ad Council's National Council for the Lewis &amp; Clark Bicentennial. Concrete5 is developed in PHP and is distributed under MIT software license.</p>

<p><strong>Weekly downloads:</strong> unavailable.</p>

<p><strong>Installations:</strong> 62 according to the survey (#10 after Alfresco and before eZ Publish), has less than 0.1% of the Alexa Top 1 million sites.</p>

<p><strong>Brand Familiarity:</strong> #20 (after TextPattern).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Integrated server side caching.</li>
	<li>Support for only MySQL.</li>
	<li>Inline content editing.</li>
	<li>Image editing tool.</li>
	<li>Editable areas are defined in concrete5 templates which allow editors to insert 'blocks' of content. Additional blocks are available as add-ons.</li>
	<li>Automatic upgrade is available.</li>
	<li>Advanced Permissions to track content versions.</li>
</ul>
<strong>Distinguished clients:</strong><p></p>

<p></p><ul>
	<li><a href="http://www.genco.com/" target="_blank">http://www.genco.com</a></li>
	<li><a href="http://www.cottonfrombluetogreen.org/" target="_blank">http://www.cottonfrombluetogreen.org/</a></li>
	<li><a href="http://www.cs.uh.edu/" target="_blank">http://www.cs.uh.edu/</a></li>
	<li><a href="http://www.signals.ca/" target="_blank">http://www.signals.ca/</a></li>
	<li><a href="http://www.paulraymondgregory.com/" target="_blank">http://www.paulraymondgregory.com</a></li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>It's PHP based and quite new but it's quite a nice layout and it's really natural for new CMS users. You can go from a paper-based sitemap and PSD to a full site structure, ready for data entry, within a day, two at a push.</li>
	<li>Concrete5 is simple, suitable for creating sites quickly.</li>
	<li>Creating template is very easy with Concrete5.</li>
</ul>
<h2>#14: Alfresco</h2><p></p>

<p></p><p style="text-align: center;"><a href="http://www.alfresco.com/" target="_blank"><img title="Alfresco" src="http://blog.cubrid.org/wp-content/uploads/2011/1-/alfresco.png" width="701" height="325" editor_component="image_link"/></a></p><p></p>

<p><strong>Official site: </strong><a href="http://www.alfresco.com/" target="_blank">http://www.alfresco.com/</a></p>

<p><strong>Alfresco</strong> is an open source enterprise content management system for Microsoft Windows and Unix-like operating systems. Alfresco includes a content repository, an out-of-the-box web portal framework for managing and using standard portal content, a CIFS interface that provides file system compatibility on Microsoft Windows and Unix-like operating systems, a web content management system capable of virtualizing web apps and static sites via Apache Tomcat, Lucene indexing, and jBPM workflow. The Alfresco system is developed using Java technology. John Newton (co-founder of Documentum) and John Powell (a former COO of Business Objects) founded Alfresco Software, Inc. in 2005.</p>

<p><strong>Weekly downloads:</strong> 7,000 (ranked #9 after Ez Publish and before Umbraco).</p>

<p><strong>Installations:</strong> 70 according to the survey (#9 after CMS Made Simple and before Concrete5) Alexa ranking is not available.</p>

<p><strong>Brand Familiarity:</strong> #9 (after Movable Type and before Tiki).</p>

<p><strong>Major Features:</strong></p>

<p></p><ul>
	<li>Document Management.</li>
	<li>Web Content Management (including full webapp &amp; session virtualization).</li>
	<li>Repository-level versioning (similar to Subversion).</li>
	<li>Records Management, including 5015.2 certification.</li>
	<li>Repository access via CIFS /SMB, FTP, Web DAV, NFS and CMIS.</li>
	<li>j BPM workflow.</li>
	<li><a title="Lucene" href="http://en.wikipedia.org/wiki/Lucene" target="_blank"></a>Advanced search with Lucene.</li>
	<li>Multi-language support.</li>
	<li>Officially runs on Windows, Linux and Solaris.</li>
	<li>User Interface official supports Internet Explorer and Firefox.</li>
	<li>Desktop integration with Microsoft Office and OpenOffice.org.</li>
	<li>Clustering support.</li>
	<li>Pluggable authentication: NTLM, LDAP, Kerberos, CAS.</li>
</ul>
<strong>Distinguished clients:</strong> no links are available but numerous case studies can be found on Alfresco home page.<p></p>

<p></p><ul>
	<li>France Air Force</li>
	<li>Harvard Business School Publishing</li>
	<li>Toyota</li>
	<li>Sony Pictures</li>
	<li>Fox</li>
	<li>National Academy of Sciences</li>
	<li>Cisco</li>
</ul>
<strong>What users say:</strong><p></p>

<p></p><ul>
	<li>Alfresco is mostly for enterprises rather than for personal sites.</li>
	<li>Simple to install and use, flexible and open-ended.</li>
	<li>Alfresco is a solution with the broadest range of technical capabilities and the best feedback from users. In addition to demonstrating a promising roadmap for collaboration tools, Alfresco was highly attractive from a cost perspective, compared to the proprietary products offered by other ECM vendors.</li>
	<li>All in one solution for enterprises.</li>
</ul>
<h2>See also</h2><p></p>

<p>Besides, the official home pages, you can refer to Wikipedia for&nbsp;general information on these content management systems. Also <a title="Stack Overflow" href="http://stackoverflow.com/" target="_blank">Stack Overflow</a> provides very informative users feedbacks on each of these CMS.</p>

<p></p><ol>
	<li><a href="http://en.wikipedia.org/wiki/Drupal" target="_blank">http://en.wikipedia.org/wiki/Drupal</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Joomla" target="_blank">http://en.wikipedia.org/wiki/Joomla</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Modx" target="_blank">http://en.wikipedia.org/wiki/Modx</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Wordpress" target="_blank">http://en.wikipedia.org/wiki/Wordpress</a></li>
	<li><a href="http://en.wikipedia.org/wiki/DotNetNuke" target="_blank">http://en.wikipedia.org/wiki/DotNetNuke</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Umbraco" target="_blank">http://en.wikipedia.org/wiki/Umbraco</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Liferay" target="_blank">http://en.wikipedia.org/wiki/Liferay</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Typo3" target="_blank">http://en.wikipedia.org/wiki/Typo3</a></li>
	<li><a href="http://en.wikipedia.org/wiki/CMS_Made_Simple" target="_blank">http://en.wikipedia.org/wiki/CMS_Made_Simple</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Movable_Type" target="_blank">http://en.wikipedia.org/wiki/Movable_Type</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Plone_(software" target="_blank">http://en.wikipedia.org/wiki/Plone_(software)</a></li>
	<li><a href="http://en.wikipedia.org/wiki/EZ_Publish" target="_blank">http://en.wikipedia.org/wiki/EZ_Publish</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Concrete5" target="_blank">http://en.wikipedia.org/wiki/Concrete5</a></li>
	<li><a href="http://en.wikipedia.org/wiki/Alfresco_(software" target="_blank">http://en.wikipedia.org/wiki/Alfresco_(software)</a></li>
	<li><a title="OPEN SOURCE CMS MARKET SHARE REPORT" href="http://www.waterandstone.com/sites/default/files/2010 OSCMS Report.pdf" target="_blank">http://www.waterandstone.com/sites/default/files/2010%20OSCMS%20Report.pdf</a></li>
	<li><a href="http://php.opensourcecms.com/" target="_blank">http://php.opensourcecms.com/</a></li>
	<li><a href="http://stackoverflow.com/" target="_blank">http://stackoverflow.com/</a></li>
</ol><p></p>]]></description>
                        <pubDate>Fri, 21 Jan 2011 12:22:43 +0900</pubDate>
                        <category>Wordpress</category>
                        <category>Joomla</category>
                        <category>CMS</category>
                        <category>content management system</category>
                        <category>Web 2.0</category>
                        <category>Drupal</category>
                        <category>Concrete5</category>
                        <category>MODx</category>
                        <category>DotNetNuke</category>
                        <category>Liferay</category>
                        <category>TYPO3</category>
                        <category>CMS Made Simple</category>
                        <category>MOVABLE TYPE</category>
                        <category>Plone</category>
                        <category>eZ Publish</category>
                        <category>Alfresco</category>
                        <category>Umbraco</category>
                                    <slash:comments>9</slash:comments>
                    </item>
            </channel>
</rss>

