<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom">
   <title type="text">CUBRID Blog</title>
      <subtitle type="html">Latest stories in the CUBRID Blog</subtitle>
      <updated>2013-05-19T04:43:06-07:00</updated>
   <id>http://www.cubrid.org/blog/textyle/atom</id>
   <link rel="alternate" type="text/html" hreflang="en" href="http://blog.cubrid.org"/>
   <link rel="self" type="application/atom+xml" href="http://www.cubrid.org/blog/textyle/atom"/>
   <generator uri="http://www.xpressengine.com/" version="1.4.4.1">XpressEngine</generator>
   <entry>
      <title>PostgreSQL at a glance</title>
      <id>http://www.cubrid.org/blog/656497</id>
      <published>2013-05-13T23:33:08-07:00</published>
      <updated>2013-05-13T23:33:08-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/656497"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/656497#comment"/>
      <author>
         <name>Kim Sung Kyu</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;PostgreSQL shows excellent functionalities and performance.&amp;nbsp;Considering its high quality, it may seem strange that PostgreSQL is not more popular. However, PostgreSQL continues to make progress. This article will discuss this database.&lt;/p&gt;
&lt;h2&gt;Why You Should Know about PostgreSQL&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.postgresql.org&quot;&gt;PostgreSQL&lt;/a&gt; is an RDBMS, which is popular mainly in North America and Japan. It is not used much in Korea yet, but as it is a very excellent RDBMS in terms of functionality and performance, it is worth learning about what kind of database PostgreSQL is.&lt;/p&gt;
&lt;p&gt;PostgreSQL (&lt;i&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/PostgreSQL#Product_name&quot;&gt;pronounced&lt;/a&gt; as [Post-Gres-Q-L]&lt;/i&gt;) is an object-relational database system (ORDBMS), and is an open-source DBMS that provides the enterprise-level DBMS functionalities and many other functionalities you can find only in advanced DBMS. PostgreSQL is also known as an open-source DBMS that Oracle users can adapt themselves to the most easily, as it has many functionalities similar to those of Oracle.&lt;/p&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;There were many ancestors of PostgreSQL, and of them, &lt;a href=&quot;https://en.wikipedia.org/wiki/Ingres_(database)&quot;&gt;Ingres&lt;/a&gt;&amp;nbsp;(&lt;i&gt;INteractive Graphics REtrieval System&lt;/i&gt;) can be said to be the progenitor of PostgreSQL. Ingres was a project launched by &lt;a href=&quot;https://en.wikipedia.org/wiki/Michael_Stonebraker&quot;&gt;Michael Stonebraker&lt;/a&gt;&amp;nbsp;(&lt;b&gt;Picture 1&lt;/b&gt;), a great master in the area of databases who is still working hard even today.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; height=&quot;213&quot; width=&quot;320&quot; alt=&quot;320px-Michael_Stonebraker_1.jpg&quot; src=&quot;/files/attach/images/220547/497/656/320px-Michael_Stonebraker_1.jpg&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Picture 1: Michael Stonebraker started Ingres project.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The Ingres project was launched at Berkeley University in the US in 1977. After Ingres&amp;nbsp;Michael Stonebraker had started&amp;nbsp;another project called Postgres (&lt;i&gt;Post-Ingres&lt;/i&gt;). As Postgres version 3 was released in 1991, its user base grew to be quite large. But as the burden of providing support to users became too high, the project was terminated in 1993 (&lt;i&gt;Postgres is known to have had a huge influence on the current Informix product, even after the end of the project. Illustra, a commercial version of POSTGRES, was taken over by Informix in 1997, and then by IBM in 2001.&lt;/i&gt;).&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/497/656/postgresql_history.png&quot; alt=&quot;postgresql_history.png&quot; width=&quot;470&quot; height=&quot;180&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1:&amp;nbsp;Product History.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Despite the project having ended, Postgres users and students continued its development and finally created Postgres95, which achieved 40% better performance than Postgres by supporting SQL and improving its structure.&lt;/p&gt;
&lt;p&gt;When Postgre95 became an open-source system in 1996, it was given the name PostgreSQL, its current name, to reflect the fact that it succeeded Postgres and supports SQL (&lt;i&gt;Postgres supported a language called QUEL instead of SQL&lt;/i&gt;). In 1997, PostgreSQL was finally released after determining its first version as 6.0.&lt;/p&gt;
&lt;p&gt;Since then, PostgreSQL has been actively developed to this day through an open-source community, and the latest release is 9.2, as of May 2013.&amp;nbsp;In addition, due to its open license (&lt;i&gt;like the BSD or MIT license, PostgreSQL allows commercial use and modification, but it also clarifies that the original developers are not liable for any problem that may occur in its use&lt;/i&gt;), there have been more than 20 various forks, some of which have had an influence on PostgreSQL and some of which have disappeared.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/attach/images/220547/497/656/postgresql_logo.png&quot; alt=&quot;postgresql_logo.png&quot; width=&quot;64&quot; height=&quot;66&quot; style=&quot;float: left; margin-right: 10px;&quot; /&gt;PostgreSQL&apos;s logo is an elephant named &apos;&lt;em&gt;Slonik&lt;/em&gt;&apos; (&lt;i&gt;a baby elephant in Russian language&lt;/i&gt;). The true reason why an elephant was used for the logo is not known, but it has been said that just after it became an open-source system, one of its users was inspired by Agatha Christie&apos;s novel &quot;Elephants Can Remember&quot; and suggested it. Since then, the elephant logo has been visible at every official PostgreSQL event.&lt;/p&gt;
&lt;p&gt;As elephants are thought of as large, strong, reliable and have a good memory, Hadoop and Evernote also use an elephant as their official logo.&lt;/p&gt;
&lt;h2&gt;Functionalities and Limitations&lt;/h2&gt;
&lt;p&gt;PostgreSQL supports transaction and &lt;a href=&quot;http://en.wikipedia.org/wiki/ACID&quot;&gt;ACID&lt;/a&gt;, which are the basic functionalities of a relational DBMS. Moreover, PostgreSQL also has many progressive functionalities or expanded functionalities for academic research as well as for basic reliability and stability.&amp;nbsp;Even a general list of PostgreSQL functionalities includes a large number of functionalities.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nested transactions (savepoints)&lt;/li&gt;
&lt;li&gt;Point in time recovery&lt;/li&gt;
&lt;li&gt;Online/hot backups, Parallel restore&lt;/li&gt;
&lt;li&gt;Rules system (query rewrite system)&lt;/li&gt;
&lt;li&gt;B-tree, R-tree, hash, GiST method indexes&lt;/li&gt;
&lt;li&gt;Multi-Version Concurrency Control (MVCC)&lt;/li&gt;
&lt;li&gt;Tablespaces&lt;/li&gt;
&lt;li&gt;Procedural Language&lt;/li&gt;
&lt;li&gt;Information Schema&lt;/li&gt;
&lt;li&gt;I18N, L10N&lt;/li&gt;
&lt;li&gt;Database &amp;amp; Column level collation&lt;/li&gt;
&lt;li&gt;Array, XML, UUID type&lt;/li&gt;
&lt;li&gt;Auto-increment (sequences),&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Asynchronous replication&lt;/li&gt;
&lt;li&gt;LIMIT/OFFSET&lt;/li&gt;
&lt;li&gt;Full text search&lt;/li&gt;
&lt;li&gt;SSL, IPv6&lt;/li&gt;
&lt;li&gt;Key/Value storage&lt;/li&gt;
&lt;li&gt;Table inheritance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition to these, it features a variety of functionalities and new functionalities of enterprise-level DBMS.&lt;/p&gt;
&lt;p&gt;In general, PostgreSQL has the following limits:&lt;/p&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;caption&gt;Table 1: Basic Limits of PostgreSQL.&lt;/caption&gt; &lt;thead&gt; 
&lt;tr&gt;
&lt;th&gt;Limit&lt;/th&gt; &lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Max. Database Size&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max. Table Size&lt;/td&gt;
&lt;td&gt;32 TB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max. Row Size&lt;/td&gt;
&lt;td&gt;1.6 TB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max. Field Size&lt;/td&gt;
&lt;td&gt;1 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max. Rows per Table&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max. Columns per Table&lt;/td&gt;
&lt;td&gt;250~1600&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max. Indexes per Table&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Roadmap&lt;/h2&gt;
&lt;p&gt;As of May 2013, the latest release is 9.2. &lt;b&gt;Figure 2&lt;/b&gt; provides some brief information on the progress of PostgreSQL by year.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/497/656/progress_of_postgresql_by_year.png&quot; alt=&quot;progress_of_postgresql_by_year.png&quot; width=&quot;430&quot; height=&quot;108&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 2:&amp;nbsp;Progress of PostgreSQL by Year.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The main functionalities of each version are as follows:&lt;/p&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;caption&gt;Table 2:&amp;nbsp;Main Functionalities by Version.&lt;/caption&gt;&lt;thead&gt; 
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;&lt;th&gt;Release Year&lt;/th&gt;&lt;th&gt;Main Functionalities&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.01&lt;/td&gt;
&lt;td&gt;1995&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Postgres95 release&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;1995&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Copyright change, open source&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6.0~6.5&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;&lt;span style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;1997~1999&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Renamed PostgreSQL&lt;/li&gt;
&lt;li&gt;Index, VIEWs and RULEs&lt;/li&gt;
&lt;li&gt;Sequences, Triggers&lt;/li&gt;
&lt;li&gt;Genetic Query Optimizer&lt;/li&gt;
&lt;li&gt;Constraints, Subselect&lt;/li&gt;
&lt;li&gt;MVCC, JDBC interface,&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7.0~7.4&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2000~2010&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Foreign keys&lt;/li&gt;
&lt;li&gt;SQL92 syntax JOINs&lt;/li&gt;
&lt;li&gt;Write-Ahead Log&lt;/li&gt;
&lt;li&gt;Information Schema, Internationalization&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.0~8.4&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2005~2012&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Native Support for MS Windows&lt;/li&gt;
&lt;li&gt;Savepoint, Point-in-time recovery&lt;/li&gt;
&lt;li&gt;Two-phase commit&lt;/li&gt;
&lt;li&gt;Table spaces, Partitioning&lt;/li&gt;
&lt;li&gt;Full text search&lt;/li&gt;
&lt;li&gt;Common table expressions (CTE)&lt;/li&gt;
&lt;li&gt;SQL/XML, ENUM, UUID Type&lt;/li&gt;
&lt;li&gt;Window functions&lt;/li&gt;
&lt;li&gt;Per-database collation&lt;/li&gt;
&lt;li&gt;Replication, Warm standby&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.0&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2010-09&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Streaming replication, Hot standby&lt;/li&gt;
&lt;li&gt;Support for 64bit MS Windows&lt;/li&gt;
&lt;li&gt;Per-column conditional trigger&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.1&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2011-09&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Functionality differentiation&lt;/li&gt;
&lt;li&gt;Synchronous replication&lt;/li&gt;
&lt;li&gt;Per-column collations&lt;/li&gt;
&lt;li&gt;Unlogged tables&lt;/li&gt;
&lt;li&gt;K-nearest-neighbor indexing&lt;/li&gt;
&lt;li&gt;Serializable isolation level&lt;/li&gt;
&lt;li&gt;Writeable CTE (WITH)&lt;/li&gt;
&lt;li&gt;SQL/MED External Data&lt;/li&gt;
&lt;li&gt;SE-Linux integration&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.2&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;2012-09&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Performance optimization&lt;/li&gt;
&lt;li&gt;linear scalability to 64 cores&lt;/li&gt;
&lt;li&gt;Reduction in CPU power consumption&lt;/li&gt;
&lt;li&gt;Cascade streaming replication&lt;/li&gt;
&lt;li&gt;JSON, Range Type&lt;/li&gt;
&lt;li&gt;Improved lock management&lt;/li&gt;
&lt;li&gt;Space-partitioned GiST index&lt;/li&gt;
&lt;li&gt;Index-only scans (covering)&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The next PostgreSQL release under development is PostgreSQL 9.3, which is due to be released in the third quarter of 2013. This release features &lt;a href=&quot;http://wiki.postgresql.org/wiki/Todo&quot;&gt;many functionalities&lt;/a&gt;, including an enhanced management functionality, parallel query, MERGE/UPSERT, multi-master replication, materialized view, and enhanced multi-language support.&lt;/p&gt;
&lt;h2&gt;Internal Structure&lt;/h2&gt;
&lt;p&gt;The following shows the process structure:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/497/656/postgresql_process_structure.png&quot; alt=&quot;postgresql_process_structure.png&quot; width=&quot;430&quot; height=&quot;282&quot; /&gt;&lt;br /&gt;&lt;b&gt;Figure 3:&amp;nbsp;Process Structure.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;If the client requests connection with the server through the&amp;nbsp;(1)&amp;nbsp;interface library (&lt;i&gt;variety of Interfaces Including libpg, JDBC and ODBC&lt;/i&gt;), the Postmaster process relays connection with the server (2). Then, the client executes a query through connection with the allocated server (&lt;b&gt;Figure 3&lt;/b&gt;).&lt;/p&gt;
&lt;p&gt;The following shows the process of query execution in the server:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/attach/images/220547/497/656/postgresql_query_execution_procedure.png&quot; alt=&quot;postgresql_query_execution_procedure.png&quot; width=&quot;430&quot; height=&quot;360&quot; style=&quot;text-align: center; display: block; margin-left: auto; margin-right: auto;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 4:&amp;nbsp;Query Execution Procedure.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;If it receives a query request from the client, the system creates a parse tree through the syntax analytics process (1), starts a new transaction through the semantic checking process (2) and creates a query tree.&lt;/p&gt;
&lt;p&gt;Next, a query tree is re-generated according to the rules defined in the server (3), and of the many available execution plans, the most optimized plan tree is created (4). The server executes this (5) and sends the result of the requested query to the client.&lt;/p&gt;
&lt;p&gt;While the server executes a query, a system catalog in the database is frequently used. In the system catalog, users can directly define the type of functions and data, as well as index access methods and rules. In PostgreSQL, therefore, a system catalog is utilized as an important point in adding or expanding its functionalities.&lt;/p&gt;
&lt;p&gt;A file that stores data consists of multiple pages, and a single page has a scalable slotted page structure (Figures 5 and 6).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/attach/images/220547/497/656/postgresql_data_page_structure.png&quot; alt=&quot;postgresql_data_page_structure.png&quot; width=&quot;430&quot; height=&quot;288&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 5: Data Page Structure.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/attach/images/220547/497/656/postgresql_index_page_structure.png&quot; alt=&quot;postgresql_index_page_structure.png&quot; width=&quot;700&quot; height=&quot;488&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 6:&amp;nbsp;Index Page Structure.&lt;/b&gt;&lt;/p&gt;
&lt;h2&gt;Development Process&lt;/h2&gt;
&lt;p&gt;The development process model of PostgreSQL can be explained by the following sentence:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;lsquo;A community-based open-source project led by a few.&amp;rsquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Like the Linux, Apache and Eclipse projects, the PostgreSQL project is also composed only of a few administrators, a variety of developers and a large number of users. The small administrator group (Core Team) collects requests and feedback (&lt;i&gt;the group sometimes takes a vote to determine priorities at &lt;a href=&quot;http://postgresql.uservoice.com&quot;&gt;http://postgresql.uservoice.com&lt;/a&gt;&lt;/i&gt;) from a large number of users, determines the direction of the product, has final approval right for the code and exerts its right for release.&amp;nbsp;This is a different model from corporate management development processes such as MySQL and JBoss.&lt;/p&gt;
&lt;p&gt;The developer group consists of code committers and code developers/contributors. They are located in many countries, including the U.S., Japan and Europe.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; height=&quot;300&quot; width=&quot;645&quot; alt=&quot;distribution_of_postgresql_developers_by_region.png&quot; src=&quot;/files/attach/images/220547/497/656/distribution_of_postgresql_developers_by_region.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 7: Distribution of PostgreSQL Developers by Region.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Codes developed by a variety of developers go through a variety of review processes (&lt;i&gt;Submission Review, Usability Review, Feature Test, Performance Review, Coding Review, Architecture Review, Review Review&lt;/i&gt;), and are reflected in the product after approval by the Core Team. The mailing list that has been used by the community for a long time is usually used, and a variety of documents, including manuals, are well maintained through the &lt;a href=&quot;http://www.postgresql.org&quot;&gt;official website&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Products in Competition&lt;/h2&gt;
&lt;p&gt;PostgreSQL wants to be compared with enterprise-level commercial DBs, but it has been compared mainly with popular open-source DBMSs. The following are the catchphrases of these open-source DBMSs, each of which reflects its features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;PostgreSQL&lt;/b&gt;: The world&apos;s most advanced open source database&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MySQL&lt;/b&gt;: The world&apos;s most popular open source database&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CUBRID&lt;/b&gt;: Open Source Database Highly Optimized for Web Applications&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Firebird&lt;/b&gt;: The true open source database&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SQLite&lt;/b&gt;: self-contained library, serverless, zero-configuration, transactional SQL database engine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is not easy to compare these products using their catchphrases alone, but you can see that PostgreSQL seeks progressiveness and openness.&lt;/p&gt;
&lt;p&gt;The following is brief comparison of PostgreSQL and its competitiors:&lt;/p&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;caption&gt;Table 3: Comparison of Products in Competition.&lt;/caption&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Oracle&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;An enormous amount of long-proven code and a variety of references.&lt;/li&gt;
&lt;li&gt;High cost&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB2,&amp;nbsp;MS SQL&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Similar to Oracle&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;A variety of applications and references.&lt;/li&gt;
&lt;li&gt;Corporate development model&lt;/li&gt;
&lt;li&gt;And the burden of licensing&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CUBRID&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;An alternative to MySQL&lt;/li&gt;
&lt;li&gt;Built-in HA and database sharding&lt;/li&gt;
&lt;li&gt;Dual licensing&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other commercial DBs&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Other commercial DBs show a downtrend due to open-source DBMSs&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Other open source DBs&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Struggle to attract developers&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For a long time, the PostgreSQL community has made attempts to enter the enterprise DBMS market. In 2004, &lt;a href=&quot;http://www.enterprisedb.com&quot;&gt;EnterpriseDB&lt;/a&gt;, a company using PostgreSQL, was established, and it is striving to strengthen its position in the enterprise DBMS market. One of the company&apos;s main products is Postgres Plus Advanced Server. Postgres Plus Advanced Server was developed by adding Oracle-compatible functionalities (&lt;i&gt;PL/SQL, SQL statements, functions, DB Links, OCI library, etc.&lt;/i&gt;) to the open-source PostgreSQL, featuring easy data and application migration and a cost reduction of 20% compared to Oracle (&lt;b&gt;Figure 7&lt;/b&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; height=&quot;362&quot; width=&quot;426&quot; alt=&quot;postgresql_cost_reduction_compared_to_oracle.png&quot; src=&quot;/files/attach/images/220547/497/656/postgresql_cost_reduction_compared_to_oracle.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 8:&amp;nbsp;Cost Reduction Compared to Oracle.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;In addition, Postgres Plus Advanced Server provides differentiated services, including a training, consulting and migration, and technical support service from PostgreSQL experts. Through approximately 300 reference sites in a variety of areas, the product is promoted as a database for all industries, with a growing base of users across the world.&lt;/p&gt;
&lt;h2&gt;Present Status and Trend&lt;/h2&gt;
&lt;p&gt;As you can see from most posts on PostgreSQL, most PostgreSQL users have a developer-like tendency, and are very loyal to the product.&lt;/p&gt;
&lt;p&gt;In fact, they have a good reason for their loyalty. PostgreSQL provides sufficient functionalities and conservative performance compared to other products, and one of its advantages is that it has good enough conditions for beginners to attract new developers.&lt;/p&gt;
&lt;p&gt;These good conditions include a well-written manual on the project page, related documents, over 300 reference publications, and over 10 seminars and conferences held in a variety of countries every year. More recently, a PostgreSQL magazine has even appeared. And these are the results of the active PostgreSQL community.&lt;/p&gt;
&lt;p&gt;The representative features that PostgreSQL users identify as being important are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Reliability&lt;/b&gt;&amp;nbsp;is the top priority of the product&lt;/li&gt;
&lt;li&gt;ACID and transaction&lt;/li&gt;
&lt;li&gt;A variety of indexing techniques&lt;/li&gt;
&lt;li&gt;Flexible full-text search&lt;/li&gt;
&lt;li&gt;MVCC for better concurrency performance&lt;/li&gt;
&lt;li&gt;Diverse and flexible replication methods&lt;/li&gt;
&lt;li&gt;A variety of procedures (&lt;i&gt;PL/pgSQL, Perl, Python, Ruby, TCL, etc.&lt;/i&gt;)/Interface (&lt;i&gt;JDBC, ODBC, C/C++, .Net, Perl, Python, etc.&lt;/i&gt;) languages&lt;/li&gt;
&lt;li&gt;Excellent community and commercial support&lt;/li&gt;
&lt;li&gt;Well-made documents and a thorough manual&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A variety of expansion functionalities and ease of development of such functionalities are also advantages of PostgreSQL. The following are the differentiated expansion functionalities of PostgreSQL:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GIS add-on (PostGIS)&lt;/li&gt;
&lt;li&gt;Key-Value store expansion (HStore)&lt;/li&gt;
&lt;li&gt;DBLink&lt;/li&gt;
&lt;li&gt;Support for a variety of functions and types, including Crypto and UUID&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are&amp;nbsp;many&amp;nbsp;other practical and experimental expansion functionalities as well.&lt;/p&gt;
&lt;p&gt;Of these, you will see a brief account of GIS (&lt;i&gt;Geographic Information System&lt;/i&gt;), which has recently become a hot topic. &lt;a href=&quot;http://postgis.refractions.net&quot;&gt;PostGIS&lt;/a&gt;&amp;nbsp;is a middleware expansion functionality that enables PostgreSQL to conform to the &lt;a href=&quot;http://www.opengeospatial.org/standards/sfs&quot;&gt;OpenGIS standard&lt;/a&gt; and support geographic objects (&lt;b&gt;Figure 9&lt;/b&gt;).&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;239&quot; width=&quot;204&quot; alt=&quot;postgis_structure.png&quot; src=&quot;/files/attach/images/220547/497/656/postgis_structure.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 9:&amp;nbsp;PostGIS Structure.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;PostGIS began to be developed from 2001, and with many functionality and performance improvements, it currently has the most users among the open-source products. There are some commercial products, such as Oracle Spatial, DB2 and MS SQL Server, but the commercial products have not been as well-received in terms of price-performance ratio.&lt;/p&gt;
&lt;p&gt;In addition, you can easily find benchmark data that shows that the functionalities and performance of PostGIS/PostgreSQL are worthy of comparison to Oracle.&lt;/p&gt;
&lt;p&gt;According to the recent trend, PostgreSQL is also much talked about in relation to cloud as well as GIS. With the recent increase in the number of companies providing DBaaS (&lt;i&gt;Database as a Service&lt;/i&gt;), the demand for PostgreSQL, which has advantages in terms of costs and license, has increased, and as such EnterpriseDB has released Postgres Plus Cloud Database in the cloud market, with the following features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simple setup &amp;amp; web-based management&lt;/li&gt;
&lt;li&gt;Automatic scaling, load balancing and failover&lt;/li&gt;
&lt;li&gt;Automated online backup&lt;/li&gt;
&lt;li&gt;Database Cloning&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is used in many web services, including Amazon EC2, Eucalyptus cloud, and Red Hat Openshift development platform cloud. Other cloud service providers such as Heroku and dotCloud also provide services using PostgreSQL.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As Sun, which had acquired MySQL, was acquired by Oracle in 2009, MySQL began to be developed as a more closed corporate project, and many MySQL developers left the community around the same time. Afraid of this change, MySQL users are paying attention not only to the forks (&lt;i&gt;MariaDB, Drizzle, Percona, etc.&lt;/i&gt;) of MySQL to which they can easily migrate, but also to the migration to PostgreSQL.&lt;/p&gt;
&lt;p&gt;Looking at the trend of help-wanted ads related to PostgreSQL and MySQL in the most popular job finding portal &lt;a href=&quot;http://www.indeed.com&quot;&gt;http://www.indeed.com&lt;/a&gt;&amp;nbsp;(&lt;b&gt;Figure 9&lt;/b&gt;), we can see the increase in help-wanted ads related to MySQL is slowing down, while help-wanted ads related to PostgreSQL continue to increase.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;206&quot; width=&quot;388&quot; alt=&quot;trend_of_help_wanted_ads.png&quot; src=&quot;/files/attach/images/220547/497/656/trend_of_help_wanted_ads.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 10:&amp;nbsp;Trend of Help-wanted Ads.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;According to the trend of search frequency in search sites (&lt;b&gt;Figure 10&lt;/b&gt;), MySQL shows a continued downtrend, while PostgreSQL seems to have almost no change. In Korea, however, the search frequency for PostgreSQL has shown an upward trend since mid 2010.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;208&quot; width=&quot;430&quot; alt=&quot;search_frequency_trend.png&quot; src=&quot;/files/attach/images/220547/497/656/search_frequency_trend.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 11: Search Frequency Trend&lt;/b&gt; (&lt;a href=&quot;http://trend.naver.com/trend.naver?where=trend&amp;amp;mobile=0&amp;amp;startDate=200701&amp;amp;endDate=201210&amp;amp;dtype=&amp;amp;query1=postgresql&amp;amp;query2=&amp;amp;query3=&amp;amp;query4=&amp;amp;query5=&quot;&gt;source&lt;/a&gt;)&lt;b&gt;.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Of course, the popularity and usage of MySQL is still much higher than PostgreSQL. Although you may not be able to determine the true status or prospects of these products from the above data alone, you could infer that if the popularity of MySQL declines, the popularity of PostgreSQL will increase.&lt;/p&gt;
&lt;p&gt;PostgreSQL is not yet powerful enough to surpass MySQL in popularity, but the PostgreSQL open source project community continues to make the following efforts:&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Improvement of the reliability of basic DBMS functionalities&lt;/li&gt;
&lt;li&gt;Provision of progressive and differentiated functionality expansion&lt;/li&gt;
&lt;li&gt;Continuous attraction of more open source developers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition, EnterpriseDB, which has stronger business purposes, is also striving to achieve the following objectives:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Expansion of its share in the enterprise market&lt;/li&gt;
&lt;li&gt;Expansion of its share in the cloud market&lt;/li&gt;
&lt;li&gt;Efforts to replace Oracle and MySQL&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By &lt;a href=&quot;/?mid=community&amp;amp;act=dispMemberInfo&amp;amp;member_srl=656646&amp;amp;tab=blogs&quot;&gt;Kim Sung Kyu&lt;/a&gt;, Senior Software Engineer at CUBRID DBMS Lab, NHN Corporation.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;&lt;/div&gt;</content>
                  <category term="PostgreSQL"/>
            <category term="ORDBMS"/>
            <category term="RDBMS"/>
            <category term="comparison"/>
            
   </entry>
   <entry>
      <title>My impressions after giving talks at RIT++ and Percona conferences</title>
      <id>http://www.cubrid.org/blog/650820</id>
      <published>2013-05-12T22:58:31-07:00</published>
      <updated>2013-05-12T23:23:39-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/650820"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/650820#comment"/>
      <author>
         <name>Esen Sagynov</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&lt;img style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; height=&quot;120&quot; width=&quot;366&quot; alt=&quot;rit_percona_conference_logo.png&quot; src=&quot;/files/attach/images/220547/820/650/rit_percona_conference_logo.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Three weeks ago&amp;nbsp;on behalf of&amp;nbsp;the CUBRID team&amp;nbsp;a few of my colleagues and me have attended and given talks at two international conferences.&amp;nbsp;Today I would like to share my impressions of these events. I will write a separate post about various sharding solutions introduced at these conferences. So, stay tuned!&lt;/p&gt;
&lt;h2&gt;RIT++&lt;/h2&gt;
&lt;p&gt;The first presentation at RIT++ (Russian Internet Technologies) was held on Monday April 22nd, 2013, in Moscow, Russia. The second one at Percona MySQL Conference &amp;amp; Expo was held on Wednesday the same week on Wednesday April 24th, 2013, in Santa Clara, CA,&amp;nbsp;US. At both conferences the agenda was the same: &quot;Easy MySQL Database Sharding with CUBRID SHARD&quot;. At RIT++, though, the presentation was given in Russian language. Very exciting! The following is a list of resouces related to the talks.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/cubrid-life/cubrid-shard-talk-at-2013-percona-mysql-conference-dont-miss/&quot;&gt;The presentation abstract in English&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ritconf.ru/2013/abstracts/560.html&quot;&gt;The presentation abstract in Russian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.slideshare.net/cubrid/easy-mysql-database-sharding-with-cubrid-shard-2013-percona&quot;&gt;Slideshare in English&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.slideshare.net/cubrid/mysql-cubrid-shard-2013-rit&quot;&gt;Slideshare in Russian&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was the third time we, the CUBRID team, have attended the conferences organized by&amp;nbsp;Russian&amp;nbsp;Ontico company. Previously we have attended to&amp;nbsp;&lt;a href=&quot;/blog/cubrid-life/meet-cubrid-developers-at-russian-internet-technologies-2012-conference/&quot;&gt;RIT++ 2012&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href=&quot;/blog/cubrid-life/database-sharding-the-right-way-easy-reliable-open-source/&quot;&gt;HighLoad++ 2012&lt;/a&gt;&amp;nbsp;conferences.&amp;nbsp;This year at RIT++ 2013 there were over 800 attendees, and 13 categories of talks ranging from client-side development to server-side, to database scalability, to project management, to analytics, and so on. Annually after the conference is over the organizers conduct after-event survey and&amp;nbsp;assess the past experience. I think because of users&apos; past feedback this year RIT++ organizers have accepted more talks related to client-side development than usually.&lt;/p&gt;
&lt;p&gt;Besides us from Korea, there were presenters from the States, representing Facebook, and Brasil, representing PUC-Rio University of Brasil. My personal impression was that&amp;nbsp;this year there were fewer&amp;nbsp;foreign speakers than last year at &lt;a href=&quot;/blog/cubrid-life/meet-cubrid-developers-at-russian-internet-technologies-2012-conference/&quot;&gt;RIT++&lt;/a&gt; or &lt;a href=&quot;/blog/cubrid-life/database-sharding-the-right-way-easy-reliable-open-source/&quot;&gt;HighLoad++&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At my session about MySQL database sharding with CUBRID SHARD there were over 100, close to 150, I guess attendees. The audience welcomed my speech in Russian language very well. Next time I should talk in Russian again. They like it! When the presentation was over, there were slew of questions. I think CUBRID SHARD as an easy sharding middleware for MySQL was received very well.&lt;/p&gt;
&lt;p&gt;To my surprise there were many questions unrelated to CUBRID SHARD. The audience asked a lot about CUBRID itself and its HA feature. Later I learned that many&amp;nbsp;attendees listened to my talks about&amp;nbsp;&lt;a href=&quot;http://www.cubrid.org&quot;&gt;CUBRID&lt;/a&gt; open source relational database system&amp;nbsp;from the last year. One from the audience said that he&apos;d been looking into CUBRID for a while already and was considering to use it in production. His most favorite feature in CUBRID was its built-in support for HA and very clever 3-tier architecture. Overall the unofficial Q&amp;amp;A session lasted for over 1 hour 30 minutes.&lt;/p&gt;
&lt;p&gt;It was a great experience for me to present CUBRID SHARD at RIT++ this year and a great opportunity to our CUBRID team. The conference lasted two days, but I could not attend the second day as I had to head to Santa Clara, CA, to give a talk at Percona MySQL Conference &amp;amp; Expo.&lt;/p&gt;
&lt;h2&gt;Percona&lt;/h2&gt;
&lt;p&gt;It was the first time I have talked at Percona. Previously we have spoken at &lt;a href=&quot;/blog/news/cubrid-will-present-at-oscon-2011/&quot;&gt;OSCON 2011&lt;/a&gt;&amp;nbsp;about &lt;a href=&quot;/cubrid_ha_oscon&quot;&gt;CUBRID HA&lt;/a&gt;, and &lt;a href=&quot;/blog/cubrid-life/mysql-conference-outcome/&quot;&gt;2010 MySQL Conference &amp;amp; Expo&lt;/a&gt;&amp;nbsp;about CUBRID Database. When compared to OSCON, Percona MySQL conference was a lot more specific (obviously about MySQL). There were more quality talks about scalability and performance tuning. If I was to choose where to go next year, I would definitly select Percona. That interesting it was!&lt;/p&gt;
&lt;p&gt;Unlike at RIT++, our session at Percona conference had attracted only about 20 attendees. The presentation went well, but I should accept that the number of listeners plays a big role. There were fewer questions, less enthusiasm. On the other hand, Facebook, two Percona, Continuent, and&amp;nbsp;Tokutek presentations, which were held at the same time at 3:30 PM, attracted hundreds of listeners each. After realizing this I came to a conclusion that it is the brand recognition that plays a significant role in attracting listeners. Even though NHN is very popular in Korea and Asia in general, it is almost unknown in Western countries. In fact, when I asked the audience at Percona if they had ever heard about NHN, their answer was negative. Very pitty. I think NHN has to seriously reconsider its&amp;nbsp;strategy on increasing its&amp;nbsp;worldwide brand recognition.&amp;nbsp;Nevertheless, I am very glad we had this chance to present our open source sharding middleware at a well-known conference like Percona.&lt;/p&gt;
&lt;p&gt;Like I mentioned at the beginning of this post, I will write another post covering various sharding solutions presented at Percona conference. It was very interesting to learn about different techniques used by large scale service providers who have developed their own sharding solutions.&lt;/p&gt;
&lt;p&gt;After my presentation was over and I had answered all the questions, I headed to one of the lounge rooms where I had made an oppointment to meet with Ryan Walsh, a Corporate Account Executive at Percona. We have discussed about various opportunities for cooperation between Percona and &lt;a href=&quot;/blog/tags/NHN&quot;&gt;NHN&lt;/a&gt;, the company behind CUBRID development.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.percona.com/&quot;&gt;Persona&lt;/a&gt; is a widely-known and reputable MySQL support and consulting company. It is known to be the oldest and largest independent company which provides not only MySQL support, consulting and training but also&amp;nbsp;&lt;a href=&quot;http://www.percona.com/development/mysql&quot;&gt;develops a custom MySQL server&lt;/a&gt;, i.e. provides patches, &quot;backport changes to older MySQL versions to obtain a key patch without a full version upgrade&quot;.&lt;/p&gt;
&lt;p&gt;During our conversation Rayn had introduced his company and told about large scale cases their company has worked so far. One that I would like to mention today is that some of the services at Amazon Web Services have been actually developed by Percona. Amazon RDS was said to have been developed by Percona team. Percona database tools &lt;a href=&quot;https://forums.aws.amazon.com/message.jspa?messageID=318349&quot;&gt;seem to work with RDS&lt;/a&gt; natively.&lt;/p&gt;
&lt;p&gt;Also Percona is &lt;a href=&quot;https://www.percona.com/live/mysql-conference-2013/sessions/using-percona-server-database-service-openstack&quot;&gt;cooperating&lt;/a&gt; with HP to build RedDwarf DaaS&amp;nbsp;as part of the OpenStack open source cloud project. At Percona conference HP engineers have presented how to use RedDwarf&amp;nbsp;APIs to use and administer the features of Percona Server.&amp;nbsp;Such vast knowledge and experience of Percona in bulding cloud database services may be quite benefitial to NHN to develop and provide its own cloud computing service.&lt;/p&gt;
&lt;p&gt;Overall, both presentations went well. I have talked to many attendees and answered to quite a lof of their questions about CUBRID SHARD and CUBRID Database. One thing which requires more attention from NHN is its global brand recognition. The more developers will recognize NHN and its services, the more will be eager to listen to and learn from NHN enginneers.&lt;/p&gt;
&lt;p&gt;If you have any feedback or suggestions, feel free to comment below. Also you should follow us on twitter &lt;a href=&quot;http://twitter.com/cubrid&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="conference"/>
            <category term="RIT++"/>
            <category term="Percona"/>
            <category term="Sharding"/>
            <category term="NHN"/>
            
   </entry>
   <entry>
      <title>NoSQL Benchmarking</title>
      <id>http://www.cubrid.org/blog/222152</id>
      <published>2011-09-07T09:27:43-07:00</published>
      <updated>2013-05-09T22:41:35-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/222152"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/222152#comment"/>
      <author>
         <name>Hye Jeong Lee</name>
                  <uri>http://www.cubrid.org</uri>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;NoSQL is the talk of the town. And we have already covered &lt;a title=&quot;What is NoSQL for?&quot; href=&quot;http://blog.cubrid.org/web-2-0/what-is-nosql-for/&quot;&gt;what it is for&lt;/a&gt; in one of our previous blogs. Today I would like to share the NoSQL benchmark test results we have recently conducted. It will help you to understand if the soon to develop system is compatible to NoSQL, and which NoSQL product to select.&lt;/p&gt;

&lt;p&gt;In this article we will reveal the characteristics of &lt;a title=&quot;Cassandra - CUBRID Blog&quot; href=&quot;http://blog.cubrid.org/tags/cassandra/&quot;&gt;Cassandra&lt;/a&gt;, &lt;a title=&quot;HBase - CUBRID Blog&quot; href=&quot;http://blog.cubrid.org/tags/hbase&quot;&gt;HBase&lt;/a&gt; and &lt;a title=&quot;MongoDB - CUBRID Blog&quot; href=&quot;http://blog.cubrid.org/tags/mongodb/&quot;&gt;MongoDB&lt;/a&gt; identified through multiple workloads.&lt;/p&gt;

&lt;h2&gt;Why NoSQL?&lt;/h2&gt;

&lt;p&gt;The interest in NoSQL continues to rise because the amount of data to process continues to increase. International internet companies, including &lt;a title=&quot;Google - CUBRID Blog&quot; href=&quot;http://blog.cubrid.org/tags/google/&quot;&gt;Google&lt;/a&gt; and &lt;a title=&quot;Facebook - CUBRID Blog&quot; href=&quot;http://blog.cubrid.org/tags/facebook/&quot;&gt;Facebook&lt;/a&gt;, have their own NoSQL solution designed to process the exploding amount of data.&lt;/p&gt;

&lt;blockquote&gt;Why are they using NoSQL instead of RDBMS?&lt;/blockquote&gt;

&lt;p&gt;&lt;a title=&quot;Twitter - CUBRID Blog&quot; href=&quot;http://blog.cubrid.org/tags/twitter/&quot;&gt;Twitter&lt;/a&gt; is still &lt;a title=&quot;Decomposing Twitter (Database Perspective)&quot; href=&quot;http://blog.cubrid.org/web-2-0/decomposing-twitter-database-perspective/&quot;&gt;using&lt;/a&gt; MySQL. Although smaller than Facebook, the international SNS company MySpace uses MS SQL Server as their main storage.&lt;/p&gt;

&lt;p&gt;RDBMS is known to experience burden when processing tera or peta unit large sized data. However, this can be resolved through sharding. For instance, &lt;a title=&quot;NHN - CUBRID Blog&quot; href=&quot;http://blog.cubrid.org/tags/nhn/&quot;&gt;NHN&lt;/a&gt;’s Café, Blog and News services use RDBMS through sharding.&lt;/p&gt;

&lt;p&gt;There is no single correct answer in processing bulk data. Since every situation is different, the company must select the solution that best fits their situation and apply that for seamless service.&lt;/p&gt;

&lt;blockquote&gt;Out of the RDBMSs, Oracle is an exception since Oracle’s performance and functions, such as mass data processing or data synchronization, are far more superior to other RDBMS. However, the high cost can be a problem. Depending on the size, it may be more economical to develop a NoSQL than purchasing an Oracle license.&lt;/blockquote&gt;

&lt;p&gt;Even if you have enough expertise on how to process bulk data with RDBMS, we will need to have continuous interest and training in NoSQL. NoSQL is gaining popularity because of its ability to process mass data, but it still has many technical (or functional) limitations compared to RDBMS. However, this will be resolved as time passes.&lt;/p&gt;

&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;
&lt;p&gt;NoSQL provides a &lt;b&gt;non-relational&lt;/b&gt;, and in the long run, &lt;b&gt;schema-free data model&lt;/b&gt;, allowing the horizontal extension of the system. Instead, it is &lt;b&gt;less structured&lt;/b&gt; than RDBMS and &lt;b&gt;does not guarantee ACID&lt;/b&gt;. Therefore, after the INSERT operation is completed and SELECT conducted, a different value can be acquired. And after the NoSQL demo has failed and restored, the stored value may be different than before. Operations such as &lt;b&gt;transactions or join cannot be conducted&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;While ACID has been abandoned, the flexibility, scalability and usability of data storage have increased. Therefore, it is more suitable for explosive amounts of data processing.&lt;/p&gt;

&lt;p&gt;Now let’s see if the NoSQL products really play the expected part for the internet services you are to develop. Why don’t we take a look at the characteristics of the most widely used NoSQL products (Cassandra, HBase, MongoDB) by looking into each of its architectures and benchmark tests that were conducted.&lt;/p&gt;

&lt;h2&gt;Benchmarking Tests using YCSB&lt;/h2&gt;

&lt;p&gt;&lt;a title=&quot;Yahoo Cloud Servicing Benchmark&quot; href=&quot;http://research.yahoo.com/Web_Information_Management/YCSB&quot;&gt;YCSB&lt;/a&gt; (Yahoo Cloud Servicing Benchmark) is a test framework developed by Yahoo. It allows to conduct benchmark tests on storages by creating &quot;&lt;em&gt;work loads&lt;/em&gt;&quot;. Through this benchmark, the storage most suitable for the service that is to be developed can be selected.&lt;/p&gt;

&lt;p&gt;Basic operations are Insert, Update, Read, and Scan. There are basic workload sets that combine the basic operations, but new additional workloads can also be created.&lt;/p&gt;

&lt;p&gt;YCBS currently supports Cassandra, HBase, MongoDB, Voldemort and JDBC. If tests on other storages are needed, then use YCBS interfaces to test during the development process.&lt;/p&gt;

&lt;p&gt;This article contains tests conducted on the following products and versions.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Cassandra-0.7.4&lt;br /&gt;&lt;/b&gt;&lt;em&gt;Although Cassandra’s latest version is 0.8.0, we have decided to use the previous version known to be stable. Because when testing with the 0.8 version, the gossip protocol between nodes malfunctioned and the node up/down information was incorrect.&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;HBase-0.90.2&lt;/b&gt; (Hadoop-0.20-append)&lt;br /&gt;&lt;em&gt;The HBase-0.90.2 (Hadoop-0.20-append) was selected because, if not the Hadoop-append version, there may be problems on decreased durability in HDFS.&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;MongoDB-1.8.1&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The test workload is as follows.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Insert Only&lt;br /&gt;&lt;/b&gt;Enter 50 million 1K-sized records to the empty DB.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Read Only&lt;br /&gt;&lt;/b&gt;Search the key in the &lt;a title=&quot;Zipf Distribution&quot; href=&quot;http://mathworld.wolfram.com/ZipfDistribution.html&quot;&gt;Zipfian Distribution&lt;/a&gt; for a one hour period on the DB that contains 50 million 1K-sized records.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Read &amp;amp; Update&lt;br /&gt;&lt;/b&gt;Conduct &lt;em&gt;read&lt;/em&gt; and &lt;em&gt;update&lt;/em&gt; one-on-one instead of &lt;em&gt;read&lt;/em&gt; under the identical conditions of &lt;em&gt;Read Only&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are three testing equipments with the same specifications:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Nehalem 6 Core x 2 CPU, 16GB Memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each conduct replicates and distributes three copies. However, with MongoDB the performance result was abnormally high when both replications and distribution compositions were organized, so the test was conducted only with the replica set. The parameter for each product is shown in the following listings. Other items were set to default.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Cassandra&lt;/li&gt;&lt;/ul&gt;

&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;
# If a minimum of one succeeds while replicating, then it is returned to application.
Consistency Level, Read=ONE, Write=ONE

# Can be set to periodic(default) or batch.
# Periodically writes (fsync) the commit log on the disk,
# and batch executes regularly (1ms) collecting those to fsync every time.
commitlog_sync: batch, commitlog_sync_batch_window_in_ms: 1

# Degree the key location is cached. When 1.0 - everything is cached.
key_cached=1.0
&lt;/pre&gt;

&lt;ul&gt;&lt;li&gt;HBase&lt;/li&gt;&lt;/ul&gt;

&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;
HeapSize, HBase=8G, HDFS=2G
&lt;/pre&gt;

&lt;ul&gt;&lt;li&gt;MongoDB&lt;/li&gt;&lt;/ul&gt;

&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;
# Size of Oplog. Oplog is the log the master accumulated for replication.
--oplogSize=100G
&lt;/pre&gt;

&lt;p&gt;The results are as shown in the following figure.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.cubrid.org/wp-content/uploads/2011/09/db-test-results.png&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/09/db-test-results.png&quot; alt=&quot;Comparison of throughput per product&quot; title=&quot;Comparison of throughput per product&quot; class=&quot;iePngFix&quot; width=&quot;587&quot; height=&quot;418&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;All three products showed better throughput in INSERT.&lt;/li&gt;
  &lt;li&gt;Cassandra showed outstanding throughput in INSERT-only with 20,000 ops.&lt;/li&gt;
  &lt;li&gt;HBase also presented relatively good performance in INSERT-only.&lt;/li&gt;
  &lt;li&gt;The products did not show large differences with READ-only than INSERT-only.&lt;/li&gt;
  &lt;li&gt;HBase’s performance was better than Cassandra in READ-only.&lt;/li&gt;
  &lt;li&gt;Cassandra’s performance in READ-and-UPDATE was better than the other two products. Cassandra’s READ-and-UPDATE might have been higher than READ-only due to Cassandra’s excellent insert throughout.&lt;/li&gt;
  &lt;li&gt;MongoDB’s throughout in all three conditions was the lowest of the three products. MongoDB, which uses the Memory Mapped File (mmap), probably showed poor performance because the large data size exceeded the physical memory size.&lt;/li&gt;
&lt;/ol&gt;
Let’s take a look at why each product showed such difference in performance.

&lt;h2&gt;Cassandra and HBase Architecture&lt;/h2&gt;

&lt;p&gt;Both Cassandra and HBase are influenced by Google’s BigTable. (&lt;em&gt;Although Cassandra was directly influenced by Amazon’s Dynamo.&lt;/em&gt;) &lt;b&gt;BigTable&lt;/b&gt; is a Column-Oriented DB that stores data in a Multidimensional Sorted Map format and has the &lt;b&gt;&amp;lt;row key, column family, column key&amp;gt;&lt;/b&gt; data structure. &lt;b&gt;&lt;em&gt;Column family&lt;/em&gt;&lt;/b&gt; is a basic unit that stores data with column groups that are related to each other.&lt;/p&gt;

&lt;p&gt;In BigTable, data is written basically with the append method. In other words, when modifying data, the updates are appended to a file, rather than an in-place update in the stored file. The figure below shows BigTable’s data read/insert path.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.cubrid.org/wp-content/uploads/2011/09/bigtable-internal-structure.png&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/09/bigtable-internal-structure.png&quot; alt=&quot;BigTable’s Internal Structure&quot; title=&quot;BigTable’s Internal Structure&quot; class=&quot;iePngFix&quot; width=&quot;417&quot; height=&quot;250&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a write operation is inserted, it is first placed in a memory space called &lt;em&gt;&lt;b&gt;memtable&lt;/b&gt;&lt;/em&gt;. If the &lt;em&gt;memtable&lt;/em&gt; is full, then the whole data is stored in a file called &lt;em&gt;&lt;b&gt;SSTable&lt;/b&gt; (Sorted String Table)&lt;/em&gt;. Data may be lost if the server collapses before the &lt;em&gt;memtable&lt;/em&gt; data is moved to &lt;em&gt;SSTable&lt;/em&gt;, so to provide durability it is necessary to save the history of commit logs every time before writing to the &lt;em&gt;memtable&lt;/em&gt;. When conducting the read operation, first find the pertaining key in the &lt;em&gt;memtable&lt;/em&gt;. If it is not in the &lt;em&gt;memtable&lt;/em&gt;, search for it in the &lt;em&gt;SSTable&lt;/em&gt;. You may have to search multiple &lt;em&gt;SSTables&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There are advantages in the writing operation if this architecture is used. This is because the ‘writing’ operation is only recorded in the memory and moved to the actual disk only after a certain amount has been accumulated. &lt;b&gt;Therefore, concurrent I/O can be avoided.&lt;/b&gt; However, when &quot;&lt;em&gt;reading&lt;/em&gt;&quot;, if &quot;&lt;em&gt;reading&lt;/em&gt;&quot; is done in the &lt;em&gt;SSTable&lt;/em&gt; and not in the &lt;em&gt;memtable&lt;/em&gt;, then the performance will relatively decrease. Both Cassandra and HBase use bloom filter to quickly judge whether the key exists in the SSTable and creates an index for use. However, if there are many &lt;em&gt;SSTable&lt;/em&gt;s, then a lot of I/O will be created during the reading operation. Therefore, compaction is done to improve the reading performance. &lt;b&gt;Compaction&lt;/b&gt; is where two &lt;em&gt;SSTable&lt;/em&gt;s merge and sort to become one &lt;em&gt;SSTable&lt;/em&gt;, which decreases the number of &lt;em&gt;SSTable&lt;/em&gt;s. The reading and writing performance improved as more compactions are done.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For these reasons READ and READ-and-UPDATE are much slower than INSERT operations in these NoSQL solutions.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Cassandra&lt;/h2&gt;

&lt;p&gt;Additionally, &lt;b&gt;Cassandra uses consistent hashing&lt;/b&gt;. The HBase and Casandra may have their similarities, there are differences as well. Cassandra prefers &lt;b&gt;AP&lt;/b&gt; (Availability &amp;amp; Partition tolerance) while HBase prefers &lt;b&gt;CP&lt;/b&gt; (Consistency &amp;amp; Partition tolerance). &lt;b&gt;CAP theorem&lt;/b&gt; is a theory in Distributed Computing.&lt;/p&gt;

&lt;blockquote&gt;The theory claims that there is no system that provides all three Consistency, Availability and Partition tolerance. For example, replications must be made in multiple nodes to increase usability, and the adjustability between replicated data must be met. However, in order to make operation possible, even during network partitioning, it becomes difficult to guarantee the adjustability between replications or data. Therefore, only a part of the CAP can be provided.&lt;/blockquote&gt;

&lt;p&gt;As mentioned before, Amazon’s Dynamo has a direct influence on Cassandra. Dynamo uses consistent hashing to &lt;em&gt;disperse data to the key-value store, and provides high adjustability&lt;/em&gt;. Consistent hashing sequences the value (slot) that hashed the key and placed it in a ring format. The multiple nodes that create the cluster processes certain ranges of the ring. Therefore, every time a node in the cluster falls out or comes in, the closed node on the ring can take over the concerned range or distribute the range without rehashing.&lt;/p&gt;

&lt;p&gt;Cassandra also raises the usability level with the concept of consistency level. This concept is related to replication. Confirmation of the number of replications and the completion of replication can be adjusted with the system parameter. For example, if three replications are maintained and a write operation is inserted, then the operation is only considered to be successful if the three replications are completed.&lt;/p&gt;

&lt;p&gt;However, Cassandra allows only N (under 3) number of executions to be checked and immediately returns to value. Therefore, write can be conducted successfully even with failures in the replication node, which raises usability. Histories of failed write operations are recorded on a different node, and the operation can be retried at a later date (this is called “&lt;b&gt;hinted handoff&lt;/b&gt;”). Since the success of replicated writing is not guaranteed, the data suitability is checked in the reading stage. Generally, if there are multiple replications, it is collected into one when reading. However, Cassandra keeps in mind that not all replications match, and reads the data from all three replications, checks whether it is identical, and restores the latest data if it is not suitable (this is called “&lt;b&gt;read repair&lt;/b&gt;”).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is why Cassandra is slower in reading than writing.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;HBase&lt;/h2&gt;

&lt;p&gt;Now let’s look into HBase. HBase has the same structure as BigTable. While BigTable operates on the &lt;em&gt;&lt;b&gt;tablet&lt;/b&gt;&lt;/em&gt; unit, HBase disperses and replicates with the &lt;em&gt;&lt;b&gt;region&lt;/b&gt;&lt;/em&gt; unit. Key is arranged according to ranges, and the location of the region, where the key is stored in, is saved as meta data (this is called &lt;em&gt;&lt;b&gt;meta region&lt;/b&gt;&lt;/em&gt;). Therefore, if a key is inserted, first find the region, and later the client will cache this information. HBase places the writing operation in a single region, without distributing and splits the region if it becomes too large. Adjustments, such as creating regions in advance, must be made for the action above.&lt;/p&gt;

&lt;p&gt;HDFS is in charge of data storage and replication. When writing a file with Hadoop’s distribution file system, HDFS writes multiple replications (synchronous replication) and only reads one of them when reading. This guarantees data integrity and lowers reading overhead. However, since HBase and HDFS operates separately, the location of the node that contains &lt;em&gt;memtable&lt;/em&gt; and &lt;em&gt;SSTable&lt;/em&gt; may change, which may cause additional network I/O.&lt;/p&gt;

&lt;p&gt;What happens if there is a failure in the node? If the region server collapses, other nodes take over the tasks which comprised the region. In other words, the commit log that pertains to the region is replayed and &lt;em&gt;memtable&lt;/em&gt; is created. If the failed node contains HDFS’s data, then chunk that pertains to the node is migrated to a different node.&lt;/p&gt;

&lt;p&gt;Thus, we have looked at the similarities and differences of Cassandra and HBase.&lt;/p&gt;

&lt;blockquote&gt;Then why did the two products show a difference in writing during the comparison test?&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;First of all, there is a &lt;b&gt;difference in commit log&lt;/b&gt;. Cassandra writes the commit log once in the local file system. However, HBase enter the commit log in the HDFS and HDFS conducts the replication. Data locality is not put into consideration, so the file write request will probably be sent to a different physical node in the network.&lt;/li&gt;
  &lt;li&gt;Second, Cassandra receives the write request on all three nodes, but HBase only ‘writes’ on a single region in the beginning, and receives requests on only one node.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;Then why is there a difference in reading performance?&lt;/blockquote&gt;

&lt;p&gt;There are various differences, but for one READ request Cassandra reads the data three times while HBase only reads the data once. This places an influence on the throughput.&lt;/p&gt;

&lt;h2&gt;MongoDB Architecture&lt;/h2&gt;

&lt;p&gt;MongoDB is unlike Cassandra or HBase eplained earlier. There are too many functional groups that can be classified as NoSQL, which makes it difficult to compare with Cassandra and HBase on the same level.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cassandra and HBase is for processing full-scale large amounts of data, while MongoDB can be used quickly, schema-free when using a certain amount of data.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;MongoDB adopts a &lt;b&gt;documented-oriented format&lt;/b&gt;, so it is more similar to RDBMS than a key-value or column oriented format.&lt;/p&gt;

&lt;p&gt;MongoDB &lt;b&gt;operates on a memory base and places high performance above data scalability&lt;/b&gt;. If reading and writing is conducted within the usable memory, then high-performance is possible. However, performance is not guaranteed if operations exceed the given memory. Therefore, &lt;b&gt;MongoDB should be used as a medium or small-sized storage system&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Configure a test condition similar to the original test on a lower specification server and test 300 thousand records instead of 50 million, and MongoDB will record greater performance than Cassandra or HBase.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Mongo DB uses &lt;a title=&quot;BSON&quot; href=&quot;http://bsonspec.org/&quot;&gt;BSON&lt;/a&gt; for data storage&lt;/b&gt;. (As known as Binary JSON, but is similar to Hessian than JSON in data encoding format and expressive datatype.)&lt;/p&gt;

&lt;p&gt;The logical unit that is expressed using BSON is called &lt;em&gt;&lt;b&gt;document&lt;/b&gt;&lt;/em&gt;. (When using NPC as an example, it is the same as when the NPC data is recorded on the disk and searched.) &lt;em&gt;Document&lt;/em&gt; is a concept that corresponds to a &lt;b&gt;row&lt;/b&gt; in RDBMS. The difference is that a &lt;em&gt;document&lt;/em&gt; in MongoDB does not have a schema.&lt;/p&gt;

&lt;p&gt;Accumulated documents&lt;em&gt; &lt;/em&gt;are called &lt;em&gt;&lt;b&gt;collections&lt;/b&gt;&lt;/em&gt;. A collection corresponds to a &lt;em&gt;&lt;b&gt;table&lt;/b&gt;&lt;/em&gt; in RDBMS.&lt;/p&gt;

&lt;p&gt;Basic query method is to search the collection to find documents that meet the conditions. Each document has a field called &lt;b&gt;_id&lt;/b&gt;, which acts as the OID (Object Identifier), and all query results are returned with this &lt;em&gt;_id&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Index can also be created for collections. An index can be prepared for the fields in the document. This index is implemented in &lt;b&gt;B-Tree&lt;/b&gt;, similar to that of RDBM’s index. Each collection creates an index for &lt;em&gt;_id&lt;/em&gt; by default. One of the strengths of MongoDB is that its functions are similar to RDBMS, in that it supports indexing and JOIN.&lt;/p&gt;

&lt;p&gt;Further, we will now look at the structure of MongoDB.&lt;/p&gt;

&lt;h3&gt;MongoDB Structure&lt;/h3&gt;

&lt;p&gt;MongoDB is configurable in replication and distribution configuration. The system configuration recommended by MongoDB is three shard servers and three replica sets for each server (in other words, nine nodes). &lt;b&gt;Replications&lt;/b&gt; are made possible by Master/Slave or a replica set. Replica set supports automatic failover. It has one master and multiple slaves, and write can only be sent to the master. If the master is terminated, service is resumed after one of the slaves are appointed as a master.&lt;/p&gt;

&lt;p&gt;The distribution method provided by MongoDB is &lt;b&gt;sharding&lt;/b&gt;. Each collection can shard, and a field in the Collection can designate a shard key. Like HBase, sharding is operated with the &lt;b&gt;Order-preserving partitioning method&lt;/b&gt;. Chunk is included in the &lt;b&gt;&amp;lt;collection, minkey, maxkey&amp;gt;&lt;/b&gt;, a continuous data range within shard, and can be as big as 64M. Chunks that have exceeded the maximum size can split into two chunks, and the divided chunks can migrate to different shard servers. The following figure contains a picture of MongoDB, which is composed of shards and replica sets.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.cubrid.org/wp-content/uploads/2011/09/mongodb-composition.png&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/09/mongodb-composition.png&quot; alt=&quot;MongoDB structure&quot; title=&quot;MongoDB structure&quot; class=&quot;iePngFix&quot; width=&quot;570&quot; height=&quot;376&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The client first contacts a process called &lt;b&gt;mongos&lt;/b&gt;, which is in charge of &lt;em&gt;routing&lt;/em&gt; and &lt;em&gt;coordination&lt;/em&gt;. Coordination is done over multiple nodes through requests and the results are collected and returned. The config server retains meta information on shards and chunks.&lt;/p&gt;

&lt;p&gt;Now let’s look into MongoDB&apos;s internal structure. MongoDB uses the &lt;b&gt;asynchronous method for replication&lt;/b&gt;. When a “write” operation is inserted, master stores the history in &lt;em&gt;Oplog&lt;/em&gt;. &lt;b&gt;Oplog&lt;/b&gt; is a fixed sized, FlfO method collection called capped collection. Logs accumulated in the Oplog are regularly polled by the slave, read, then implemented. If the slave failed to replay the log while the Oplog fills up, then the slave must suspend log-based replications and synchronizes by resyncing the master’s data. One of Oplog’s other distinctive characteristics is that it can conduct the saved operations idempotently when replaying the log. Operation logs are saved in the order it was executed in, so logs can be replayed after that period. Ops such as &lt;em&gt;increment&lt;/em&gt; are changed to set ops when logged for this purpose.&lt;/p&gt;

&lt;p&gt;MongoDB’s replication and failover method and query power is similar to RDBMS. The most significant difference is that flexibility in data storage is provided to the application while schema-free data is stored.&lt;/p&gt;

&lt;h2&gt;RDBMS Architecture&lt;/h2&gt;

&lt;p&gt;Unlike NoSQL, RDBMS is &lt;b&gt;&quot;read&quot; operation oriented&lt;/b&gt;. The detailed method differs for each product, but generally NoSQL products are implemented so that mass data can be ‘&lt;b&gt;written&lt;/b&gt;’ quickly. On the other hand, RDBMS, which is ‘read’ oriented, not only enables quick reading, but also provides many functions and inquiry features. DBMS can quickly inquire values using indexes, but at the same time indexes slow down ‘writing’. Since an index must be configured for every ‘writing’ operation, the more indexes there are, the more time is needed to configure the indexes.&lt;/p&gt;

&lt;p&gt;The difference of RDBMS and NoSQL can be compared with ACID and BASE, but comparisons can also be made with reading and writing.&lt;/p&gt;

&lt;p&gt;If the business you are to build requires more reading than writing, and needs complex reading methods, as well as basic aggregate functions such as SUM() or AVG(), then RDBMS might be a better choice than NoSQL.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;We have looked at benchmark tests done on Cassandra, HBase, MongoDB and the differences between the products. Cassandra and HBase show excellent writing abilities, but its reading performance did not meet expectations. This was because unlike existing RDBMSs, the two products were optimized for writing, and this resulted in a lot of concurrent I/O when reading.&lt;/p&gt;

&lt;p&gt;MongoDB has similar structures to that of RDBMS and shows great flexibility in data modeling especially for medium and small-sized businesses.&lt;/p&gt;

&lt;p&gt;By Lee Hye Jeong, Storage System Development Team, NHN Corporation.&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="benchmark"/>
            <category term="MS SQL"/>
            <category term="NHN"/>
            <category term="Cassandra"/>
            <category term="Twitter"/>
            <category term="NoSQL"/>
            <category term="Facebook"/>
            <category term="Google"/>
            <category term="BigTable"/>
            <category term="Dynamo"/>
            <category term="Amazon"/>
            <category term="MongoDB"/>
            <category term="Oracle"/>
            <category term="Dev Platform Blog"/>
            <category term="HBase"/>
            
   </entry>
   <entry>
      <title>Comprehensive Overview of Top 14 Content Management Systems</title>
      <id>http://www.cubrid.org/blog/221610</id>
      <published>2011-01-20T18:22:43-08:00</published>
      <updated>2013-05-09T22:40:30-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/221610"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/221610#comment"/>
      <author>
         <name>Esen Sagynov</name>
                  <uri>http://www.cubrid.org</uri>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&lt;strong&gt;Update: &lt;/strong&gt;added the &lt;em&gt;Distinguished clients&lt;/em&gt; for DotNetNuke.&lt;/p&gt;

&lt;p&gt;These days many websites (&lt;em&gt;in fact, millions&lt;/em&gt;) are implemented by the use of popular open source content management systems (CMS). I would say, for &lt;em&gt;everything&lt;/em&gt; &lt;em&gt;you would imagine your site doing&lt;/em&gt;, 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.&lt;/p&gt;

&lt;p&gt;I will not tell you what a CMS is. If you want to learn, see the &lt;a title=&quot;Wikipedia: Content management system&quot; href=&quot;http://en.wikipedia.org/wiki/Content_management_system&quot; target=&quot;_blank&quot;&gt;CMS Wikipedia page&lt;/a&gt;. 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;amp;stone (2010). The report is distributed under the &lt;a title=&quot;Creative Commons Attribution-Noncommercial License (3.0)&quot; href=&quot;http://creativecommons.org/licenses/by-nc/3.0/&quot; target=&quot;_blank&quot;&gt;Creative Commons Attribution-Noncommercial License&lt;/a&gt; (3.0).&lt;/p&gt;

&lt;p&gt;Today we will cover &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#drupal&quot;&gt;Drupal&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#joomla&quot;&gt;Joomla&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#modx&quot;&gt;MODx&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#wordpress&quot;&gt;WordPress&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#dotnetnuke&quot;&gt;DotNetNuke&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#umbraco&quot;&gt;umbraco&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#liferay&quot;&gt;Liferay&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#typo3&quot;&gt;TYPO3&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#cmsmadeeasy&quot;&gt;CMS Made Simple&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#movabletype&quot;&gt;MOVABLE TYPE&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#plone&quot;&gt;Plone&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#ezpublish&quot;&gt;eZ Publish&lt;/a&gt;, &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#concrete5&quot;&gt;concrete5&lt;/a&gt;, and &lt;a href=&quot;http://blog.cubrid.org/web-2-0/comprehensive-overview-of-top-14-content-management-systems/#alfresco&quot;&gt;Alfresco&lt;/a&gt; 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&apos;s learn about each of them, and &lt;em&gt;do not forget to leave your comments below on what other CMS should have been included in this list and why&lt;/em&gt;.&lt;/p&gt;

&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;
&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;em&gt; 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.&lt;/em&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;h2&gt;# 1: Drupal&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://drupal.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/drupal.png&quot; alt=&quot;drupal.png&quot; title=&quot;drupal.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site:&lt;/strong&gt; &lt;a title=&quot;Drupal - Open Source CMS&quot; href=&quot;http://drupal.org/&quot; target=&quot;_blank&quot;&gt;http://drupal.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 33,671 (&lt;em&gt;ranked #3 after Joomla and before DotNetNuke&lt;/em&gt;).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; Drupal is known to be &lt;em&gt;the #3 most familiar content management system&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;li&gt;Provides multiple-level menu system, template customization, advanced search, RSS feed aggregator.&lt;/li&gt;
	&lt;li&gt;Officially Drupal supports several databases including MySQL, PostgreSQL, MariaDB, and SQLite.&lt;/li&gt;
	&lt;li&gt;To increase its performance, you can use caching. At the same time it provides high security with notifications about the new update releases.&lt;/li&gt;
	&lt;li&gt;Provides Search Engine Friendly descriptive URLs.&lt;/li&gt;
	&lt;li&gt;Powered by jQuery JavaScript framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;Extensions:&lt;/strong&gt; over 7,000 free community-contributed addons, known as contrib modules.&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distinguished Clients:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;More difficult to master especially for newbies. It&apos;s more for advanced users. Though the new Drupal 7 claims to provide significantly improved usability (&lt;em&gt;maybe more toward WordPress style&lt;/em&gt;). To achieve this, they hired web designers to specifically address the UX problems it had in previous versions.&lt;/li&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;li&gt;jQuery, the default JavaScript framework in Drupal, allows to use alternative Mootools framework at the same time.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;# 2: Joomla&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;a title=&quot;Joomla&quot; href=&quot;http://www.joomla.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/joomla.png&quot; alt=&quot;joomla.png&quot; title=&quot;joomla.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site:&lt;/strong&gt; &lt;a href=&quot;http://www.joomla.org/&quot; target=&quot;_blank&quot;&gt;http://www.joomla.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 113,836 (&lt;em&gt;ranked #2 after WordPress and before Drupal&lt;/em&gt;).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; Joomla is known to be &lt;em&gt;the #1 most familiar content management system&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;li&gt;You can easily manage your site users, providing standard registration, including Google OpenID support. Full support for Access Control List.&lt;/li&gt;
	&lt;li&gt;Provides Multiple-level menu and content category system, template customization, advanced search, RSS feed aggregator.&lt;/li&gt;
	&lt;li&gt;Officially supports only MySQL.&lt;/li&gt;
	&lt;li&gt;Page cashing for increased performance.&lt;/li&gt;
	&lt;li&gt;Provides moderate descriptive URLs (&lt;em&gt;still not fully customizable as you can do in WordPress&lt;/em&gt;).&lt;/li&gt;
	&lt;li&gt;Powered by MooTools JavaScript framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;Extensions:&lt;/strong&gt; There are over 6,000 free and commercial plugins available from the official site.&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distinguished Clients:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;More intuitive and easy to use than Drupal, though still not like WordPress.&lt;/li&gt;
	&lt;li&gt;Powerful. Fully-fledged content management system, so you can create whatever site you want.&lt;/li&gt;
	&lt;li&gt;Really strong security. If security problems found, immediately fixed.&lt;/li&gt;
	&lt;li&gt;The new Joomla 1.6 release is expected to be faster, more convenient, with more features.&lt;/li&gt;
	&lt;li&gt;Its strong dependency on Mootools JavaScript framework sometimes bothers users as Joomla does not give easy workaround to disable it and use jQuery instead.&lt;/li&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;li&gt;Does not allow to fully customize URLs - a must feature for CMS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;#3: modx&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;a title=&quot;modx&quot; href=&quot;http://www.modxcms.com/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/modx.png&quot; alt=&quot;modx.png&quot; title=&quot;modx.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site: &lt;/strong&gt;&lt;a href=&quot;http://www.modxcms.com/&quot; target=&quot;_blank&quot;&gt;http://www.modxcms.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;modx&lt;/strong&gt; 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).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 4,500 (&lt;em&gt;ranked #11 after umbraco and before Tiki&lt;/em&gt;).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #14 (&lt;em&gt;before Liferay and after eZ Publish&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Distinguished Clients:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.pippatoledo.com/&quot; target=&quot;_blank&quot;&gt;http://www.pippatoledo.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.aquevix.com/&quot; target=&quot;_blank&quot;&gt;http://www.aquevix.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.not1bug.com/&quot; target=&quot;_blank&quot;&gt;http://www.not1bug.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://everlight-uva.com/&quot; target=&quot;_blank&quot;&gt;http://everlight-uva.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.tritopora.ru/&quot; target=&quot;_blank&quot;&gt;http://www.tritopora.ru/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.strategische-webloesungen.de/&quot; target=&quot;_blank&quot;&gt;http://www.strategische-webloesungen.de/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;What users say:&lt;/strong&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;Good to have a choice for favorite JavaScript framework.&lt;/li&gt;
	&lt;li&gt;Light CMS solution (but not necessarily the fastest).&lt;/li&gt;
	&lt;li&gt;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 .&lt;/li&gt;
	&lt;li&gt;Nice to have freedom to set custom URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;#4: WordPress&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://wordpress.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/wordpress.png&quot; alt=&quot;wordpress.png&quot; title=&quot;wordpress.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site:&lt;/strong&gt; &lt;a href=&quot;http://wordpress.org/&quot; target=&quot;_blank&quot;&gt;http://wordpress.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 983,625 (&lt;em&gt;ranked #1 before Joomla&lt;/em&gt;).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #2 (&lt;em&gt;after Joomla and before Drupal&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Extensions:&lt;/strong&gt; 12,780 plugins and 1,315 themes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distinguished Clients:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;Perhaps, the most convenient, easy to use and intuitive CMS (&lt;em&gt;or BMS&lt;/em&gt;) 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.&lt;/li&gt;
	&lt;li&gt;I would avoid Wordpress as a CMS in a professional environment. As stated earlier, it&apos;s a great blogging platform, but doesn&apos;t generally offer the robustness that most professional environments require.&lt;/li&gt;
	&lt;li&gt;Availability of jQuery makes the plugin development a lot easier for external developers and site owners.&lt;/li&gt;
	&lt;li&gt;Endless themes - no need to worry about the new design for your site, unless you really need something special.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;#5: DotNetNuke&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://www.dotnetnuke.com/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/dotnetnuke.png&quot; alt=&quot;dotnetnuke.png&quot; title=&quot;dotnetnuke.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site:&lt;/strong&gt; &lt;a href=&quot;http://www.dotnetnuke.com/&quot; target=&quot;_blank&quot;&gt;http://www.dotnetnuke.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;a href=&quot;http://en.wikipedia.org/wiki/DotNetNuke#cite_note-autogenerated1-2&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 13,000 (&lt;em&gt;ranked #4 after Drupal and before CMS Made Simple&lt;/em&gt;).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #4 (&lt;em&gt;after Drupal and before Typo3&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

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

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;A little bit difficult to create modules.&lt;/li&gt;
	&lt;li&gt;It is perceived as a little bit bulky CMS.&lt;/li&gt;
	&lt;li&gt;Does not provide extensive documentation and user guides.&lt;/li&gt;
	&lt;li&gt;Similar to most CMS, does not provide full backward compatibility in its new major releases.&lt;/li&gt;
	&lt;li&gt;Unlike its enterprise edition, the community edition is not tested and certified by the DotNetNuke Corporation.&lt;/li&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;#6: Umbraco&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://umbraco.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/umbraco.png&quot; alt=&quot;umbraco.png&quot; title=&quot;umbraco.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site: &lt;/strong&gt;&lt;a href=&quot;http://umbraco.org/&quot; target=&quot;_blank&quot;&gt;http://umbraco.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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&lt;a href=&quot;http://en.wikipedia.org/wiki/Umbraco#cite_note-history-1&quot; target=&quot;_blank&quot;&gt;&lt;/a&gt;. It is written in C# and can be deployed on Microsoft based infrastructure. In 2010, with about &lt;strong&gt;1,000 downloads a day&lt;/strong&gt;, Umbraco was in the Top 5 most popular downloads via the &lt;em&gt;Microsoft Web Platform Installer&lt;/em&gt;, two places below its main rival DotNetNuke.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 5,420 (&lt;em&gt;ranked #10 after Alfresco and before MODx&lt;/em&gt;).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #16 (after Liferay and before e107).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;What users say:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://www.liferay.com/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/liferay.png&quot; alt=&quot;liferay.png&quot; title=&quot;liferay.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site: &lt;/strong&gt;&lt;a href=&quot;http://www.liferay.com/&quot; target=&quot;_blank&quot;&gt;http://www.liferay.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Liferay &lt;/strong&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 9,435 (&lt;em&gt;ranked #6 after CMS Made Simple and before TYPO3&lt;/em&gt;).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #15 (after MODx and before Umbraco).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features/ Portlets:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Distinguished Clients:&lt;/strong&gt; It is primarily used to power corporate business sites.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://developer.cisco.com/&quot; target=&quot;_blank&quot;&gt;http://developer.cisco.com&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.t-mobile.cz/&quot; target=&quot;_blank&quot;&gt;http://www.t-mobile.cz&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.betavine.net/&quot; target=&quot;_blank&quot;&gt;http://www.betavine.net&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.foxchannel.de/&quot; target=&quot;_blank&quot;&gt;http://www.foxchannel.de/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.ixarm.com/&quot; target=&quot;_blank&quot;&gt;http://www.ixarm.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;What users say:&lt;/strong&gt;&lt;p&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://typo3.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/typo3.png&quot; alt=&quot;typo3.png&quot; title=&quot;typo3.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site:&lt;/strong&gt; &lt;a href=&quot;http://typo3.org/&quot; target=&quot;_blank&quot;&gt;http://typo3.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TYPO3&lt;/strong&gt; 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&apos;s standard templating, while making it possible to enforce a strict corporate design and allowing editors to work with content more intuitively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 7,461 (ranked #7 after Liferay and before eZ Publish).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installations:&lt;/strong&gt; 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).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #5 (after DotNetNuke and before OpenCMS).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Distinguished clients:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.volkswagen-ir.de/&quot; target=&quot;_blank&quot;&gt;http://www.volkswagen-ir.de&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.eadssecureuk.com/&quot; target=&quot;_blank&quot;&gt;http://www.eadssecureuk.com&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.geveriwise-eu.com/&quot; target=&quot;_blank&quot;&gt;http://www.geveriwise-eu.com&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.rewe-xxl.de/&quot; target=&quot;_blank&quot;&gt;http://www.rewe-xxl.de&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;What users say:&lt;/strong&gt;&lt;p&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://www.cmsmadesimple.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/cms-made-simple.png&quot; alt=&quot;cms-made-simple.png&quot; title=&quot;cms-made-simple.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site: &lt;/strong&gt;&lt;a href=&quot;http://www.cmsmadesimple.org/&quot; target=&quot;_blank&quot;&gt;http://www.cmsmadesimple.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 9,948 (ranked #5 after DotNetNuke and before Liferay).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installations:&lt;/strong&gt; 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).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #12 (after Xoop and before Ez Publish).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;What users say:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;http://movabletype.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/movabletype.png&quot; alt=&quot;movabletype.png&quot; title=&quot;movabletype.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt; &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site: &lt;/strong&gt;&lt;a href=&quot;http://movabletype.org/&quot; target=&quot;_blank&quot;&gt;http://movabletype.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Movable Type&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; unavailable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installations:&lt;/strong&gt; 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).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #8 (after Plone and before Alfresco).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;Convenient blogging system with social community features.&lt;/li&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;li&gt;Manage user roles. OpenID support.&lt;/li&gt;
	&lt;li&gt;Multiple site hosting.&lt;/li&gt;
	&lt;li&gt;Easily customizable templates.&lt;/li&gt;
	&lt;li&gt;Revision history.&lt;/li&gt;
	&lt;li&gt;Can add custom fields.&lt;/li&gt;
	&lt;li&gt;Content tags and categories.&lt;/li&gt;
	&lt;li&gt;Feeds and trackback links.&lt;/li&gt;
	&lt;li&gt;Available localization and internationalization.&lt;/li&gt;
	&lt;li&gt;Can generate static pages (updated whenever the content of the site is changed).&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;Extensions:&lt;/strong&gt; about 1,000 plugins.&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distinguished clients:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.britneyspears.com/&quot; target=&quot;_blank&quot;&gt;http://www.britneyspears.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.barackobama.com/&quot; target=&quot;_blank&quot;&gt;http://www.barackobama.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://boeingblogs.com/&quot; target=&quot;_blank&quot;&gt;http://boeingblogs.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://blogs.oracle.com/&quot; target=&quot;_blank&quot;&gt;http://blogs.oracle.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://gehealthcare.typepad.com/&quot; target=&quot;_blank&quot;&gt;http://gehealthcare.typepad.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.spd.org/&quot; target=&quot;_blank&quot;&gt;http://www.spd.org/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://blog.ted.com/&quot; target=&quot;_blank&quot;&gt;http://blog.ted.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;What users say:&lt;/strong&gt;&lt;p&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://plone.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/plone.png&quot; alt=&quot;plone.png&quot; title=&quot;plone.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site: &lt;/strong&gt;&lt;a href=&quot;http://plone.org/&quot; target=&quot;_blank&quot;&gt;http://plone.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plone&lt;/strong&gt;, 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; unavailabe.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #7 (after OpenCMS and before Movable Type).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Distinguished clients:&lt;/strong&gt;&lt;/p&gt;

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

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

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://ez.no/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/ez.png&quot; alt=&quot;ez.png&quot; title=&quot;ez.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site: &lt;/strong&gt;&lt;a href=&quot;http://ez.no/&quot; target=&quot;_blank&quot;&gt;http://ez.no/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 7,031 (ranked #8 after TYPO3 and before Alfresco).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installations:&lt;/strong&gt; 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).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #13 (after CMS Made Simple and before MODx).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

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

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

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://www.concrete5.org/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/concrete5.png&quot; alt=&quot;concrete5.png&quot; title=&quot;concrete5.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site: &lt;/strong&gt;&lt;a href=&quot;http://www.concrete5.org/&quot; target=&quot;_blank&quot;&gt;http://www.concrete5.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concrete5&lt;/strong&gt; 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&apos;s National Council for the Lewis &amp;amp; Clark Bicentennial. Concrete5 is developed in PHP and is distributed under MIT software license.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; unavailable.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #20 (after TextPattern).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.genco.com/&quot; target=&quot;_blank&quot;&gt;http://www.genco.com&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.cottonfrombluetogreen.org/&quot; target=&quot;_blank&quot;&gt;http://www.cottonfrombluetogreen.org/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.cs.uh.edu/&quot; target=&quot;_blank&quot;&gt;http://www.cs.uh.edu/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.signals.ca/&quot; target=&quot;_blank&quot;&gt;http://www.signals.ca/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.paulraymondgregory.com/&quot; target=&quot;_blank&quot;&gt;http://www.paulraymondgregory.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;strong&gt;What users say:&lt;/strong&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;It&apos;s PHP based and quite new but it&apos;s quite a nice layout and it&apos;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.&lt;/li&gt;
	&lt;li&gt;Concrete5 is simple, suitable for creating sites quickly.&lt;/li&gt;
	&lt;li&gt;Creating template is very easy with Concrete5.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;#14: Alfresco&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;http://www.alfresco.com/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;http://blog.cubrid.org/wp-content/uploads/2011/1-/alfresco.png&quot; alt=&quot;alfresco.png&quot; title=&quot;alfresco.png&quot; class=&quot;iePngFix&quot; width=&quot;701&quot; height=&quot;325&quot; style=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Official site: &lt;/strong&gt;&lt;a href=&quot;http://www.alfresco.com/&quot; target=&quot;_blank&quot;&gt;http://www.alfresco.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alfresco&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly downloads:&lt;/strong&gt; 7,000 (ranked #9 after Ez Publish and before Umbraco).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Brand Familiarity:&lt;/strong&gt; #9 (after Movable Type and before Tiki).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Major Features:&lt;/strong&gt;&lt;/p&gt;

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

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

&lt;p&gt;&lt;/p&gt;&lt;ul&gt;
	&lt;li&gt;Alfresco is mostly for enterprises rather than for personal sites.&lt;/li&gt;
	&lt;li&gt;Simple to install and use, flexible and open-ended.&lt;/li&gt;
	&lt;li&gt;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.&lt;/li&gt;
	&lt;li&gt;All in one solution for enterprises.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;See also&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;/p&gt;&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Drupal&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Drupal&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Joomla&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Joomla&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Modx&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Modx&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Wordpress&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Wordpress&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/DotNetNuke&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/DotNetNuke&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Umbraco&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Umbraco&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Liferay&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Liferay&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Typo3&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Typo3&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/CMS_Made_Simple&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/CMS_Made_Simple&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Movable_Type&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Movable_Type&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Plone_(software&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Plone_(software)&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/EZ_Publish&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/EZ_Publish&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Concrete5&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Concrete5&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Alfresco_(software&quot; target=&quot;_blank&quot;&gt;http://en.wikipedia.org/wiki/Alfresco_(software)&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a title=&quot;OPEN SOURCE CMS MARKET SHARE REPORT&quot; href=&quot;http://www.waterandstone.com/sites/default/files/2010 OSCMS Report.pdf&quot; target=&quot;_blank&quot;&gt;http://www.waterandstone.com/sites/default/files/2010%20OSCMS%20Report.pdf&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://php.opensourcecms.com/&quot; target=&quot;_blank&quot;&gt;http://php.opensourcecms.com/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/&quot; target=&quot;_blank&quot;&gt;http://stackoverflow.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="Wordpress"/>
            <category term="Joomla"/>
            <category term="CMS"/>
            <category term="content management system"/>
            <category term="Web 2.0"/>
            <category term="Drupal"/>
            <category term="Concrete5"/>
            <category term="MODx"/>
            <category term="DotNetNuke"/>
            <category term="Liferay"/>
            <category term="TYPO3"/>
            <category term="CMS Made Simple"/>
            <category term="MOVABLE TYPE"/>
            <category term="Plone"/>
            <category term="eZ Publish"/>
            <category term="Alfresco"/>
            <category term="Umbraco"/>
            
   </entry>
   <entry>
      <title>Our Experience of Creating Large Scale Log Search System Using ElasticSearch</title>
      <id>http://www.cubrid.org/blog/651202</id>
      <published>2013-05-06T02:06:36-07:00</published>
      <updated>2013-05-06T02:20:32-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/651202"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/651202#comment"/>
      <author>
         <name>Lee Jae Ik</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;At NHN we have a service called NELO (NHN Error Log System) to manage and search logs pushed to the system by various applications and other Web services. The&amp;nbsp;search performance and functionality of&amp;nbsp;NELO2, the&amp;nbsp;second generation of the system,&amp;nbsp;have significantly been improved through ElasticSearch.&amp;nbsp;Today I would like to share our experience at &lt;a href=&quot;http://cubrid.org/blog/tags/NHN&quot;&gt;NHN&lt;/a&gt; in deploying ElasticSearch in Log Search Systems.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.elasticsearch.org&quot;&gt;ElasticSearch&lt;/a&gt; is a distributed search engine based on Lucene developed by&amp;nbsp;Shay Banon. Shay and his team have recently released the long awaited version 0.90. Here is a link to a &lt;a href=&quot;http://info.elasticsearch.com/Recorded_0.90_Webinar.html&quot;&gt;one-hour recorded webinar&lt;/a&gt;&amp;nbsp;where Clinton Gormley, one of the core ElasticSearch developers, explains what&apos;s new in ElasticSearch 0.90.&lt;/p&gt;
&lt;p&gt;If you are developing a system which requires a search functionality, I would recommend ElasticSearch as its installation and server expansion are very easy. Since it is a distributed system, ElasticSearch can easily cope with an increase in the volume of search targets. At NHN all logs coming into NELO2 are stored and indexed by ElasticSearch for faster near real-time search results.&lt;/p&gt;
&lt;h2&gt;Features of ElasticSearch&lt;/h2&gt;
&lt;p&gt;Let&apos;s get started with familiarizing ourselves with the terms widely used in ElasticSearch.&amp;nbsp;For those who are familiar with relational database systems, the following table compares the terms used in relational databases with the terms used in ElasticSearch.&lt;/p&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;caption&gt;Table 1: Comparison of the terms of RDBMS and ElasticSearch.&lt;/caption&gt; &lt;thead&gt; 
&lt;tr&gt;
&lt;th&gt;Relational DB&lt;/th&gt; &lt;th&gt;ElasticSearch&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;Index&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Table&lt;/td&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Row&lt;/td&gt;
&lt;td&gt;Document&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Column&lt;/td&gt;
&lt;td&gt;Field&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schema&lt;/td&gt;
&lt;td&gt;Mapping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Index&lt;/td&gt;
&lt;td&gt;Everything is indexed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQL&lt;/td&gt;
&lt;td&gt;Query DSL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;JSON-based Schemaless Storage&lt;/h3&gt;
&lt;p&gt;ElasticSearch is a search engine but can be used like &lt;a href=&quot;/blog/tags/NoSQL/&quot;&gt;NoSQL&lt;/a&gt;. Since a data model is represented in JSON, both requests and responses are exchanged as JSON documents. Moreover, sources are also stored in JSON. Although schema is not defined in advance, JSON documents are automatically indexed when they are transferred. Number and date types are automatically mapped.&lt;/p&gt;
&lt;h3&gt;Multitenancy&lt;/h3&gt;
&lt;p&gt;ElasticSearch supports &lt;a href=&quot;http://en.wikipedia.org/wiki/Multitenancy&quot;&gt;multitenancy&lt;/a&gt;. Multiple indexes can be stored in a single ElasticSearch server, and data of multiple indexes can be searched with a &lt;i&gt;single&lt;/i&gt; query. NELO2 separates indexes by date and stores logs. When executing a search, NELO requests indexes of dates within the scope of search with a single query.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 1: Multitenancy Example Query.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;# Store logs in the log-2012-12-26 index
curl -XPUT http://localhost:9200/log-2012-12-26/hadoop/1 -d &apos;{
    &quot;projectName&quot;: &quot;hadoop&quot;,
    &quot;logType&quot;: &quot;hadoop-log&quot;,
    &quot;logSource&quot;: &quot;namenode&quot;,
    &quot;logTime&quot;:&quot;2012-12-26T14:12:12&quot;,
    &quot;host&quot;: &quot;host1.nelo2&quot;,
    &quot;body&quot;: &quot;org.apache.hadoop.hdfs.StateChange: DIR* NameSystem.completeFile&quot;
}&apos;

# Store logs in the log-2012-12-27 index
curl -XPUT http://localhost:9200/log-2012-12-27/hadoop/1 -d &apos;{
    &quot;projectName&quot;: &quot;hadoop&quot;,
    &quot;logType&quot;: &quot;hadoop-log&quot;,
    &quot;logSource&quot;: &quot;namenode&quot;,
    &quot;logTime&quot;:&quot;2012-12-27T02:02:02&quot;,
    &quot;host&quot;: &quot;host2.nelo2&quot;,
    &quot;body&quot;: &quot;org.apache.hadoop.hdfs.server.namenode.FSNamesystem&quot;
}&apos;

# Request search to the nelo2-log-2012-12-26 and nelo2-log-2012-12-27 indexes at once
curl -XGET http://localhost:9200/nelo2-log-2012-12-26,nelo2-log-2012-12-27/_search&lt;/pre&gt;
&lt;h3&gt;Scalability and Flexibility&lt;/h3&gt;
&lt;p&gt;ElasticSearch provides excellent scalability and flexibility. It enables the expansion of functionality through plug-ins, which was further improved in recent 0.90 release. For example, by using Thrift or Jetty plugin, you can change transfer protocol. If you install BigDesk or Head, which is a required plugin, you can use the functionality of ElasticSearch monitoring. As shown in the following &lt;b&gt;Code 2&lt;/b&gt;, you can also adjust the number of replicas dynamically. The number of shards is not changeable as it is fixed for each index, so an appropriate number of shards should be allocated in the first time by taking the number of nodes and future server expansion into account.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 2: Dynamic Configuration Change Query.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;$ curl -XPUT http://localhost:9200/log-2012-12-27/ -d &apos;{
    &quot;settings&quot;: {
        &quot;number_of_shards&quot;: 10,
        &quot;number_of_replicas&quot;: 1
    }
}&apos;&lt;/pre&gt;
&lt;h3&gt;Distributed Storage&lt;/h3&gt;
&lt;p&gt;ElasticSearch is a distributed search engine. It distributes data by configuring multiple shards according to keys. An index is configured for each shard. Each shard has 0 or more replicas. Moreover, ElasticSearch supports clustering, and when a cluster runs, one of many nodes is selected as the master node to manage metadata. If the master node fails, another node in the cluster automatically becomes the master. It is also very easy to add nodes. When a node is added to the same network, the added node will automatically find the cluster through multicast and add itself to the cluster. If the same network is not used, the master node address should be specified through unicast (see a related video: &lt;a href=&quot;http://youtu.be/l4ReamjCxHo&quot;&gt;http://youtu.be/l4ReamjCxHo&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Installing&lt;/h2&gt;
&lt;h3&gt;Quick Start&lt;/h3&gt;
&lt;p&gt;ElasticSearch supports zero configuration installation. As shown in the following code snippets, all you have to do for execution is download a file from the official homepage and unzip it.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Download&lt;br /&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;~$ wget http://download.ElasticSearch.org/ElasticSearch/ElasticSearch/ElasticSearch-0.20.1.tar.gz   
~$ tar xvzf ElasticSearch-0.20.1.tar.gz&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Executing Server&lt;br /&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;~$ bin/ElasticSearch -f&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Installing Plugins&lt;/h3&gt;
&lt;p&gt;You can easily expand the functionality of ElasticSearch through plugins. You can add management functionalities, change the analyzer of Lucene, and change the basic transfer module from Netty to Jetty. The following is a command we use to install plugins for NELO2. Head and bigdesk, which are found in the first and second lines, are the plugins required for ElasticSearch monitoring. It is strongly recommended to install them and check their functionalities. After installing them, visit &lt;a href=&quot;http://localhost:9200/plugin/head/&quot;&gt;http://localhost:9200/plugin/head/&lt;/a&gt; and &lt;a href=&quot;http://localhost:9200/plugin/bigdesk/&quot;&gt;http://localhost:9200/plugin/bigdesk/&lt;/a&gt;, and you can see the status of ElasticSearch in your Web browser.&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;bin/plugin -install Aconex/ElasticSearch-head
bin/plugin -install lukas-vlcek/bigdesk
bin/plugin -install ElasticSearch/ElasticSearch-transport-thrift/1.4.0
bin/plugin -install sonian/ElasticSearch-jetty/0.19.9&lt;/pre&gt;
&lt;h3&gt;Main Configurations&lt;/h3&gt;
&lt;p&gt;You don&apos;t need to change configurations when conducting a simple functionality test. When you carry out a performance test or apply it to production services, then you should change some default configurations. See the following snippet and try to find for yourself the configurations which should be changed from the initial configuration file.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 5:&amp;nbsp;Main Configurations (&lt;i&gt;config/ElasticSearch.yml&lt;/i&gt;).&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;# As it is a name used to identify clusters, use a name with uniqueness and a meaning.
cluster.name: ElasticSearch-nelo2

# A node name is automatically created but it is recommended to use a name that is discernible in a cluster like a host name.
node.name: &quot;xElasticSearch01.nelo2&quot;

# The default value of the following two is all true. node.master sets whether the node can be the master, while node.data is a configuration for whether it is a node to store data. Usually you need to set the two values as true, and if the size of a cluster is big, you should adjust this value by node to configure three types of node. More details will be explained in the account of topologies configuration later.
node.master: true
node.data: true

# You can change the number of shards and replicas. The following value is a default value: 
index.number_of_shards: 5
index.number_of_replicas: 1

#To prevent jvm swapping, you should set the following value as true:
bootstrap.mlockall: true

# It is a timeout value for checking the status of each node in a cluster. You should set an appropriate value; if the value is too small, nodes may frequently get out of a cluster. The default value is 3 seconds.
discovery.zen.ping.timeout: 10s

# The default value is multicast, but in an actual environment, unicast should be employed due to the possibility of overlapping with other clusters. It is recommended to list servers that can be a master in the second setting.
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: [&quot;host1&quot;, &quot;host2:port&quot;, &quot;host3[portX-portY]&quot;]&lt;/pre&gt;
&lt;h2&gt;Using REST API&lt;/h2&gt;
&lt;p&gt;ElasticSearch provides a REST API as shown below. It provides most of its functionalities through REST API, including the creation and deletion of indexes, mappings, as well as search and change of settings. In addition to REST API, it also provides various client APIs for Java, Python and Ruby.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 6:&amp;nbsp;REST API Format in ES.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;http://host:port/(index)/(type)/(action|id)&lt;/pre&gt;
&lt;p&gt;As mentioned earlier, NELO2 classifies indexes (&lt;i&gt;databases&lt;/i&gt; in RDBMS terms) by date, and type (&lt;i&gt;table&lt;/i&gt;) is separated by project. &lt;b&gt;Code 7&lt;/b&gt; below shows the process of creating logs that came into the &lt;b&gt;hadoop&lt;/b&gt; project on &lt;b&gt;December 27, 2012&lt;/b&gt;, in the unit of &lt;b&gt;document&lt;/b&gt; by using a REST API.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 7:&amp;nbsp;An Example of Using ElasticSearch REST API.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;#Creating documents
curl -XPUT http://localhost:9200/log-2012-12-27/hadoop/1
curl -XGET http://localhost:9200/log-2012-12-27/hadoop/1
curl -XDELETE http://localhost:9200/log-2012-12-27/hadoop/1

#Search
curl -XGET http://localhost:9200/log-2012-12-27/hadoop/_search
curl -XGET http://localhost:9200/log-2012-12-27/_search
curl -XGET http://localhost:9200/_search

#Seeing the status of indexes
curl -XGET http://localhost:9200/log-2012-12-27/_status&lt;/pre&gt;
&lt;h3&gt;Creating Documents and Indexes&lt;/h3&gt;
&lt;p&gt;As shown in the following &lt;b&gt;Code 8&lt;/b&gt;, when the request is sent, ElasticSearch creates the &lt;b&gt;log-2012-12-27&lt;/b&gt; index and &lt;b&gt;hadoop&lt;/b&gt; type automatically without any pre-defined index or type. If you want to create them specifically instead of using auto creation, you should specify the setting of &lt;code&gt;action.auto_create_index&lt;/code&gt; and &lt;code&gt;index.mapper.dynamic&lt;/code&gt; as &lt;code&gt;false&lt;/code&gt; in the configuration file.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 8:&amp;nbsp;Creating Documents.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;# Request
curl -XPUT http://localhost:9200/log-2012-12-27/hadoop/1 -d &apos;{
    &quot;projectName&quot;: &quot;hadoop&quot;,
    &quot;logType&quot;: &quot;hadoop-log&quot;,
    &quot;logSource&quot;: &quot;namenode&quot;,
    &quot;logTime&quot;:&quot;2012-12-27T02:02:02&quot;,
    &quot;host&quot;: &quot;host2.nelo2&quot;,
    &quot;body&quot;: &quot;org.apache.hadoop.hdfs.server.namenode.FSNamesystem&quot;
}&apos;

# Result
{
    &quot;ok&quot;: true,
    &quot;_index&quot;: &quot;log-2012-12-27&quot;,
    &quot;_type&quot;: &quot;hadoop&quot;,
    &quot;_id&quot;: &quot;1&quot;,
    &quot;_version&quot;: 1
}&lt;/pre&gt;
&lt;p&gt;As shown in Code 9 below, you can make a request after including type in a document.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 9:&amp;nbsp;A Query Including Type.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;curl -XPUT http://localhost:9200/log-2012-12-27/hadoop/1 -d &apos;{
    &quot;hadoop&quot;: {
        &quot;projectName&quot;: &quot;hadoop&quot;,
        &quot;logType&quot;: &quot;hadoop-log&quot;,
        &quot;logSource&quot;: &quot;namenode&quot;,
        &quot;logTime&quot;:&quot;2012-12-27T02:02:02&quot;,
        &quot;host&quot;: &quot;host2.nelo2&quot;,
        &quot;body&quot;: &quot;org.apache.hadoop.hdfs.server.namenode.FSNamesystem&quot;
    }
}&apos;&lt;/pre&gt;
&lt;p&gt;If an&amp;nbsp;&lt;code&gt;id&lt;/code&gt;&amp;nbsp;value is omitted as in &lt;b&gt;Code 10&lt;/b&gt;, an&amp;nbsp;&lt;code&gt;id&lt;/code&gt;&amp;nbsp;will be created automatically when a document is created. Note that the&lt;code&gt;POST&lt;/code&gt;&amp;nbsp;method was used instead of&amp;nbsp;&lt;code&gt;PUT&lt;/code&gt;&amp;nbsp;when a request was made.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 10:&amp;nbsp;A Query Creating a Document without an ID.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;# Request
curl -XPOST http://localhost:9200/log-2012-12-27/hadoop/ -d &apos;{
    &quot;projectName&quot;: &quot;hadoop&quot;,
    &quot;logType&quot;: &quot;hadoop-log&quot;,
    &quot;logSource&quot;: &quot;namenode&quot;,
    &quot;logTime&quot;:&quot;2012-12-27T02:02:02&quot;,
    &quot;host&quot;: &quot;host2.nelo2&quot;,
    &quot;body&quot;: &quot;org.apache.hadoop.hdfs.server.namenode.FSNamesystem&quot;
}&apos;

# Result
{
    &quot;ok&quot;: true,
    &quot;_index&quot;: &quot;log-2012-12-27&quot;,
    &quot;_type&quot;: &quot;hadoop&quot;,
    &quot;_id&quot;: &quot;kgfrarduRk2bKhzrtR-zhQ&quot;,
    &quot;_version&quot;: 1
}&lt;/pre&gt;
&lt;h3&gt;Deleting a Document&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;Code 11&lt;/b&gt;&amp;nbsp;below shows how to delete a document (&lt;i&gt;a record&lt;/i&gt;&amp;nbsp;in RDBMS terms) in type (&lt;i&gt;a table&lt;/i&gt;). You can delete a &lt;b&gt;hadoop&lt;/b&gt; type document with &lt;code&gt;id=1&lt;/code&gt; of the &lt;b&gt;log-2012-12-27&lt;/b&gt; index by using the &lt;code&gt;DELETE&lt;/code&gt; method.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 11:&amp;nbsp;A Query to Delete a Document.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;# Request
$ curl -XDELETE &apos;http://localhost:9200/log-2012-12-27/hadoop/1&apos;

# Result
{
    &quot;ok&quot;: true,
    &quot;_index&quot;: &quot;log-2012-12-27&quot;,
    &quot;_type&quot;: &quot;hadoop&quot;,
    &quot;_id&quot;: &quot;1&quot;,
    &quot;found&quot;: true
}&lt;/pre&gt;
&lt;h3&gt;Getting a Document&lt;/h3&gt;
&lt;p&gt;You can get a &lt;b&gt;hadoop&lt;/b&gt; type document with &lt;code&gt;id=1&lt;/code&gt; of the &lt;b&gt;log-2012-12-27 &lt;/b&gt;index by using the &lt;code&gt;GET&lt;/code&gt; method as shown in Code 12.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 12:&amp;nbsp;A Query to Get a Document.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;#Request
curl -XGET &apos;http://localhost:9200/log-2012-12-27/hadoop/1&apos;

# Result
{
    &quot;_index&quot;: &quot;log-2012-12-27&quot;,
    &quot;_type&quot;: &quot;hadoop&quot;,
    &quot;_id&quot;: &quot;1&quot;,
    &quot;_source&quot;: {
        &quot;projectName&quot;: &quot;hadoop&quot;,
        &quot;logType&quot;: &quot;hadoop-log&quot;,
        &quot;logSource&quot;: &quot;namenode&quot;,
        &quot;logTime&quot;:&quot;2012-12-27T02:02:02&quot;,
        &quot;host&quot;: &quot;host2.nelo2&quot;,
        &quot;body&quot;: &quot;org.apache.hadoop.hdfs.server.namenode.FSNamesystem&quot;
    }
}&lt;/pre&gt;
&lt;h3&gt;Search&lt;/h3&gt;
&lt;p&gt;When the Search API is called, ElasticSearch executes the Search API and returns the search results that match the content of the query. Code 13 shows an example of using Search API.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 13:&amp;nbsp;An Example Query of Using Search API.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;# All types of a specific index
$ curl -XGET &apos;http://localhost:9200/log-2012-12-27/_search?q=host:host2.nelo2&apos;

# A specific type of a specific index
$ curl -XGET &apos;http://localhost:9200/log-2012-12-27/hadoop,apache/_search?q=host:host2.nelo2&apos;

# A specific type of all indexes
$ $ curl - XGET &apos;http://localhost:9200/_all/hadoop/_search?q=host:host2.nelo2&apos;

# All indexes and types
$ curl -XGET &apos;http://localhost:9200/_search?q=host:host2.nelo2&apos;&lt;/pre&gt;
&lt;h3&gt;Search API by Using URI Request&lt;/h3&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;thead&gt; &lt;/thead&gt;&lt;caption&gt;Table 2: Main Parameters.&lt;/caption&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt; &lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;q&lt;/td&gt;
&lt;td&gt;Query string.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;default_operator&lt;/td&gt;
&lt;td&gt;The operator used as a default (&lt;code&gt;AND&lt;/code&gt; or &lt;code&gt;OR&lt;/code&gt;). The default is &lt;code&gt;OR&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fields&lt;/td&gt;
&lt;td&gt;The field to get as a result. The default is the &quot;_source&quot; field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sort&lt;/td&gt;
&lt;td&gt;Sort method. Ex) fieldName:asc/fieldName:desc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;timeout&lt;/td&gt;
&lt;td&gt;Search timeout value. The default is &quot;unlimited&quot;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;size&lt;/td&gt;
&lt;td&gt;The number of result values. The default is 10.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If you use URI, you can search easily by using parameters in &lt;b&gt;Table 2&lt;/b&gt; and a query string. As it does not provide all search options, it is useful when used for tests.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 14:&amp;nbsp;Search Query by Using URI Request.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;# Request
$ curl -XGET &apos;http://localhost:9200/log-2012-12-27/hadoop/_search?q=host:host2.nelo2&apos;

# Result
{
    &quot;_shards&quot;:{
        &quot;total&quot;: 5,
        &quot;successful&quot;: 5,
        &quot;failed&quot;: 0
    },
    &quot;hits&quot;:{
        &quot;total&quot;: 1,
        &quot;hits&quot;: [
            {
                &quot;_index&quot;: &quot;log-2012-12-27&quot;,
                &quot;_type&quot;: &quot;hadoop&quot;,
                &quot;_id&quot;: &quot;1&quot;, 
                &quot;_source&quot;: {
                    &quot;projectName&quot;: &quot;hadoop&quot;,
                    &quot;logType&quot;: &quot;hadoop-log&quot;,
                    &quot;logSource&quot;: &quot;namenode&quot;,
                    &quot;logTime&quot;:&quot;2012-12-27T02:02:02&quot;,
                    &quot;host&quot;: &quot;host2.nelo2&quot;,
                    &quot;body&quot;: &quot;org.apache.hadoop.hdfs.server.namenode.FSNamesystem&quot;
                }
            }
        ]
    }
}&lt;/pre&gt;
&lt;h3&gt;Search API by Using Request Body&lt;/h3&gt;
&lt;p&gt;When HTTP body is used, perform a search by using query DSL. As query DSL has a large amount of contents, you are advised to refer to a guide from the &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/query-dsl/&quot;&gt;official website&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 15:&amp;nbsp;Search by Using Query DSL.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;# Request
$ curl -XPOST &apos;http://localhost:9200/log-2012-12-27/hadoop/_search&apos; -d &apos;{
    &quot;query&quot;: {
        &quot;term&quot;: { &quot;host&quot;: &quot;host2.nelo2&quot; }
    }
}&apos;

# Result
{
    &quot;_shards&quot;:{
        &quot;total&quot;: 5,
        &quot;successful&quot;: 5,
        &quot;failed&quot;: 0
    },
    &quot;hits&quot;:{
        &quot;total&quot;: 1,
        &quot;hits&quot;: [
            {
                &quot;_index&quot;: &quot;log-2012-12-27&quot;,
                &quot;_type&quot;: &quot;hadoop&quot;,
                &quot;_id&quot;: &quot;1&quot;,
                &quot;_source&quot;: {
                    &quot;projectName&quot;: &quot;hadoop&quot;,
                    &quot;logType&quot;: &quot;hadoop-log&quot;,
                    &quot;logSource&quot;: &quot;namenode&quot;,
                    &quot;logTime&quot;:&quot;2012-12-27T02:02:02&quot;,
                    &quot;host&quot;: &quot;host2.nelo2&quot;,
                    &quot;body&quot;: &quot;org.apache.hadoop.hdfs.server.namenode.FSNamesystem&quot;
                }
            }
        ]
    }
}&lt;/pre&gt;
&lt;h2&gt;Mapping&lt;/h2&gt;
&lt;h3&gt;Put Mapping API&lt;/h3&gt;
&lt;p&gt;To add a mapping to a specific type, you can define a mapping in the form shown in &lt;b&gt;Code 16&lt;/b&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 16:&amp;nbsp;Query to Register a Mapping.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;$ curl -XPUT &apos;http://localhost:9200/log-2012-12-27/hadoop/_mapping&apos; -d &apos;
{
    &quot;hadoop&quot;: {
        &quot;properties&quot;: {
            &quot;projectName&quot;: {&quot;type&quot;: &quot;string&quot;, &quot;index&quot;: &quot;not_analyzed&quot;},
            &quot;logType&quot;: {&quot;type&quot;: &quot;string&quot;, &quot;index&quot;: &quot;not_analyzed&quot;},
            &quot;logSource&quot;: {&quot;type&quot;: &quot;string&quot;, &quot;index&quot;: &quot;not_analyzed&quot;},
            &quot;logTime&quot;: {&quot;type&quot;: &quot;date&quot;},
            &quot;host&quot;: {&quot;type&quot;: &quot;string&quot;, &quot;index&quot;: &quot;not_analyzed&quot;},
            &quot;body&quot;: {&quot;type&quot;: &quot;string&quot;},
        }
    }
}&apos;&lt;/pre&gt;
&lt;h3&gt;Get Mapping API&lt;/h3&gt;
&lt;p&gt;To get defined mapping information, you can use a query in the form shown in &lt;b&gt;Code 17&lt;/b&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 17:&amp;nbsp;Query to Get a Mapping.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;$ curl -XGET &apos;http://localhost:9200/log-2012-12-27/hadoop/_mapping&apos;&lt;/pre&gt;
&lt;h3&gt;Delete Mapping API&lt;/h3&gt;
&lt;p&gt;Code 18 shows an example of deleting a defined mapping.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 18:&amp;nbsp;Query to Delete a Mapping.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;$ curl -XDELETE &apos;http://localhost:9200/log-2012-12-27/hadoop&apos;&lt;/pre&gt;
&lt;h2&gt;How to Optimize Performance&lt;/h2&gt;
&lt;h3&gt;Memory and the Number of Open Files&lt;/h3&gt;
&lt;p&gt;If the amount of data to search increases, you will need more memory. When you run ElasticSearch, you will encounter many problems due to the use of memory. In an operating method recommended by an ElasticSearch community, when you run a server exclusively for ElasticSearch, you are advised to allocate only half of the memory capacity to ElasticSearch, and to allow the OS to use the other half for system cache. You can set the memory size by setting the &lt;code&gt;ES_HEAP_SIZE&lt;/code&gt; environmental variable or by using &lt;code&gt;-Xms&lt;/code&gt; and &lt;code&gt;-Xmx&lt;/code&gt; of JVM.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 19:&amp;nbsp;Execution by Specifying Heap Size.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;bin/ElasticSearch -Xmx=2G -Xms=2G&lt;/pre&gt;
&lt;p&gt;When using ElasticSearch, you will see &lt;code&gt;OutOfMemory&lt;/code&gt; errors frequently. This error occurs when the field cache exceeds the maximum heap size. If you change the setting for &lt;code&gt;index.cache.field.type&lt;/code&gt; from &lt;b&gt;resident&lt;/b&gt; (default) to &lt;b&gt;soft&lt;/b&gt;, &lt;b&gt;soft&lt;/b&gt; reference will be used and the cache area will be preferentially &lt;a href=&quot;/blog/tags/Garbage%20Collection/&quot;&gt;GC&lt;/a&gt;, and this problem can be resolved.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 20:&amp;nbsp;Configuring Field Cache Type.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;index.cache.field.type: soft&lt;/pre&gt;
&lt;p&gt;If the amount of data increases, the number of index files also increases. This is because Lucene, which is used by ElasticSearch, manages indexes in the unit of &lt;i&gt;segments&lt;/i&gt;. Sometimes the number will even exceed the number of &lt;code&gt;MAX_OPEN&lt;/code&gt; files. For this reason, you need to change the maximum open file limit by using the &lt;code&gt;ulimit&lt;/code&gt; command. The recommended value is &lt;b&gt;32000-64000&lt;/b&gt;, but sometimes you may need to set a larger value depending on the size of the system or data.&lt;/p&gt;
&lt;h3&gt;Index Optimization&lt;/h3&gt;
&lt;p&gt;NELO2 manages indexes by date. If indexes are managed by date, you can delete old logs that don&apos;t need to be managed easily and quickly, as shown in &lt;b&gt;Code 21&lt;/b&gt;. In this case, the overhead imposed on the system is smaller than when deleting logs by specifying the TTL value for each document.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 21:&amp;nbsp;Deleting an Index.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;$ curl -XDELETE &apos;http://localhost:9200/log-2012-10-01/&apos;&lt;/pre&gt;
&lt;p&gt;If index optimization is performed, &lt;i&gt;segments&lt;/i&gt; are incorporated. Using this method, you can enhance search performance. As index optimization can impose a burden on the system, it is better to perform it when the system is being used less.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 22:&amp;nbsp;Index Optimization.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;$ curl -XPOST &apos;http://localhost:9200/log-2012-10-01/_optimize&apos;&lt;/pre&gt;
&lt;h3&gt;Shards and Replicas&lt;/h3&gt;
&lt;p&gt;You can&apos;t change the number of shards after setting it. For this reason, you need to decide this value carefully by taking the current number of nodes in the system and the number of nodes expected to be added in the future into account. For example, if there are 5 nodes and the number is expected to reach 10 in the future, it is recommended to set the number of shards as 10 from the beginning. If you set it as 5 in the beginning, you can add 5 more nodes later, but you won&apos;t be able to use the added 5 nodes. If you set the number of replicas to 1, of course, you can utilize the added 5 nodes as nodes exclusively for replication.&lt;/p&gt;
&lt;p&gt;If the number of shards increases, it is more advantageous to process a large amount of data because queries are distributed as much as the number of shards. But you need to set this value appropriately, because the performance could be deteriorated due to increasing traffic if the value is too high.&lt;/p&gt;
&lt;h2&gt;Configuring Cluster Topologies&lt;/h2&gt;
&lt;p&gt;The content of the configuration file of ElasticSearch is shown in &lt;b&gt;Code 23&lt;/b&gt;&amp;nbsp;below. There are three types of nodes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;b&gt;data node&lt;br /&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;This does not act as the master, and only stores data. When it receives a request from a client, it searches data from shards or creates an index.&lt;/span&gt;&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;master node&lt;br /&gt;&lt;/b&gt;I&lt;b&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;t functions to maintain a cluster, and requests indexing or search to data nodes.&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;search balancer node&lt;/b&gt;&lt;br /&gt;If it receives a search request, it requests data, gathers data and delivers the result.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can have one node which will function both like a master and a data node. But if you use the three types of node separately, you can reduce the burden of the data node. In addition, if you configure the master node separately, you can improve the stability of a cluster. Also, you can reduce operation costs by using low-spec. server equipment for the master and search node.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 23: Settings Related to Topology.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;# You can exploit these settings to design advanced cluster topologies.
#
# 1. You want this node to never become a master node, only to hold data.
#    This will be the &quot;workhorse&quot; of your cluster.
#
# node.master: false
# node.data: true
#
# 2. You want this node to only serve as a master, to not store any data and
#    to have free resources. This will be the &quot;coordinator&quot; of your cluster.
#
# node.master: true
# node.data: false
#
# 3. You want this node to be neither a master nor a data node, but
#    to act as a &quot;search load balancer&quot; (fetching data from nodes,
#    aggregating results, etc.)
#
# node.master: false
# node.data: false&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;Figure 1&lt;/b&gt; below shows the configuration of NELO2 topologies that use ElasticSearch. The efficiency of equipment use and the stability of the entire cluster has been improved as follows: only ElasticSearch runs on the 20 data nodes (server) so that they can achieve sufficient performance, while other daemon server processes in addition to ElasticSearch run on the 4 master nodes and 3 search nodes.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/202/651/nhn_nelo2_elasticsearch_topologies.png&quot; alt=&quot;nhn_nelo2_elasticsearch_topologies.png&quot; width=&quot;663&quot; height=&quot;348&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1:&amp;nbsp;NELO2 ElasticSearch Topologies.&lt;/b&gt;&lt;/p&gt;
&lt;h3&gt;Configuring Routing&lt;/h3&gt;
&lt;p&gt;When a large amount of data needs to be indexed, increasing the number of shards will improve the overall performance. On the other hand, if the number of shards increases, the traffic among nodes will also go up. For example, when there are 100 shards, if it receives a single search request, it sends the request to all the 100 shards and aggregates data, and this imposes a burden on the entire cluster.&lt;/p&gt;
&lt;p&gt;If you use routing, data will be stored only in a specific shard. Even if the number of shards increases, the application will still send a request only to a single shard, and consequently the traffic can be reduced dramatically. &lt;b&gt;Figure 2&lt;/b&gt;, &lt;b&gt;3&lt;/b&gt;, and &lt;b&gt;4&lt;/b&gt; are excerpted from the &lt;a href=&quot;http://www.slideshare.net/kucrafal/scaling-massive-elastic-search-clusters-rafa-ku-sematext&quot;&gt;slides&amp;nbsp;Rafal Kuc presented at Berlin Buzzwords 2012&lt;/a&gt;. If you don&apos;t use routing, as shown in &lt;b&gt;Figure 2&lt;/b&gt;, the application will send a request to all the shards. But if you use routing, it will send a request only to a specific shard, as shown in &lt;b&gt;Figure 3&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;According to the material cited, in &lt;b&gt;Figure 4&lt;/b&gt;&amp;nbsp;when there are 200 shards, the response time is over 10 times faster with routing than without routing. If routing is applied, the number of threads will increase by 10 to 20 times compared to when it is not applied, but the CPU usage is much smaller. In some cases, however, the performance will be better when routing is not applied. For a search query whose result should be collected from multiple shards, it could be more advantageous in terms of performance to send the request to multiple shards. To complement this, NELO2 determines the use of routing depending on the log usage of the project.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/202/651/nhn_nelo_before_using_routing.png&quot; alt=&quot;nhn_nelo_before_using_routing.png&quot; width=&quot;470&quot; height=&quot;324&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 2: Before Using Routing.&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/202/651/nhn_nelo2_after_using_routing.png&quot; alt=&quot;nhn_nelo2_after_using_routing.png&quot; width=&quot;466&quot; height=&quot;343&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 3:&amp;nbsp;After Using Routing.&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;&lt;img src=&quot;/files/attach/images/220547/202/651/nhn_nelo2_performance_comparison_before_after_using_routing.png&quot; alt=&quot;nhn_nelo2_performance_comparison_before_after_using_routing.png&quot; width=&quot;521&quot; height=&quot;218&quot; /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 4: Performance Comparison before and after Using Routing.&lt;/b&gt;&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;The number of users of ElasticSearch is increasing rapidly, thanks to its easy installation and high scalability. It was several days only since the release of the latest ElasticSearch version 0.90. Its functionality is improving very quickly thanks to its active community. In addition, more and more companies are beginning to use ElasticSearch for their services.&amp;nbsp;Recently, some committers, including the developer Shay Banon, gathered together and established ElasticSearch.com, which provides consulting and training services.&lt;/p&gt;
&lt;p&gt;In this article I have explained the basic information on the installation of ElasticSearch, how to use it, and do performance tuning. We have started testing the latest 0.90 release and soon will migrate the current 0.20.1 ES deployment.&amp;nbsp;In the next post I will continue this topic and tell you about our experience with 0.90 as well as the critical split-brain problem we have previously experienced. Due to the scarcity of solutions for this problem, I believe it will be very useful for our readers.&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;/?mid=textyle&amp;amp;act=dispMemberInfo&amp;amp;member_srl=651249&amp;amp;vid=blog&amp;amp;tab=blogs&quot;&gt;Lee Jae Ik&lt;/a&gt;, Senior Software Engineer at Global Platform Development Lab, NHN Corporation.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Official guide: &lt;a href=&quot;http://www.ElasticSearch.org/guide/&quot;&gt;http://www.ElasticSearch.org/guide/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Introduction to ElasticSearch and comparison of the terms of ElasticSearch and RDB: &lt;a href=&quot;http://www.slideshare.net/clintongormley/cool-bonsai-cool-an-introduction-to-ElasticSearch&quot;&gt;http://www.slideshare.net/clintongormley/cool-bonsai-cool-an-introduction-to-ElasticSearch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;About ElasticSearch: &lt;a href=&quot;http://www.slideshare.net/dadoonet/ElasticSearch-devoxx-france-2012-english-version&quot;&gt;http://www.slideshare.net/dadoonet/ElasticSearch-devoxx-france-2012-english-version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Shay Banon&apos;s articles: &lt;a href=&quot;http://2011.berlinbuzzwords.de/sites/2011.berlinbuzzwords.de/files/ElasticSearch-bbuzz2011.pdf&quot;&gt;http://2011.berlinbuzzwords.de/sites/2011.berlinbuzzwords.de/files/ElasticSearch-bbuzz2011.pdf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Using ElasticSearch for logs: &lt;a href=&quot;http://www.ElasticSearch.org/tutorials/2012/05/19/ElasticSearch-for-logging.html&quot;&gt;http://www.ElasticSearch.org/tutorials/2012/05/19/ElasticSearch-for-logging.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Concept of multitenancy: &lt;a href=&quot;http://en.wikipedia.org/wiki/Multitenancy&quot;&gt;http://en.wikipedia.org/wiki/Multitenancy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Shay Banon&apos;s ElasticSearch optimization: &lt;a href=&quot;https://github.com/logstash/logstash/wiki/ElasticSearch-Storage-Optimization&quot;&gt;https://github.com/logstash/logstash/wiki/ElasticSearch-Storage-Optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Rafal Kuc&apos;s article on performance tuning presented at Berlin Buzzwords 2012: &lt;a href=&quot;http://www.slideshare.net/kucrafal/scaling-massive-elastic-search-clusters-rafa-ku-sematext&quot;&gt;http://www.slideshare.net/kucrafal/scaling-massive-elastic-search-clusters-rafa-ku-sematext&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</content>
                  <category term="ElasticSearch"/>
            <category term="NHN"/>
            <category term="NELO"/>
            <category term="Log Analysis System"/>
            <category term="Lucene"/>
            <category term="Scalability"/>
            <category term="Sharding"/>
            
   </entry>
   <entry>
      <title>Announcing CUBRID ALL-IN-ONE Windows Downloader</title>
      <id>http://www.cubrid.org/blog/646162</id>
      <published>2013-04-29T00:05:10-07:00</published>
      <updated>2013-04-29T01:26:30-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/646162"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/646162#comment"/>
      <author>
         <name>Esen Sagynov</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&lt;img style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; height=&quot;168&quot; width=&quot;637&quot; alt=&quot;cubrid-all-in-one-windows-downloader.png&quot; src=&quot;/files/attach/images/220547/162/646/cubrid-all-in-one-windows-downloader.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We are very glad to announce the immediate availability of &lt;b&gt;CUBRID ALL-IN-ONE Windows Downloader&lt;/b&gt;&amp;nbsp;version 1.0 &lt;i&gt;beta&lt;/i&gt;. You can download CUBRID ALL-IN-ONE Windows Downloader from &lt;a href=&quot;/wiki_tools/entry/cubrid-all-in-one-windows-downloader&quot;&gt;http://www.cubrid.org/wiki_tools/entry/cubrid-all-in-one-windows-downloader&lt;/a&gt;. The source code is available at &lt;a href=&quot;http://svn.cubrid.org/cubridtools/cubrid-downloader/&quot;&gt;http://svn.cubrid.org/cubridtools/cubrid-downloader/&lt;/a&gt;&amp;nbsp;which is open sourced under &lt;a href=&quot;/bsd_license&quot;&gt;BSD license&lt;/a&gt; just like all other &lt;a href=&quot;/wiki_tools/entry/cubrid-tools-wiki&quot;&gt;CUBRID Tools&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CUBRID ALL-IN-ONE Windows Downloader is an application that allows our users to easily download CUBRID components including the server engine, drivers and GUI tools. All you have to do is to select the components you want to download on your local Windows machine and the Downloader will download them for you, one by one, without any other actions required.&lt;/p&gt;
&lt;p&gt;Application key features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The application can &lt;b&gt;auto-update&lt;/b&gt; itself, anytime a new version is available (it uses the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms227123%28v=vs.80%29.aspx&quot;&gt;ClickOnce&lt;/a&gt;&amp;nbsp;technology).&lt;/li&gt;
&lt;li&gt;Retrieves all the components information from a remote CUBRID online location, so it is always up-to- date with the latest application releases.&lt;/li&gt;
&lt;li&gt;Detects local machine specifics - CUBRID version, OS architecture &amp;ndash; and automatically selects the appropriate list of components.&lt;/li&gt;
&lt;li&gt;Can handle software pre-prerequisites dependencies and download them as well.&lt;/li&gt;
&lt;li&gt;Supports both HTTP and FTP protocols for&amp;nbsp;downloads.&lt;/li&gt;
&lt;li&gt;Provides additional information to users like&amp;nbsp;links&amp;nbsp;to&amp;nbsp;online resources.&lt;/li&gt;
&lt;li&gt;Handles download errors and auto-retries in case of failures.&lt;/li&gt;
&lt;li&gt;Supports alternate download locations to try in case of failures.&lt;/li&gt;
&lt;li&gt;Saves the user preferences and re-uses them next time.&lt;/li&gt;
&lt;li&gt;Provides a comprehensive operations log information.&lt;/li&gt;
&lt;li&gt;Supports UI localization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is a mute video which shows how to use CUBRID ALL-IN-ONE Downloader.&lt;/p&gt;
&lt;p&gt;&lt;iframe width=&quot;640&quot; height=&quot;480&quot; src=&quot;http://www.youtube.com/embed/8Hh0SE-I7c0&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you have questions or suggestions, leave your comments below.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;&lt;/div&gt;</content>
                  <category term="Downloader"/>
            <category term="Windows"/>
            <category term="downloads"/>
            
   </entry>
   <entry>
      <title>CUBRID Node.js Driver 1.1 is now available at NPM</title>
      <id>http://www.cubrid.org/blog/534207</id>
      <published>2012-12-23T16:45:24-08:00</published>
      <updated>2013-04-17T23:00:04-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/534207"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/534207#comment"/>
      <author>
         <name>Esen Sagynov</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/207/534/cubrid_nodejs_logo.png&quot; alt=&quot;cubrid_nodejs_logo.png&quot; title=&quot;cubrid_nodejs_logo.png&quot; class=&quot;iePngFix&quot; width=&quot;245&quot; height=&quot;140&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I am very glad to announce the immediate availability of CUBRID Node.js driver version 1.1. You can download &lt;b&gt;node-cubrid&lt;/b&gt; from NPM. For more details, see check out the official repository at&amp;nbsp;&lt;a target=&quot;_self&quot; href=&quot;https://github.com/CUBRID/node-cubrid&quot;&gt;https://github.com/CUBRID/node-cubrid&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;What&apos;s New&lt;/h2&gt;
&lt;p&gt;In this new release we have improved many aspects of the driver.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We now follow &quot;&lt;b&gt;One driver to rule them all&lt;/b&gt;&quot; concept. In other words, you can use &lt;b&gt;node-cubrid&lt;/b&gt;&amp;nbsp;with any version of CUBRID Database including&amp;nbsp;8.4.1,&amp;nbsp;8.4.3, and&amp;nbsp;9.0.0 (beta).&lt;/li&gt;
&lt;li&gt;The new driver comes with many code fixes, bugs fixes, and design changes.&lt;/li&gt;
&lt;li&gt;Rich database support: Connect, Query, Fetch, Execute, Commit, Rollback, DB Schema etc.&lt;/li&gt;
&lt;li&gt;Out of the box driver events model.&lt;/li&gt;
&lt;li&gt;10.000+ LOC, including the driver test code and demos&lt;/li&gt;
&lt;li&gt;New test cases added. Now 50+.&lt;/li&gt;
&lt;li&gt;We have significantly refactored the code using JSHint/JSLint code analysis.&lt;/li&gt;
&lt;li&gt;New documentation.&lt;/li&gt;
&lt;li&gt;Created new tutorials that we will publish later.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;The 1.1 release was successfully tested, using the driver test suite, on 2 OS x 3 CUBRID engine = 6 different test environments.&lt;/p&gt;
&lt;h2&gt;What&apos;s next&lt;/h2&gt;
&lt;p&gt;The upcoming new version, 2.0, will feature many new features and improvements. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CUBRID 9.1 stable release compatibility.&lt;/li&gt;
&lt;li&gt;Improved queries support. In particular, implementing &lt;b&gt;queries queuing&lt;/b&gt; support similar to MySQL.&lt;/li&gt;
&lt;li&gt;Extended database schema support&lt;/li&gt;
&lt;li&gt;... and many more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have questions, ask at our &lt;a target=&quot;_self&quot; href=&quot;/questions&quot;&gt;CUBRID Q&amp;amp;A&lt;/a&gt; site, or at &lt;a target=&quot;_self&quot; href=&quot;http://webchat.freenode.net/?channels=cubrid&quot;&gt;#cubrid&lt;/a&gt; IRC. We will be glad to answer you!&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="Node.js"/>
            <category term="JavaScript"/>
            <category term="Drivers"/>
            <category term="Web development"/>
            <category term="programming"/>
            <category term="APIs"/>
            
   </entry>
   <entry>
      <title>Inside Vert.x. Comparison with Node.js.</title>
      <id>http://www.cubrid.org/blog/629772</id>
      <published>2013-04-08T03:30:00-07:00</published>
      <updated>2013-04-08T18:36:33-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/629772"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/629772#comment"/>
      <author>
         <name>Woo Seongmin</name>
                  <uri>http://www.cubrid.org</uri>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://vertx.io&quot;&gt;Vert.x&lt;/a&gt; is a server framework which is rapidly arising. Each server framework claims its strong points are high performance with a variety of protocols supported. Vert.x takes a step forward from that. Vert.x considers the environment of establishing and operating the server network environment. In other words, Vert.x includes careful consideration in producing several &apos;server process DAEMONs&apos; that run on the clustering environment, as well as producing one server process DAEMON.&lt;/p&gt;
&lt;p&gt;Therefore, it is important to review into Vert.x: which network environment it considers as well as how it delivers high performance. So, I think it will be valuable to pay sufficient time examining Vert.x structure.&lt;/p&gt;
&lt;h2&gt;Philosophy of Vert.x&lt;/h2&gt;
&lt;p&gt;Vert.x is a project affected by &lt;a href=&quot;http://nodejs.org&quot;&gt;Node.js&lt;/a&gt;. Like Node.js, Vert.x is a server framework providing an event-based programming model. Therefore, Vert.x API is very similar to that of Node.js. That&apos;s because both of these models provide asynchronous API.&lt;/p&gt;
&lt;p&gt;Node.js is created by using JavaScript, but Vert.x is created by using &lt;b&gt;Java&lt;/b&gt;. However, it is too much to understand Vert.x as a Java version of Node.js. Vert.x has been affected by Node.js; but Vert.x has its own unique philosophy, different from Node.js.&lt;/p&gt;
&lt;p&gt;The most typical design philosophy of Vert.x is summarized as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Polyglot - supports several languages&lt;/strong&gt;&lt;br /&gt;Vert.x itself is built in Java. However, Java is not required to use Vert.x. &lt;br /&gt;As well as languages based on JVM operation, such as Java or Groovy, Vert.x can be used with Ruby, Python, and even JavaScript. If you need to build a server application by using JavaScript, there is an alternative to Node.js. In addition, Scala and Closure are planned to be supported.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Super Simple Concurrency model&lt;/strong&gt;&lt;br /&gt;When building a server application by using Vert.x, users can write code as a single thread application. That means that the multi-thread programming effect can be achieved without synchronization, lock, or volatility.&lt;br /&gt;In Node.js, the JavaScript execution engine does not support multi-thread. However, to utilize all CPU cores, several same JavaScript programs have to be executed. &lt;br /&gt;However, Vert.x allows to create multiple threads based on the number of CPU cores whlie only one process is executed.  It handle the multi-threading so users can focus on implementing business logic. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provides Event Bus&lt;br /&gt;&lt;/strong&gt; As described in the introduction, the goal of Vert.x is not only to produce a &amp;lsquo;one server process DAEMON&apos;. Vert.x aims to make a variety of Vert.x-built server programs communicate well with each other. For this, Vert.x provides Event Bus. Therefore, MQ functions such as Point to Point or Pub/Sub can be used (to provide Event Bus function, Vert.x uses &lt;a href=&quot;http://www.hazelcast.com&quot;&gt;Hazelcastm&lt;/a&gt;, an In-Memory Data Grid).&lt;br /&gt;With this Event Bus, a server application built with different languages can easily communicate with each other. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Module System &amp;amp; Public Module Repository&lt;/strong&gt;&lt;br /&gt;Vert.x has a module system. This module system can be understood as a type of component.  That means the Vert.x-built server application project itself is modularized. It aims at reusability. This module can be registered to Public Module Repository. Through the Public Module Repository, the module can be shared.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;What is the relationship and defference between Netty and Vert.x?&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;Before discussing the Vert.x performance, we should summarize the relationship between Netty and Vert.x. Vert.x uses Netty. In other words, it processes all IOs by using Netty. Therefore, it is meaningless to verify differences of the performance between Vert.x and Netty.&lt;/p&gt;
&lt;p&gt;Vert.x is a server framework that provides API and functions different and independent from Netty, designed with different purpose from Netty.&lt;/p&gt;
&lt;p&gt;Netty is a framework that can process the low-level IO and Vert.x can process the higher-level IO than Netty.&lt;/p&gt;
&lt;h2&gt;Comparison of Performance with Node.js&lt;/h2&gt;
&lt;p&gt;Even if functions provided by Vert.x are different from those of Node.js, comparing the performance between them is a significant matter.  &lt;b&gt;Figure 1&lt;/b&gt; and &lt;b&gt;Figure 2&lt;/b&gt;&amp;nbsp;below show the performance of Vert.x (Java, Ruby, Groovy) and Node.js. (Source: &lt;a href=&quot;http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/&quot;&gt;http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Figure 1&lt;/b&gt; shows a comparison of performance when an HTTP server is built and only a 200/OK response has been returned. &lt;b&gt;Figure 2&lt;/b&gt; shows the comparison of performance when a 72-byte static HTML file is returned as a response.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/772/629/vertx_nodejs_performance_comparison_200_ok.png&quot; alt=&quot;vertx_nodejs_performance_comparison_200_ok.png&quot; width=&quot;572&quot; height=&quot;273&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 1: Comparison of Performance When Only 200/OK Response Has Been Returned.&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/772/629/vertx_nodejs_performance_comparison_72_byte_response.png&quot; alt=&quot;vertx_nodejs_performance_comparison_72_byte_response.png&quot; width=&quot;579&quot; height=&quot;336&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 2: Comparison of Performance When a 72-byte Static HTML File is Returned.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This performance is proclaimed by Vert.x developers but the test has not been made under a strict environment. Just look the relative differences in performance.&lt;/p&gt;
&lt;p&gt;Also, a notable point is that the performance of Vert.x-JavaScript is better than Node.js. However, even if the performance result is very reliable, it may be difficult to say that Vert.x is better than Node.js. That&apos;s because Node.js provides great models such as Socket.io and has lots of references.&lt;/p&gt;
&lt;h2&gt;Vert.x Terminology&lt;/h2&gt;
&lt;p&gt;Vert.x defines its unique terms and redefines general terms for Vert.x itself. Therefore, to understand Vert.x, it is necessary to understand the Vert.x-defined terms. The followings are popular terms used in Vert.x:&lt;/p&gt;
&lt;h3&gt;Verticle&lt;/h3&gt;
&lt;p&gt;For Java, it is the class with a main method. Verticle can also include other scripts referred to by the main method. It can also include the jars files or resources. An application may consist of one Verticle or several Verticles, which communicate through Event Bus. Alongside Java, it can be understood as an independently executable class or a jar file.&lt;/p&gt;
&lt;h3&gt;Vert.x Instance&lt;/h3&gt;
&lt;p&gt;A Verticle is executed within a Vert.x instance and the Vert.x instance is executed in its JVM instance. So there will be a lot of Verticles which are simultaneously executed in a single Vert.x instance. Each Verticle can have its own unique class loader. In this manner, direct interactions between Verticles, made through static members and global variables, can be prevented. A lot of Verticles can be simultaneously executed in several hosts on the network and the Vert.x instances can be clustered through Event Bus.&lt;/p&gt;
&lt;h3&gt;Concurrency&lt;/h3&gt;
&lt;p&gt;The Verticle instance guarantees it is always executed on an identical thread. As all codes can be developed as a single thread operation type, developers who use environment where Vert.x can be easily developed. In addition, race condition or deadlock can be prevented.&lt;/p&gt;
&lt;h3&gt;Event-based Programming Model&lt;/h3&gt;
&lt;p&gt;Like the Node.js framework, Vert.x provides an event-based programming model. When programming a server by using Vert.x, most codes for development are related to event handlers. For example, an event handler should be set to receive data from a TCP socket or an event handler, which will be called when data is received, should be created. In addition, event handlers should be created to receive alarms &apos;when Event Bus receives a message,&apos; &apos;when HTTP messages are received,&apos; &apos;when a connection has been disconnected,&apos; and &apos;when a timer is timeout.&apos;&lt;/p&gt;
&lt;h3&gt;Event Loops&lt;/h3&gt;
&lt;p&gt;Vert.x instance internally manages the thread pool. Vert.x matches the number of thread pools to the number of CPU cores as closely as possible.&lt;/p&gt;
&lt;p&gt;Each thread executes Event Loop.  Event Loop verifies the events as rounding the loop. For example, verifying whether there is data to read in the socket or on which timer an event has occurred. If there is an event to process on the loop, Vert.x calls the corresponding handler (of course, additional work is necessary if the handler-processing period is too long or there is a blocking I/O).&lt;/p&gt;
&lt;h3&gt;Message Passing&lt;/h3&gt;
&lt;p&gt;Verticles use Event Bus for communication. If a Verticle is assumed as an actor, Message Passing is similar to an actor model, which was famous in Erlang programming languages. The Vert.x server instance has a lot of Verticle instances and allows message passing among the instances. Therefore, the system can be extended according to the usable cores without executing the Verticle code through multi-thread.&lt;/p&gt;
&lt;h3&gt;Shared data&lt;/h3&gt;
&lt;p&gt;Message passing is very useful. However, it is not always the best approach in all types of application concurrency situations. Cache is one of the most popular examples. If only one vertical has a certain cache, it is very inefficient. If other Verticles need the cache, each Verticle should manage the same cache data.&lt;/p&gt;
&lt;p&gt;Therefore, Vert.x provides a method for global access. It is the &lt;b&gt;Shared Map&lt;/b&gt;. Verticles share immutable data only.&lt;/p&gt;
&lt;h3&gt;Vert.x Core&lt;/h3&gt;
&lt;p&gt;As named, this is the core function of Vert.x. Functions that the Verticle can directly call are included in the core. Therefore, the core can be accessed by each programming language API supported by Vert.x.&lt;/p&gt;
&lt;h2&gt;Vert.x Architecture&lt;/h2&gt;
&lt;p&gt;The simple architecture of Vert.x is shown in the following &lt;b&gt;Figure 3&lt;/b&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/772/629/vertx_architecture.png&quot; alt=&quot;vertx_architecture.png&quot; width=&quot;304&quot; height=&quot;245&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 3: Vert.x Architecture (source: &lt;a href=&quot;http://www.javacodegeeks.com/2012/07/osgi-case-study-modular-vertx.html&quot;&gt;http://www.javacodegeeks.com/2012/07/osgi-case-study-modular-vertx.html&lt;/a&gt;) &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The default execution unit of Vert.x is Verticle and several Verticles can be simultaneously executed on one Vert.x instance. The Verticles are executed on the event-loop thread. Several Vert.x instances can be executed on several hosts, as well as on one host on the network. At this time, the Verticles or modules communicate by using the event bus.&lt;/p&gt;
&lt;p&gt;To sum up, the vert.x application consists of combinations of Verticles or modules and communication among those is made by using Event Bus.&lt;/p&gt;
&lt;h2&gt;vert.x Project Structure&lt;/h2&gt;
&lt;p&gt;The following is the Vert.x project structure viewed from eclipse when clonning the source code from the &lt;a href=&quot;https://github.com/vert-x/vert.x&quot;&gt;Vert.x Github page&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://helloworld.naver.com/./files/attach/images/61/784/163/./files/attach/images/61/784/163/49e1c3d8d3329e1bd3a1043166caf566.png&quot; alt=&quot;49e1c3d8d3329e1bd3a1043166caf566.png&quot; title=&quot;49e1c3d8d3329e1bd3a1043166caf566.png&quot; class=&quot;iePngFix&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt; Figure 4: Vert.x source tree.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The overall configuration is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt; vertx-core&lt;/b&gt;&amp;nbsp;is the core library.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;vertx-platform&lt;/b&gt;&amp;nbsp;manages distribution and lifecycle.&lt;/li&gt;
&lt;li&gt;&lt;b&gt; vert-lang&lt;/b&gt; used to expose the Core Java API to another language.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://www.gradle.org&quot;&gt;Gradle&lt;/a&gt; is used as its project build system. It has the advantages of ant and maven.&lt;/p&gt;
&lt;h2&gt;Installing Vert.x and Executing Simple Examples&lt;/h2&gt;
&lt;p&gt;To use Vert.x, JDK7 is required because Vert.x uses the &lt;a href=&quot;http://oneminutedistraction.wordpress.com/2010/11/22/invokedynamic-bytecode-in-jdk-7/&quot;&gt;invokeDynamic in JDK7&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14px;&quot;&gt;Vert.x can easily be installed.&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;ownload the compressed installation file from &lt;a href=&quot;http://vertx.io/downloads.html&quot;&gt;http://vertx.io/downloads.html&lt;/a&gt;&amp;nbsp;to a desired location.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Decompress the file and add the bin directory to the PATH environment variables.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span&gt;This is all about the installation of Vert.x. &lt;/span&gt;&lt;span&gt;In the command window, execute the &lt;code&gt;vertx version&lt;/code&gt;. If the version information successfully prints out, the installation is completed.&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Example 1&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Now, let&apos;s build and execute a simple Web server with JavaScript which&amp;nbsp;&lt;span style=&quot;font-size: 14px;&quot;&gt;prints out &quot;hello world&quot;. After writing the following codes, save it in &lt;b&gt;server.js&lt;/b&gt;&amp;nbsp;file. It is almost identical to the Node.js code.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;load(&apos;vertx.js&apos;);

vertx.createHttpServer().requestHandler(function(req) {
req.response.end(&quot;Hello World!&quot;);}) .listen(8080, &apos;localhost&apos;);&lt;/pre&gt;
&lt;p&gt;Execute the created &lt;b&gt;server.js&lt;/b&gt; application by using the vertx command as follows:&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;$ vertx run server.js&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14px;&quot;&gt;Open a browser and connect to&lt;/span&gt; &lt;a href=&quot;http://localhost:8080&quot;&gt;http://localhost:8080&lt;/a&gt;. &lt;span style=&quot;font-size: 14px;&quot;&gt;If you can see the &apos;Hello World!&apos;&amp;nbsp;&lt;/span&gt;message, you have succeeded.&lt;/p&gt;
&lt;h3&gt;Example 2&lt;/h3&gt;
&lt;p&gt;Let&apos;s see another example built other languages. The following code is written in Java. It shows a Web server that reads a static file and returns it as an HTTP response.&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot;  title=&quot;&quot;&gt;
Vertx vertx = Vertx.newVertx();
vertx.createHttpServer().requestHandler(new Handler() {
    public void handle(HttpServerRequest req) {
        String file = req.path.equals(&quot;/&quot;) ? &quot;index.html&quot; : req.path;
        req.response.sendFile(&quot;webroot/&quot; + file);
    }
}).listen(8080);
&lt;/pre&gt;
&lt;p&gt;The following code is written in Groovy and provide the same functionality:&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;def vertx = Vertx.newVertx()
vertx.createHttpServer().requestHandler { req -&amp;gt;
def file = req.uri == &quot;/&quot; ? &quot;index.html&quot; : req.uri
req.response.sendFile &quot;webroot/$file&quot;
}.listen(8080)&lt;/pre&gt;
&lt;h2&gt;Future of Vert.x and NHN&lt;/h2&gt;
&lt;p&gt;At &lt;a href=&quot;/blog/tags/NHN&quot;&gt;NHN&lt;/a&gt;&amp;nbsp;we have been observing Vert.x development since its preofficial release. We think highly of Vert.x. We have been communicating with the main developer, Tim Fox, since June 2012 to discuss ways to improve Vert.x. For example,  &lt;span style=&quot;font-size: 14px;&quot;&gt;Socket.io on Vert.x. Socket.io is available on Node.js only. So we have ported it to Java and sent a Pull Request&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/vert-x/vert.x/pull/320&quot; target=&quot;_blank&quot;&gt;https://github.com/vert-x/vert.x/pull/320&lt;/a&gt;&amp;nbsp;to&amp;nbsp;Vert.x repository on Gitub. It&apos;s now merged to Vert.x-mod project.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14px;&quot;&gt;Our effort, socket.io vert.x module, will be used for RTCS 2.0 version (vert.x + Socket.io) which is under-developing in NHN.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Node.js could remain very popular because of Socket.io. If Vert.x can use Socket.io, Vert.x may have many use cases. Furthermore, if this socket.io vertx module is used as an embedded library, it will be meaningful to use socket.io in Java based applications.&lt;/p&gt;
&lt;h3&gt;What is RTCS?&lt;/h3&gt;
&lt;p&gt;RTCS (Real Time Communication System) is a Real Time Web Development Platform created by NHN. It helps to transfer messages between a Browser and a Server in real time. RTCS has been deployed for NHN Web services such as Baseball 9, Me2Day Chatting, BAND Chatting and so on.&lt;/p&gt;
&lt;h2&gt;Wrap-up&lt;/h2&gt;
&lt;p&gt;The first version of Vert.x was released in May 2012. Compared to Node.js where the first version was released in 2009, the history of Vert.x is very short. Therefore, Vert.x does not have many references&amp;nbsp;yet. However, Vert.x is supported by VmWare and can run on CloudFoundry. So, we expect that many references will soon be obtained.&lt;/p&gt;
&lt;p&gt;By&amp;nbsp;&lt;a href=&quot;/?mid=textyle&amp;amp;act=dispMemberInfo&amp;amp;member_srl=630183&amp;amp;vid=blog&amp;amp;tab=blogs&quot;&gt;Seongmin Woo&lt;/a&gt;, Software Engineer at Web Platform Development Lab, NHN Corporation.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Main Manual&quot; &lt;a href=&quot;http://vertx.io/manual.html&quot;&gt;http://vertx.io/manual.html&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&quot;Installation Guide&quot; &lt;a href=&quot;http://vertx.io/install.html&quot;&gt;http://vertx.io/install.html&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&quot;The C10K problem&quot; &lt;a href=&quot;http://www.kegel.com/c10k.html&quot;&gt;http://www.kegel.com/c10k.html&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Gim Seongbak, Song Jihun &quot;Java I/O &amp;amp; NIO Network Programming&amp;rdquo;, Hanbit Media 2004.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</content>
                  <category term="Vert.x"/>
            <category term="Node.js"/>
            <category term="performance"/>
            <category term="comparison"/>
            <category term="Java"/>
            <category term="JavaScript"/>
            <category term="Groovy"/>
            <category term="Gradle"/>
            <category term="IMDG"/>
            
   </entry>
   <entry>
      <title>Understanding Encryption and Security through Java Cryptography Architecture</title>
      <id>http://www.cubrid.org/blog/629824</id>
      <published>2013-04-08T18:36:20-07:00</published>
      <updated>2013-04-08T18:36:20-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/629824"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/629824#comment"/>
      <author>
         <name>Jaehee Ahn</name>
                  <uri>http://www.cubrid.org</uri>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;For a long time, Java has provided security-related functions. Among the security-related functions, &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&quot;&gt;Java Cryptography Architecture&lt;/a&gt; (JCA) is the core one. JCA uses a provider structure with a variety of APIs related to security. These functions are essential for modern IT communication encryption technology, including Digital Signature, Message Digest (hashs), Certificate, Certificate Validation, creation and management of Key, and creation of Secure Random Number.&lt;/p&gt;
&lt;p&gt;With JCA, even developers who do not have specialized knowledge of encryption can successfully implement security-related functions.   You don&apos;t need to use algorithms like those you had to rack your brain for a long time to understand in computer science classes and cryptology-related classes. JCA allows you to implement the algorithms with a few lines of codes. Of course, utilizing the APIs well will be highly valuable for business. But, it does not mean that you do not need to understand how JCA runs. Understanding how JCA runs internally will be important to using the functions more efficiently.&lt;/p&gt;
&lt;p&gt;To be a better software developer and architect, you may need to trace how the result, JCA, was created from the cryptology and security-related algorithms. This article is a summary of JCA architecture that I learned while producing the nClavis (Symmetric-key cryptography) at &lt;a href=&quot;/http:/www.cubrid.org/blog/tags/NHN&quot;&gt;NHN&lt;/a&gt;. Of course, I do not understand all of JCA yet. However, I was so happy to understand JCA at this level that I decided to write this article to share my experience with you.&lt;/p&gt;
&lt;h2&gt;Design Principles&lt;/h2&gt;
&lt;p&gt;As I mentioned, JCA is a Java security platform, based on the provider structure, having implementation independence, implementation interoperability, and algorithm extensibility.&lt;/p&gt;
&lt;p&gt;An application can utilize the information protection encryption technology just by requesting security services on the Java platform, without implementing security algorithms. JCA-provided security services are implemented by the provider mounted on the Java security platform. An application can introduce a variety of security functions by using several independent providers. The list of providers is described in the &lt;strong&gt;jre/lib/security/java.security&lt;/strong&gt; file. The Java platform includes many providers and installs them by default when JRE is installed.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Code 1: java.security file.&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot;  title=&quot;&quot;&gt;#
# List of providers and their preference orders (see above):
#
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=com.sun.net.ssl.internal.ssl.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider
security.provider.6=com.sun.security.sasl.Provider
security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.8=sun.security.smartcardio.SunPCSC
security.provider.9=sun.security.mscapi.SunMSCAPI&lt;/pre&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;The providers mounted on the Java security platform by default are compatible with all Java applications and so widely used to regard them as trusted. Of course, JCA supports mounting of custom providers for applications which want to introduce the latest security technology that has not been implemented yet.&lt;/p&gt;
&lt;h2&gt;Architecture&lt;/h2&gt;
&lt;h3&gt;Cryptographic Service Providers&lt;/h3&gt;
&lt;p&gt;All providers are an implementation of java.security.Provider. This provider implementation includes the list of security algorithm implementations. When an instance of a specific algorithm is necessary, the JCA framework searches the proper implementation class of the corresponding algorithm from the provider repository and creates a class instance. The providers defined in the java.security file are included in the repository by default. In this way, a provider can be statically included. In addition, it can be dynamically added in runtime. When several providers are defined, they may implement an identical encryption algorithm in different ways. In this case, an application can specify the provider or specify the preference in the repository.&lt;/p&gt;
&lt;p&gt;To use JCA, an application simply requests a specific object type (such as MessageDigest) and an algorithm or service (e.g., MD5). Then, the application obtains an implementation from one of the installed providers. Of course, it can explicitly request an object of a specific provider.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b style=&quot;text-align: center;&quot;&gt;Code 2: Requesting an Object of a Provider.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot;  title=&quot;&quot;&gt;md = MessageDigest.getInstance(&quot;MD5&quot;);
md = MessageDigest.getInstance(&quot;MD5&quot;, &quot;ProviderC&quot;);&lt;/pre&gt;
&lt;pre class=&quot;brush:java&quot;&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;413&quot; width=&quot;490&quot; alt=&quot;provider_framework_of_jca_java.png&quot; src=&quot;/files/attach/images/220547/824/629/provider_framework_of_jca_java.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1: Provider Framework of JCA&lt;/b&gt; (Source: &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&quot;&gt;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Oracle JRE (Sun JDK) has a variety of providers (Sun, SunJSSE, SunJCE, and SUnRsaSign) included by default. The criteria of classifying the providers are made based on the production process; functions or algorithms used by each provider are not so different from each other. JRE except Oracle has no need to include the providers mandatorily. Therefore, it is not recommended to implement an application in the provider-dependent way. All encryption technology implementations required by an application are provided by default and implemented with a fully reliable level. Therefore, developers do not need to pay attention to a provider itself.&lt;/p&gt;
&lt;h3&gt;Key Management&lt;/h3&gt;
&lt;p&gt;Two of the most important things in JCA are &lt;b&gt;provider&lt;/b&gt; and &lt;b&gt;key management&lt;/b&gt;. Java uses a kind of key database, called &quot;&lt;b&gt;keystore&lt;/b&gt;&quot;, to manage the key/certificate repository. KeyStore can be usefully used in an application that needs information for authentication, encryption, or signature.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;An application can access the KeyStore by using the implementation of the &lt;code&gt;java.security.KeyStore&lt;/code&gt; class. The default KeyStore implementation is provided by Sun Microsystems (the package name still starts with com.sun even though Oracle acquired it long time ago :D). The KeyStore is created as a file with the naming rule of &amp;ldquo;jks&amp;rdquo;. It can also be converted to the type of &amp;ldquo;&lt;b&gt;jceks&lt;/b&gt;&amp;rdquo; or &amp;ldquo;&lt;b&gt;pkcs12&lt;/b&gt;&amp;rdquo; in order to suppoprt applications which use another format of KeyStore implemetation.&lt;/p&gt;
&lt;p&gt;&quot;&lt;b&gt;jceks&lt;/b&gt;&quot; format is in PBE format which uses triple DES, which uses even stronger encryption algorithm than &quot;&lt;b&gt;jks&lt;/b&gt;&quot; type, to protect KeyStore.&lt;/p&gt;
&lt;p&gt;&quot;&lt;b&gt;pkcs12&lt;/b&gt;&quot; format is a standard syntax to exchange personal information, based on RSA. For machines, applications, and browser Internet kiosks that support this standard, users can export, import, or activate the personally identifying information (certificates for identification, &lt;b&gt;pkcs12&lt;/b&gt; format certificates). Safari, Chrome, and IE browsers follow this standard. Therefore, when the &lt;b&gt;pkcs12&lt;/b&gt; certificate file is installed once, it is applied to all browsers. However, Firefox does not follow this standard.&lt;/p&gt;
&lt;p&gt;KeyStore is to save and to manage SecretKey (SymmetricKey), Public/Private KeyPair (AsymmetricKey), self-signed certificate, and the certificates signed by trusted CA (Certificate Authority) or the private CA on a file. Here, experienced developers may recall OpenSSL which was used to create a certificate file. Both certificate files have the same purpose but different file format. However their formats are convertible.&lt;/p&gt;
&lt;p&gt;Java even provides &apos;&lt;b&gt;keytool&lt;/b&gt;&apos; command-line utility in JDK_HOME/bin directory, which is similar as OpenSSL&apos;s utility. Therefore you can handle certificates using a keytool on Windows, unlikely OpeSSL only on Linux. Of course, this tool runs with the KeyStore implementation provided by Oracle JRE. If JDK is installed in the system, a certificate can be created by using the keytool. However, note that the keytool can provide the functions at the same level provided by OpenSSL from JAVA. A KeyStore file created by using the keytool is compatible with the lower Java versions, so you do not need to worry about it.&lt;/p&gt;
&lt;h4&gt;In-depth 1: Certificate.&lt;/h4&gt;
&lt;p&gt;Here, I need to address the correct meaning of &lt;i&gt;certificate&lt;/i&gt;. In a narrow sense, KeyStore is a kind of certificate. A certificate is used for two purposes; a &quot;lock&quot; required for encrypting the information and a tool for &quot;identification&quot; to identify the opponent technically. The authenticated certificate used for bank transactions is a security technology which utilizes both purposes of a certificate.&lt;/p&gt;
&lt;p&gt;The cryptographic meaning of a certificate is an electronic document that uses a digital signature to sign the public key created by the RSA algorithm (asymmetric-key cryptography) with the private key of the certificate authority (CA).&lt;/p&gt;
&lt;p&gt;It is popular practice that a pair of keys created by using the RSA algorithm is solid. It had been proven long ago that calculating the other key by using one key within a meaningful time is impossible. So, why is electronic signature required? When &quot;A&quot; and &quot;B&quot; communicate with each other by encrypting their data, A opens its public key and then protects the private key paired with the public key. Then B encrypts the data to be sent to A by using the public key of A. In this case, there is a problem of how B will know it can trust the public key; is it really provided by A? When a malicious attacker &quot;C&quot; disguises its public key as A&apos;s to deceive B, the public key cannot be used. To solve this problem, a trusted certificate authority &quot;D&quot; is necessary. The CA has a chain structure from the top root certificate authority to the sub certificate authority. In this structure, the upper layer certifies the lower layer by using signature. As it had been rooted as a worldwide standard so long ago, the signature chain of the certificates around the world includes a few common top root CAs (e.g. VeriSign, Thawte). Countries of which IT communication environment reaches a certain standard have their national root CA (e.g., KISA in Korea). The top root CAs may have a circular structure that allows signatures with each other. In some cases, one CA can sign the public key with its private key.&lt;/p&gt;
&lt;p&gt;So, the signature of CA should not be valid limitlessly but updated regularly or irregularly by other security events.&lt;/p&gt;
&lt;p&gt;It is possible for an individual or a company to establish a private certificate authority if required. Certificates signed by the private certificate authority have a more complex certification process. You may have seen the following &lt;b&gt;Figure 2&lt;/b&gt; on your browser:&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;287&quot; width=&quot;700&quot; alt=&quot;browser_display_when_private_certificate_authority_is_used.png&quot; src=&quot;/files/attach/images/220547/824/629/browser_display_when_private_certificate_authority_is_used.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 2: Browser Display when Private Certificate Authority is used.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;It is displayed when the website uses the private certificate authority. On the browser (even though it is not recommended), the user can skip this situation by clicking the mouse. However, for server-to-server connection, the opponent&apos;s certificate issued by the private certificate authority should be imported to &lt;code&gt;JAVA_HOME/jre/lib/security/cacerts&lt;/code&gt; or added to &lt;code&gt;SSLContext&lt;/code&gt; when creating the connection of the program code.&lt;/p&gt;
&lt;p&gt;The certificates from official certificate authorities are widely granted as trusted CAs and included to the OS or JRE by default. Therefore, the situation illustrated in &lt;b&gt;Figure 2&lt;/b&gt; does not occur. If a private certificate authority can obtain the pkcs12 format certificate, the private certificate authority is considered as a trusted CA. Therefore, it can be easily installed in the system.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Code 2: Certificate Verification Program installed in the system.&lt;/b&gt;&lt;/p&gt;
&lt;h4&gt;
&lt;pre class=&quot;brush:java&quot;  title=&quot;&quot;&gt;@Windows&amp;gt;certmgr.msc
@MAC OS X&amp;gt;Keychain Access
@Linux&amp;gt; keychain&lt;/pre&gt;
&lt;/h4&gt;
&lt;h4&gt;In-depth 2:  HTTPS&lt;/h4&gt;
&lt;p&gt;To understand encryption, you need to understand SSL/TLS, the certificate-based cryptographic protocols, as well as certificate. The purpose of a certificate can be easily misunderstood when encrypting the HTTPS protocol communication section. When a server and a client communicate via HTTPS, if only the communication section is encrypted without identifying the client (setting the clientAuth attribute of HTTPS Connector to false in the server.xml setting of Tomcat), only a simple certification verification is executed.  Symmetric-key cryptography is used for encryption of data.&lt;/p&gt;
&lt;p&gt;Here, I will describe how a certificate is used through HTTPS.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;&lt;ol&gt;
&lt;li&gt;A client connects to a server via the HTTPS protocol (at this time, the SSL connection-defined server port is used).&lt;/li&gt;
&lt;li&gt;The server sends its certificate public key to the client.(including several meta information for validation and Cipher supported by the server)&lt;/li&gt;
&lt;li&gt;The client validates the server with the public key and meta information sent by the server.(checking whether the public key is signed with a trusted official Root CA)&lt;ol&gt;
&lt;li&gt;When the certificate of the server is signed with the official CA, it is passed (the official CAs are registered to the system as a trusted authority by default).&lt;/li&gt;
&lt;li&gt;When the certificate of the server is signed with a private CA, checking the trust manager of the SSL socket (SSLContext) created by the client. If the certificate is registered, it is passed.&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;When the server&apos;s certificate passes the validation check, the client creates a symmetric key, encrypts the symmetric key and the cipher as a public key of the server, and then sends them to the server.(the symmetric key is created by selecting one of cipher algorithms supported by the server)&lt;/li&gt;
&lt;li&gt;The server decodes the [symmetric key and cipher: encrypted as the public key of the server] to its private key and acquires the symmetric key to be used for encrypted communication.&lt;/li&gt;
&lt;li&gt;After that, data communication between the server and the client is made to be encrypted with the symmetric key created by the client.&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
&lt;h2 class=&quot;xe_content&quot;&gt;JCA Structure&lt;/h2&gt;
&lt;p class=&quot;xe_content&quot;&gt;JCA structure can be described with Engine class and algorithm. In JCA, an Engine class provides interfaces for all encryption service types regardless of a specific encryption algorithm or provider. The engine class provides one of the following functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encryption operations (encryption, digital signatures, message digests, etc.) &lt;/li&gt;
&lt;li&gt;Creating and converting the elements (keys and algorithm parameters) required for encryption &lt;/li&gt;
&lt;li&gt;Objects (keystores or certificates) which imply the encryption data or can be used by an object or the upper abstraction layer &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s take a look at the Engine classes provided by JCA and talk about encryption in detail.&lt;/p&gt;
&lt;h3&gt;SecureRandom&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SecureRandom&lt;/code&gt; class is used to create a Pseudo Random number.&amp;nbsp;In Java, random refers to Pseudo Random, as a more accurate expression. If so, are random and pseudo random different? Technically, they are different. There are two random types: &lt;b&gt;True Random&lt;/b&gt; and &lt;b&gt;Pseudo Random&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;True Random&lt;/b&gt; is a random number which cannot be forecasted. You may say that Pseudo Random cannot be forecasted. Pseudo Random is a random progression determined by seed and a mathematical algorithm. It has a sequence which is eventually repeated even if it takes a very long time or its probability is very low. In addition, if you know the seed and the random algorithm, you can forecast the sequence of the Pseudo Random. True Random creates a random number based on atomic physical phenomena, not the mathematical way used by the Pseudo Random. If there is no hardware equipment to measure the atomic physical phenomena, e.g., electromagnetic noises and radioactive element decay, it is impossible to create True Random.&lt;/p&gt;
&lt;p&gt;JCA SecureRandom class is an engine class that provides a powerful function to create random numbers. As I described, it is not easy to implement a True Random Number Generator (TRNG). Therefore, many implementations implement Pseudo Random Number Generator (PRNG). As mentioned before, the random level of the pseudo random is incomplete. The popular random class cannot satisfy the minimum level that is required cryptographically. Therefore, the implementation of SecureRandom should be verified that it satisfies the requirements of cryptographic level (CSPRNG).&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;305&quot; width=&quot;530&quot; alt=&quot;classification_of_encryption_type.png&quot; src=&quot;/files/attach/images/220547/824/629/classification_of_encryption_type.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 3: Classification of Encryption Type&lt;/strong&gt; (source: &lt;a href=&quot;http://en.wikipedia.org/wiki/Cipher&quot;&gt;http://en.wikipedia.org/wiki/Cipher&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Now, you may ask why creating the random number is considered such an very important thing for encryption.&lt;/p&gt;
&lt;p&gt;The core of modern cryptology is the key used for encryption. Previously, cryptology had been based on a conversion table like Base64 or UTF8 encoding. For modern cryptology, that kind of traditional method is not considered as encryption any more. The key is a random sequence generated by the random sequence generator. We naturally think of an encryption algorithm as thinking of cryptology. However, the open symmetric key encryption algorithm can be simplified to XOR operation (or multiplication/division operation) for the input values and key streams. As I said, the core is the key.&lt;/p&gt;
&lt;p&gt;If the random level of a random sequence generator is not ensured, the entire outline of the key may be revealed to an attacker when a part of created key or some sequential random sequences are leaked out to the attacker. For modern cryptology, the key used for encryption is the core. So, the random sequence generator is very important.&lt;/p&gt;
&lt;p&gt;JCA uses SecureRandom as the random sequence generator. Implementation of an algorithm to create random numbers is provided by a provider, like other encryption algorithms.&lt;/p&gt;
&lt;h3&gt;MessageDigest&lt;/h3&gt;
&lt;p&gt;MessageDigest is used to calculate the message digest (hash) of input data.&lt;/p&gt;
&lt;p&gt;The purpose of message digest is the integrity check to check whether the original file is reserved as it is. Message digest algorithm processes a variable-length original message into a fixed-length hash output. Message digest algorithm consists of a unidirectional hash function, so it is not possible to draw the original value from the hash value. When A and B are communicating with each other, A sends the original message, message hash value of the original message, and the message digest algorithm to B. B calculates the message hash value by using the algorithm and original message sent from A. When the message hash value calculated by B is identical to the message hash value sent from A, it means that the original message sent from A has not been changed or modified until B receives it via the network.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;215&quot; width=&quot;477&quot; alt=&quot;using_messagedigest_at_download_site.png&quot; src=&quot;/files/attach/images/220547/824/629/using_messagedigest_at_download_site.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 4: Example of Using MessageDigest at a Download Site.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;You can frequently see Checksums or digital fingerprints at download sites. It is an alternative name for MessageDigest. MD5 or SHA1 is the well-known message digest algorithm.&lt;/p&gt;
&lt;h3&gt;Signature&lt;/h3&gt;
&lt;p&gt;Signature is used to sign data and to decide validity of the digital signature with a key received during initialization. Receiving a key means that key-based encryption is executed.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;172&quot; width=&quot;444&quot; alt=&quot;flow_of_actions_of_signature_object.png&quot; src=&quot;/files/attach/images/220547/824/629/flow_of_actions_of_signature_object.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 5: Flow of Actions of Signature Object&lt;/b&gt;&amp;nbsp;(source: &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&quot;&gt;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In initialization, Signature Object receives the private key and the original data to be signed as parameters and finishes preparation for signing. The sign() method of Signature signs the original data with the private key and returns Signature Bytes. To validate the signed data, the verification signature object is initialized by using the public key paired with the private key used for signing. The object additionally receives the original data, signature output and Signature Bytes, and the verify method checks whether the two parameters are identical to determine the reliability of the original data. Signature can be made only by the person who holds the private key. However, verification is made by using the public key. So, anyone who acquired the public key can perform verification.&lt;/p&gt;
&lt;h2&gt;Digital Signature vs Cryptography vs MessageDigest&lt;/h2&gt;
&lt;p&gt;For cryptography, users can select either symmetric key method or asymmetric key method based on the user&apos;s request. Digital signature is also a kind of cryptography. However, asymmetric key encryption is a prerequisite for digital signature. In addition, digital signature is a combination of MessageDigest and asymmetric key encryption. Large-capacity data with a variable length is compressed to a fixed-length format which is easy to manage by the MessageDigest and then signed with a private key to create fixed-length signature bytes. When creating a signature instance, you can see the principle of digital signature from the signature algorithm names, such as SHA1withRSA, MD5withRSA, SHA1withDSA; the signature algorithms are sent as a signature.getInstance() parameter and their names are made by combining RSA (asymmetric key encryption algorithm), MessageDigest algorithm, SHA1, and MD5.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;Signature dsa = Signature.getInstance(&quot;SHA1withDSA&quot;);&lt;/pre&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h3&gt;Signed Certificate&lt;/h3&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;Keystore Type: jks
Keystore Provider: SUN

Keystore includes the following two items:

Alias: rootcaalias
Written on: 2012. 9. 26
Input Type: trustedCertEntry

Holder: CN=NSYMKEY Root CA, OU=NHN NBP, O=NHN INC
Issuer: CN=NSYMKEY Root CA, OU=NHN NBP, O=NHN INC
Serial Number: 
Opened on: Fri Apr 06 10:17:08 KST 2012 Expired on: Sun Mar 13 10:17:08 KST 2112
Certificate Fingerprint:
MD5: 0C:FC:12:C5:68:E5:95:0B:95:7D:B0:2F:FA:4F:DB:B4
SHA1: 90:37:1C:E6:F4:64:AD:E6:27:AA:4F:58:88:16:11:24:6D:A5:EB:2B


*******************************************
*******************************************

Alias: nplatform
Written on: 2012. 9. 26
Input Type: keyEntry
Length of Certificate Chain: 2
Certificate[1]:
Holder: O=NHN INC, OU=NHN NBP, CN= NPLAFORM, UID=1
Issuer: CN=NSYMKEY Root CA, OU=NHN NBP, O=NHN INC
Serial Number: 
Opened on: Fri Sep 21 17:26:22 KST 2012 Expired on: Sun Aug 28 17:26:22 KST 2112
Certificate Fingerprint:
MD5: 48:8C:46:A3:E7:54:58:97:60:0D:5C:56:08:B0:D1:E7
SHA1: 12:64:3C:DA:C1:2C:94:1A:2B:EB:E9:98:2B:DA:8F:06:78:6E:26:1E

Certificate[2]:
Holder: CN=NSYMKEY Root CA, OU=NHN NBP, O=NHN INC
Issuer: CN=NSYMKEY Root CA, OU=NHN NBP, O=NHN INC
Serial Number: 
Opened on: Fri Apr 06 10:17:08 KST 2012 Expired on: Sun Mar 13 10:17:08 KST 2112
Certificate Fingerprint:
MD5: 0C:FC:12:C5:68:E5:95:0B:95:7D:B0:2F:FA:4F:DB:B4
SHA1: 90:37:1C:E6:F4:64:AD:E6:27:AA:4F:58:88:16:11:24:6D:A5:EB:2B&lt;/pre&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;Let&apos;s review certificate and signature, which were described in the previous in depth section, with JCA Signature object mechanism.&lt;/p&gt;
&lt;p&gt;The above text box is the KeyStore certificate file created by using the keytool of Java. From Holder and Issuer of Certificate[1], you can see that &amp;ldquo;CN=NSYMKEY Root CA, OU=NHN NBP, O=NHN INC&amp;rdquo; has signed the certificate of Holder &amp;ldquo;O=NHN INC, OU=NHN NBP, CN= NPLAFORM, UID=1&amp;rdquo; by using its private key. The result of the signature is the Certificate Fingerprint. The length of the Certificate Fingerprint is decided by the MessageDigest algorithm (MD5 or SHA1). As following the Certificate Chain, you can see that the Holder and Issuer of Certificate[2] are identical. It means that &amp;ldquo;CN=NSYMKEY Root CA, OU=NHN NBP, O=NHN INC&amp;rdquo; is self-signed by using its private key. As the Certificate[2] has self-signed, the Certificate Chain is ended here.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h3&gt;Cipher Class&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;136&quot; width=&quot;451&quot; alt=&quot;flow_of_actions_of_cipher_object.png&quot; src=&quot;/files/attach/images/220547/824/629/flow_of_actions_of_cipher_object.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 6: Flow of Actions of Cipher Object&lt;/strong&gt; (source: &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&quot;&gt;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Cipher class provides encryption/decryption functions. The encryption/decryption algorithms are variously classified as follows: Symmetric bulk encryption (AES, DES, DESede, Blowfish, IDEA), Stream encryption (RC4), Asymmetric encryption (RSA), and Password-based encryption (PBE).&lt;/p&gt;
&lt;p&gt;I will not describe classification of encryption to Symmetric and Asymmetric because the classification is so well-known.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h3&gt;Stream vs. Block Cipher&lt;/h3&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;Symmetric bulk encryption can be classified into Stream and Block Cipher. Block Cipher encodes the data in the fixed-length block unit. Data whose length does not fit the fixed length is padded with dummy values. Bytes padded are removed while decrypting the data. This padding is executed by the padding type (e.g., PKCS5PADDING) which is sent as a parameter while initializing Cipher. On the contrary, Stream Cipher processes input data in the unit of byte or bit. Therefore, it can process variable-length data without padding.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h3&gt;Modes Of Operation&lt;/h3&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;The important concept of Block Cipher you should know is Feedback Modes. Assume a very simple block cipher. If the input data is identical, the encrypted result is identical. From this characteristic, attackers obtain a hint to decrypt the encrypted data with a repeated same pattern.&lt;/p&gt;
&lt;p&gt;To avoid security vulnerabilities and make Cipher more complex, Feedback Mode was introduced. Feedback Mode is an operation which combines (XOR operation) the Nth input data block (or the Nth encrypted result data block) and the N-1st input data block (or the N-1st encrypted result data block) at the Nth encryption process. Therefore, when the input data blocks are identical, the result values are different corresponding to the variables used in the previous encryption process. Note one more thing: if N = 1, any variable cannot be acquired from the N-1st encryption process. In this case, Initial Value (IV) takes the role instead of the variable in the previous process. To use Feedback Mode, the IV value should be randomly created and prepared for encryption. The IV value used for encryption should be stored because it is necessary for decryption as well.&lt;/p&gt;
&lt;p&gt;The feedback modes provided by JCA are CBC, CFB, and OFB. The mode that no feedback mode is used is called ECB for distinction. More detailed description of each mode will not be provided here.&lt;/p&gt;
&lt;p&gt;Figure 7 shows the importance of feedback modes. If the original image data is encrypted without using the feedback mode (ECB MODE), identical input data is used and an identical encryption result is acquired. Therefore, the entire outline is drawn up.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;328&quot; width=&quot;608&quot; alt=&quot;image_encryption.png&quot; src=&quot;/files/attach/images/220547/824/629/image_encryption.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 7: Image Encryption&lt;/strong&gt; (source: &lt;a href=&quot;http://en.wikipedia.org/wiki/Modes_of_operation&quot;&gt;http://en.wikipedia.org/wiki/Modes_of_operation&lt;/a&gt;).&lt;/p&gt;
&lt;h3&gt;Creating Cipher Object&lt;/h3&gt;
&lt;p&gt;The essential thing for creating a Cipher instance is to specify transformation. Transformation consists of encryption algorithms (/feedback modes/paddings) described before. Only the encryption algorithm values can be specified. But, the default feedback mode/padding (ECB/PKCS5Padding) is internally specified.&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;Cipher c1 = Cipher.getInstance(&quot;DES/ECB/PKCS5Padding&quot;);

or

Cipher c1 = Cipher.getInstance(&quot;DES&quot;);&lt;/pre&gt;
&lt;div&gt;&lt;/div&gt;
&lt;pre class=&quot;brush:java&quot;&gt;&lt;/pre&gt;
&lt;p&gt;The Cipher class instance can be initialized by selecting one from four modes (opmode: Encryption, Decryption, Wrap, Unwrap) for initialization.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WRAP_MODE: Wraps Java.security.Key to convert it to the byte unit for secured key transmission &lt;/li&gt;
&lt;li&gt;UNWRAP_MODE: Unwraps the wrapped key to the Java.security.Key object &lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;p&gt;When initializing the cipher class instance, the &lt;code&gt;init()&lt;/code&gt; method is called as its parameter. It requests opmode, key(certificate), params, and random as its parameters. Here, note the AlgorithmParameters-type params parameter. This instance is used to store the IV value of feedback mode and the salt value and the iteration count value of the PBS algorithm. These values are not required when initializing cipher of &lt;code&gt;ENCRYPTION_MODE&lt;/code&gt;. These can be randomly created by ScureRandom and used for the encryption process. The values created are stored in the AlgorithmParameters field of the encryption cipher object. On the other hand, the params value is required for initializing &lt;code&gt;DECRYPTION_MODE&lt;/code&gt; Cipher. In the decryption process, the params value identical to the value used for the encryption process is required. When the &lt;code&gt;init()&lt;/code&gt; method is called, all existing values are deleted from the cipher class. Therefore, before initializing the cipher instance again, the &lt;code&gt;getParameters()&lt;/code&gt; method should be called to store the AlgorithmParameter object used for the encryption process.&lt;/p&gt;
&lt;p&gt;To make the jobs simpler, SealedObject can be used in the encryption result. &lt;code&gt;SealedObject&lt;/code&gt; class receives a target statement to encrypt and Cipher object as arguments(sealing process  in SealedObject class). The &lt;code&gt;SealedObject&lt;/code&gt; itself is an encrypted data and it manages algorithm arguments used for encryption. If a key used in encryption process is passed, you can  obtain decrypted data(unsealing process in &lt;code&gt;SealedObject&lt;/code&gt; class).&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Code 4: Encryption using SealedObject.&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot;&gt;&lt;pre class=&quot;brush:java&quot;  title=&quot;&quot;&gt;//Create Cipher object
Cipher c = Cipher.getInstance(&quot;DES&quot;);
c.init(Cipher.ENCRYPT_MODE, sKey);
// Create SealedObject: it is an encryped data
SealedObject so = new SealedObject(&quot;This is a secret&quot;, c);&lt;/pre&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Code 5 Decryption using SealedObject&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot;&gt;&lt;pre class=&quot;brush:java&quot;  title=&quot;&quot;&gt;//Note: sKey is as same as encryption key
//Note: so is SealedObject which was previously created. 
//Decryption using SealedObject #1
//Decrypt using Cipher object
c.init(Cipher.DECRYPT_MODE, sKey);
try {
	String s = (String)so.getObject(c);
} catch (Exception e) {
	//do something
};
//Decryption using SealedObject #2
//Decrypt using encryption key
try {
	String s = (String)so.getObject(sKey);
} catch (Exception e) {
	//do something
};&lt;/pre&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;h3&gt;Message Authentication Codes(MAC)&lt;/h3&gt;
&lt;p&gt;MAC is similar to MessageDigest because it creates the hash value; however, it is different from MessageDigest in that it requires SecretKey (symmetric key) for initialization. MessageDigest allows any receiving party to execute integrity check for the received message. However, MAC allows only the party which has the identical SecretKey to execute integrity check for the received message. MAC is used among those who share the SecretKey.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;170&quot; width=&quot;308&quot; alt=&quot;flow_of_actions_of_mac.png&quot; src=&quot;/files/attach/images/220547/824/629/flow_of_actions_of_mac.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 8. Flow of Actions of MAC&lt;/strong&gt; (source: &lt;a href=&quot;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&quot;&gt;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&lt;/a&gt;).&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;HMAC is a MAC based on the encryption hash function (MessageDigest algorithm: MD5 or SHA1). HMAC is a combination of MessageDigest algorithm and shared SecretKey.&lt;/p&gt;
&lt;p&gt;Signature is different from HMAC because Signature uses the asymmetric key. HMAC allows identifying the opponent faster than the signature that uses the RSA algorithm. So, some services strategically use HMAC.&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;div&gt;
&lt;p&gt;So far, I have described half of JCA functions. However, the rest of the functions are also important even if they are not described here. This article does not include the other core of JCA, such as Key, KeyPair, KeyFactory, KeyGenerator, KeyStore, CertificateFactory, and CertStore. I think that the functions should be deeply and fully described. For lack of space, I won&apos;t deal with the functions here. They will be described in the next article if possible.&lt;/p&gt;
&lt;p&gt;It was very difficult to study JCA and prepare this article. I felt that there were more things to study and research as I prepared the article and was left with even more questions while writing. I hope my article will help you to understand the &quot;vague&quot; concept of encryption more clearly.&lt;/p&gt;
&lt;p&gt;By Jaehee Ahn, Software Egnineer at Web Platform Development Lab, NHN Corporation.&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html&quot;&gt;http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Modes_of_operation&quot;&gt;http://en.wikipedia.org/wiki/Modes_of_operation &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Cipher&quot;&gt;http://en.wikipedia.org/wiki/Cipher &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Stream_Cipher&quot;&gt;http://en.wikipedia.org/wiki/Stream_Cipher &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://luxsci.com/blog/how-does-secure-socket-layer-ssl-or-tls-work.html&quot;&gt;http://luxsci.com/blog/how-does-secure-socket-layer-ssl-or-tls-work.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</content>
                  <category term="Java"/>
            <category term="JCA"/>
            <category term="security"/>
            <category term="encryption"/>
            <category term="HTTPS"/>
            <category term="certificate"/>
            
   </entry>
   <entry>
      <title>Database Sharding Platform at NHN</title>
      <id>http://www.cubrid.org/blog/323507</id>
      <published>2012-04-09T22:40:32-07:00</published>
      <updated>2013-03-24T18:53:10-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/323507"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/323507#comment"/>
      <author>
         <name>jeonwonhee</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&quot;&lt;i&gt;Ins and outs of NHN&lt;/i&gt;&quot; is a series of articles that compares platforms and services from third-party vendors with &lt;a target=&quot;_self&quot; href=&quot;/blog/tags/NHN/&quot;&gt;NHN&lt;/a&gt;&apos;s own solutions.  The topic of this first article in the series is &lt;b&gt;Database&amp;nbsp;Sharding Platform&lt;/b&gt;. I will introduce about the efforts being made from inside and outside of NHN to implement&amp;nbsp;Database Sharding. I will first explain the concept of Sharding data vs. Partitioning data. Then review the common methodology to implement sharding. And finally I will compare all sharding platforms. This article is recommented for developers interested in big data management.&lt;/p&gt;
&lt;h2&gt;Database Expansion&lt;/h2&gt;
&lt;p&gt;To store and search a volume of data which is so big that it cannot be handled by one database, you must find a way to use multiple databases.  Although there are some databases made for distributed environments, such as Cassandra or Dynamo, these have many functional constraints, such as weakness in terms of search range or inability to use the JOIN operations.  In order to expand data while using a relatively feature-rich functionality, it is recommended to use RDBMS by sharding the databases.&lt;/p&gt;
&lt;p&gt;In the past, the Sharding logic was implemented directly on the application layer, but now there is an increasing number of examples which introduce&amp;nbsp;&lt;i&gt;Sharding platforms&lt;/i&gt;&amp;nbsp;which allow to move the Sharding logic from the application layer to database or middleware layers.  At a core level, Sharding platforms must respond effectively to ever-increasing data without failure, and handle different data characteristics and models depending on services.&lt;/p&gt;
&lt;p&gt;In this article I will  compare &lt;a href=&quot;http://spockproxy.sourceforge.net/&quot;&gt;Spock Proxy&lt;/a&gt;, the Sharding platform based on MySQL Proxy, &lt;a href=&quot;https://github.com/twitter/gizzard&quot;&gt;Gizzard&lt;/a&gt;, created by Twitter, and &lt;b&gt;CUBRID SHARD&lt;/b&gt;, native database sharding feature in CUBRID which is set to launch in the first half of 2012. A table of other solutions was previous posted at &lt;a target=&quot;_self&quot; href=&quot;/blog/cubrid-life/database-sharding-with-cubrid/&quot;&gt;Database Sharding with CUBRID&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Horizontal Partitioning and Sharding&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;Horizontal partitioning&lt;/b&gt; is a design that divides and stores data, such as a schema, into two or more tables &lt;em&gt;&lt;strong&gt;within one database&lt;/strong&gt;&lt;/em&gt;. For example, to handle large data of user messages, such schema may be created so that messages by users from city A are stored in one table, while messages by users from city B are stored in another table. This allows to reduce the size of the index and increase the concurrency of operations. The key point in this approach is that the data is partitioned between tables&amp;nbsp;&lt;i&gt;&lt;b&gt;within a single database&lt;/b&gt;&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Sharding&lt;/b&gt;, on the other hand, is the &lt;i&gt;&lt;b&gt;distributed&lt;/b&gt;&lt;/i&gt;&amp;nbsp;approach where data is horizontally partitioned between tables created in &lt;i&gt;&lt;b&gt;physically different databases&lt;/b&gt;&lt;/i&gt;. &amp;nbsp;Thus, Sharding is a method to store the&amp;nbsp;messages by users from city A&amp;nbsp;in &lt;i&gt;database A&lt;/i&gt; and&amp;nbsp;messages by users from city B&amp;nbsp;in &lt;i&gt;database B&lt;/i&gt;. Here each database is called a&amp;nbsp;&lt;b&gt;Shard&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;As you have to work on multiple databases, there could be functional limitations based on circumstances and also drawbacks in terms of consistency and replication, including JOIN operations.  In many cases, Sharding used to be implemented at the application server level.  There have been many attempts to provide this at the platform level.   These can be classified into a pattern that operates in the application server, such as  &lt;a href=&quot;http://www.hibernate.org/subprojects/shards.html&quot;&gt;Hibernate Shards&lt;/a&gt;, a middle tier pattern such as CUBRID SHARD, Spock Proxy, or Gizzard, and a pattern that provides the Sharding functionality from a database itself, e.g. &lt;a href=&quot;http://devcafe.nhncorp.com/nStore&quot;&gt;nStore&lt;/a&gt; or &lt;a href=&quot;http://www.mongodb.org/&quot;&gt;MongoDB&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Middle Tier Sharding Platform&lt;/h2&gt;
&lt;p&gt;By default, a Sharding platform should consider the following items:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Database location abstraction&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;li&gt;Monitoring/Ease of operations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Database location abstraction&lt;/b&gt; and &lt;b&gt;scalability&lt;/b&gt; are different from each other but connected.  &lt;i&gt;Database location abstraction&lt;/i&gt; ensures that&amp;nbsp;on the application layer&amp;nbsp;you do not need to know which data (which Row) is located in which database. The application is connected only with the &lt;i&gt;Sharding platform&lt;/i&gt;. Connecting to a database is what the Sharding platform should do. In addition, Sharding platform should carry out the task to add a replicated storage to a specific Shard (one of the partitioned databases) in order to migrate database for replacement &lt;b&gt;&lt;i&gt;without restarting or changing the application code&lt;/i&gt;&lt;/b&gt;. When the Sharding platform comes to a stop, it is obvious that an application server will not be able to access the database.  For this reason, the Sharding platform should provide&amp;nbsp;&lt;b&gt;&lt;i&gt;redundancy&lt;/i&gt;&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;For monitoring, the Sharding platform should be able to provide a number of requests and error information according to &lt;b&gt;Shard keys&lt;/b&gt; (a standard to determine which data is stored in which database).&lt;/p&gt;
&lt;h2&gt;Comparison between Spock Proxy and CUBRID SHARD&lt;/h2&gt;
&lt;p&gt;The key function of the Sharding platform is the CRUD operation (CREATE, READ, UPDATE, DELETE) which chooses one database among many according to &apos;&lt;b&gt;&lt;i&gt;a standard set by a developer&lt;/i&gt;&lt;/b&gt;&apos;, in other words the &lt;b&gt;Sharding strategy&lt;/b&gt;.   We will compare &lt;b&gt;Spock Proxy&lt;/b&gt;, a typical Sharding platform of MySQL, with the &lt;b&gt;CUBRID SHARD&lt;/b&gt; platform developed by &lt;a target=&quot;_self&quot; href=&quot;/blog/tags/NHN/&quot;&gt;NHN&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Spock Proxy&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;Spock Proxy&lt;/b&gt; is a Sharding platform designed based on MySQL Proxy. In MySQL Proxy, you can execute the Lau scrip code, which is written by a developer before and after performing SQL.  The primary purpose of using MySQL Proxy is to analyze and modify SQL. To use Spock Proxy, you need to create a MySQL database to manage the information about shards and how the data should be distributed.  The row is a rule for Sharding.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/507/323/specifying-sharding-rules-in-spock-proxy.png&quot; alt=&quot;Figure 1: Specifying Sharding rules in Spock Proxy.&quot; title=&quot;Figure 1: Specifying Sharding rules in Spock Proxy.&quot; class=&quot;iePngFix&quot; width=&quot;477&quot; height=&quot;219&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Arial; font-size: 12px;&quot;&gt;&lt;strong&gt;Figure 1: Specifying Sharding rules in Spock Proxy.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;CUBRID SHARD&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;CUBRID SHARD&lt;/b&gt; is the Sharding platform for CUBRID. The uniqueness of CUBRID SHARD is that it can also be used with MySQL as well as Oracle. It is set to be launched in the first half of 2012, and is planned to be used for processing the meta information database system of &lt;a style=&quot;font-weight: bold;&quot; target=&quot;_self&quot; href=&quot;http://ndrive.naver.com/index.nhn&quot;&gt;NDrive&lt;/a&gt;&amp;nbsp;service, the cloud storage system developed by NHN.&lt;/p&gt;
&lt;p&gt;The following table shows a summary of a comparison between Spock Proxy and CUBRID SHARD.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Table 1 Comparison between Spock Proxy and CUBRID SHARD&lt;/strong&gt;&lt;/p&gt;
&lt;table style=&quot;margin: 0 auto;&quot;&gt;
&lt;thead&gt; 
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;Spock Proxy&lt;/td&gt;
&lt;td&gt;CUBRID SHARD&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sharding rule storage&lt;/td&gt;
&lt;td&gt;DBMS Table&lt;/td&gt;
&lt;td&gt;Configuration file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How to create Shard keys&lt;/td&gt;
&lt;td&gt;Modulo&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Modulo&lt;/li&gt;
&lt;li&gt;Developer&apos;s own sharding strategy provided in a library&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How to find a Shard key&lt;/td&gt;
&lt;td&gt;SQL parsing&lt;/td&gt;
&lt;td&gt;Using HINT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strength&lt;/td&gt;
&lt;td&gt;No need to change SQL&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Supports CURBID, MySQL, and Oracle&lt;/li&gt;
&lt;li&gt;Higher performance&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weakness&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;Lower performance due to extra SQL parsing&lt;/li&gt;
&lt;li&gt;Supports MySQL only&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td&gt;Requires the change to SQL queries to insert sharding HINT&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;b&gt;Spock Proxy&lt;/b&gt; stores Sharding rules in the table in MySQL &lt;b&gt;universal_db&lt;/b&gt;&amp;nbsp;database. The SQL received from an application server is parsed and checked whether the query has &lt;b&gt;shard keys&lt;/b&gt;.  If shard keys are provided, the MySQL instance will be identified according to the standard recorded in &lt;b&gt;universal_db&lt;/b&gt;, then SQL will be relayed to that MySQL instance.&lt;/p&gt;
&lt;p&gt;When using this method, you do not need to describe information related to shard keys in SQL, unlike in CUBRID SHARD.  Therefore, if you did not use Sharding before for your coding, but recently had to use due to the data increase, you may use Spock Proxy which will work without requiring you to change the SQL in your application.  Note that this is limited to cases where there is no need to change the schema for Sharding, or when Sharding can be applied without changing the SQL that you use.  However, the method used to find the Shard after parsing SQL, as used by Spock Proxy, has weaknesses in terms of performance.  It could lead to unnecessary work, as SQL should be parsed twice: once by Spock Proxy to determine the MySQL instance, then by MySQL itself.&lt;/p&gt;
&lt;p&gt;In CUBRID SHARD, &lt;strong&gt;SQL&amp;nbsp;&lt;/strong&gt;&lt;b&gt;HINT&lt;/b&gt; is used which allows to avoid parsing SQL twice. Suppose there is a table as follows:&lt;/p&gt;
&lt;table style=&quot;margin: 0 auto;&quot;&gt;
&lt;thead&gt; 
&lt;tr&gt;
&lt;td colspan=&quot;3&quot;&gt;student&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;student_no&lt;/td&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;age&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;To use the &lt;b&gt;student_no&lt;/b&gt; column data as a &lt;i&gt;shard key&lt;/i&gt;, an application server sends the following prepared SQL to  CUBRID SHARD.&lt;/p&gt;
&lt;pre class=&quot;brush:sql;gutter:false&quot;  title=&quot;&quot;&gt;SELECT student_no, name, age FROM student WHERE student_no = /*+ SHARD_KEY */ ?&lt;/pre&gt;
&lt;p&gt;CUBRID SHARD checks if a HINT displays &lt;span style=&quot;font-family: monospace;&quot;&gt;/*+ SHARD_KEY */&lt;/span&gt; in SQL, in which case the column data with the corresponding HINT will be used as a &lt;b&gt;Shard key&lt;/b&gt;. It then reads the &lt;b&gt;student_no&lt;/b&gt; value, which follows the hint, and identifies RDBMS based on the configuration file and transmits the corresponding query. As such, the benefit of using HINT is that you can improve processing efficiency by avoiding parsing SQL twice, and react to various RDBMS without violating the database location abstract.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CUBRID SHARDING provides various HINTs, in addition to &lt;span style=&quot;font-family: monospace;&quot;&gt;/*+ SHARD_KEY */&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Typically, there is  &lt;span style=&quot;font-family: monospace;&quot;&gt;/*+ SHARD_ID(&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;font-family: monospace;&quot;&gt;__id__&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;font-family: monospace;&quot;&gt;) */&lt;/span&gt;, a HINT that allows you to find a special shard.&lt;/li&gt;
&lt;li&gt;The&amp;nbsp;&lt;span style=&quot;font-family: monospace;&quot;&gt;/*+ SHARD_VAL(&lt;/span&gt;&lt;em&gt;&lt;span style=&quot;font-family: monospace;&quot;&gt;__shard_key_val__&lt;/span&gt;&lt;/em&gt;&lt;span style=&quot;font-family: monospace;&quot;&gt;) */&amp;nbsp;&lt;/span&gt;HINT can also play a role in finding a special shard for tables which have no shard keys. While this HINT is the same in that it searches for tables that have no specific shard keys, it configures a value for shard key column directly without choosing a shard, and selects the shard according to the internal rules of the middleware.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unlike Spock Proxy, where Sharding rules are inserted into a database table,&amp;nbsp;in CUBRID SHARD&amp;nbsp;Sharding rules are specified in the configuration file. If there are three access addresses for actual RDBMS storage, you should specify DB addresses to CUBRID SHARD as follows.&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;0     shardDB     shardNODE1:3306
1     shardDB     shardNODE2:3306
2     shardDB     shardNODE3:3306
3     shardDB     shardNODE4:3306&lt;/pre&gt;
&lt;p&gt;If you want to use the &lt;b&gt;Modulo&lt;/b&gt; method, write the corresponding value in the configuration file as below.&lt;/p&gt;
&lt;pre class=&quot;brush:plain;gutter:false&quot;  title=&quot;&quot;&gt;SHARD_KEY_MODULAR = 256&lt;/pre&gt;
&lt;p&gt;In addition, specify &lt;span style=&quot;font-family: monospace;&quot;&gt;[MIN..MAX]&lt;/span&gt; according to the value generated from &lt;span style=&quot;font-family: monospace;&quot;&gt;SHARD_KEY_MODULAR&lt;/span&gt;, and describe which shard to send the corresponding query to.&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;#min max shard_id
0         63       0
64       127     1
128     191     2
192     255     3&lt;/pre&gt;
&lt;p&gt;If you need a more subtle method than &lt;b&gt;Modulo&lt;/b&gt;, you can create program code of your own that calculates the Shard ID for Shard keys.&lt;/p&gt;
&lt;pre class=&quot;brush:plain&quot;  title=&quot;&quot;&gt;SHARD_KEY_LIBRARY_NAME = libshardkeyid.so
SHARD_FUNCTION_NAME = user_get_shard_key&lt;/pre&gt;
&lt;p&gt;As shown in the above example, you can register your own&amp;nbsp;library which will&amp;nbsp;calculate the&amp;nbsp;Shard ID&amp;nbsp;logic.&lt;/p&gt;
&lt;p&gt;The common weakness of both Spock Proxy and CUBRID SHARD is that they both require additional network IO time for each additional hop&amp;nbsp;because they are implemented as a middle tier.&lt;/p&gt;
&lt;p&gt;The following figure displays a general process of internal execution in CUBRID SHARD, which is performed when a developer executes a query. When a developer executes a query, the query is analyzed by the DB shard middleware, which determines to which shard it will be sent.  Then the query is transmitted to the selected shard, and finally the middleware delivers the response to the client.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/507/323/cubrid-shard-process.png&quot; alt=&quot;Figure 2: CUBRID SHARD process.&quot; title=&quot;Figure 2: CUBRID SHARD process.&quot; class=&quot;iePngFix&quot; width=&quot;648&quot; height=&quot;510&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Arial; font-size: 12px;&quot;&gt;&lt;strong&gt;Figure 2: CUBRID SHARD process.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Gizzard&lt;/h2&gt;
&lt;p&gt;Gizzard is a Sharding platform developed by &lt;a target=&quot;_self&quot; href=&quot;/blog/tags/Twitter/&quot;&gt;Twitter&lt;/a&gt;. It is also a middle tier just like Spock Proxy and CUBRID SHARD. However, its usage and architecture are quite different from Spock Proxy or CUBRID SHARD.&lt;/p&gt;
&lt;p&gt;The following figure shows how the data can be shared between several databases deploying two units of Gizzard.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/507/323/gizzard-deployment-diagram.png&quot; alt=&quot;gizzard-deployment-diagram.png&quot; title=&quot;gizzard-deployment-diagram.png&quot; class=&quot;iePngFix&quot; width=&quot;390&quot; height=&quot;450&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Arial; font-size: 12px;&quot;&gt;&lt;strong&gt;Figure 3: Gizzard deployment diagram.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this case, the interface being used by an application server is &lt;b&gt;Thrift&lt;/b&gt;, an RPC protocol, not JDBC. Therefore, it is similar to&amp;nbsp;&lt;b&gt;DBGW (CUBRID SHARD)&amp;nbsp;&lt;/b&gt;platform&amp;nbsp;developed by NHN. When the schema of a storage changes, Gizzard may also need modifications. While it can be a constraint, it could also open up access not only to RDBMS, but also to various other databases (e.g. Lucene).&lt;/p&gt;
&lt;p&gt;Gizzard is written based on Scala, and you can expand its functions by adding Scala codes as needed. Instead of viewing it as a complete product, we recommend that you download the source and modify it to suit your needs.&lt;/p&gt;
&lt;p&gt;The biggest advantage of Gizzard is that you can perform hotspot response and database migration in the middle tier platform level.  For example, Gizzard provides the direct replication feature, as shown in the following figure.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/507/323/replication-feature-of-gizzard.png&quot; alt=&quot;Figure 4: The replication feature of Gizzard.&quot; title=&quot;Figure 4: The replication feature of Gizzard.&quot; class=&quot;iePngFix&quot; width=&quot;365&quot; height=&quot;298&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Arial; font-size: 12px;&quot;&gt;&lt;strong&gt;Figure 4: The replication feature of Gizzard.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Spock Proxy or  CUBRID SHARD do not offer this feature, as they do not need it.  CUBRID, MySQL, and Oracle have their own replication feature, thus they do not need to offer the feature from the middle tier.&lt;/p&gt;
&lt;p&gt;The replication feature provided by Gizzard is very simple - send each request to several replicas -  but cannot handle variety of requests that may occur while running the replication feature.  However, it can be useful when using a database without the replication feature.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/507/323/migration-feature-of-gizzard.png&quot; alt=&quot;Figure 5: The migration feature of Gizzard.&quot; title=&quot;Figure 5: The migration feature of Gizzard.&quot; class=&quot;iePngFix&quot; width=&quot;365&quot; height=&quot;396&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Arial; font-size: 12px;&quot;&gt;&lt;strong&gt;Figure 5: The migration feature of Gizzard.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As shown in the figure above, it offers the replication feature which does not require a service halt.  When migrating a certain database, the feature replicates the details of a database storage before replication configuration, after allowing the new data to be written in two locations by configuring the replication.  This approach, of course, cannot be used on RDBMS due to consistency issue.&lt;/p&gt;
&lt;h2&gt;Limitations of Sharding&lt;/h2&gt;
&lt;p&gt;Sharding, on the other hand, also has its own limitations. Typical constraints of Sharding are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It cannot perform JOIN operations for two or more Shardings. &lt;/li&gt;
&lt;li&gt;auto_increment (serial) values can vary depending on Sharding. &lt;/li&gt;
&lt;li&gt;last_insert_id() value is no more valid. &lt;/li&gt;
&lt;li&gt;&lt;b&gt;shard key&lt;/b&gt; column value must not be updated; requires delete, then insert. &lt;/li&gt;
&lt;li&gt;does not allow to access two or more Shards from one transaction. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When using Sharding, therefore, it is important that you perform right data modeling and schema design to prevent the above constraint issues.&lt;/p&gt;
&lt;p&gt;To learn more about Sharding and other features of CUBRID I suggest you to see the Slideshare presentation at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a target=&quot;_self&quot; href=&quot;http://www.slideshare.net/cubrid/growing-in-the-wild-the-story-by-cubrid-database-developers&quot;&gt;http://www.slideshare.net/cubrid/growing-in-the-wild-the-story-by-cubrid-database-developers&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/cubrid-life/database-sharding-the-right-way-easy-reliable-open-source/&quot;&gt;http://www.cubrid.org/blog/cubrid-life/database-sharding-the-right-way-easy-reliable-open-source/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By&amp;nbsp;Jeon Won Hee, Senior Software Engineer at CUBRID&amp;nbsp;DBMS Development Lab,&amp;nbsp;NHN Corporation.&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="CUBRID Internals"/>
            <category term="Sharding"/>
            <category term="CUBRID SHARD"/>
            <category term="Spock Proxy"/>
            <category term="MySQL"/>
            <category term="Gizzard"/>
            
   </entry>
   <entry>
      <title>Basic Operations of CUBRID Processes</title>
      <id>http://www.cubrid.org/blog/411987</id>
      <published>2012-08-20T19:20:30-07:00</published>
      <updated>2013-03-18T23:46:49-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/411987"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/411987#comment"/>
      <author>
         <name>Park Kieun</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&lt;i&gt;This article is a part of &quot;&lt;a href=&quot;/blog/tags/CUBRID%20Internals/&quot;&gt;CUBRID Internals&lt;/a&gt;&quot; series.&lt;/i&gt; In the &lt;a target=&quot;_self&quot; href=&quot;/blog/cubrid-life/cubrid-database-processes/&quot;&gt;previous article&lt;/a&gt;&amp;nbsp;I have explained about CUBRID Processes and where to configure them. In this article I would like to dive into how those processes run. If you have not read the previous article, I recommend you to do so before reading further.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Figure 1&lt;/b&gt; below illustrates the basic operation flow in CUBRID.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, when a user enters the &lt;code&gt;cubrid service start&lt;/code&gt; command,&amp;nbsp;CUBRID gets started.&lt;/li&gt;
&lt;li&gt;Then, the &lt;b&gt;cub_master&lt;/b&gt;&amp;nbsp;and &lt;b&gt;cub_broker&lt;/b&gt; processes are started.&amp;nbsp;At this time, a number of&amp;nbsp;&lt;b&gt;cub_cas&lt;/b&gt; processes will be started which corresponds to the&amp;nbsp;value of &lt;code&gt;MIN_NUM_APPL_SERVER&lt;/code&gt; parameter in the&amp;nbsp;&lt;b&gt;&lt;span style=&quot;font-family: monospace;&quot;&gt;cubrid_broker.conf&lt;/span&gt;&lt;/b&gt;&amp;nbsp;file.&lt;/li&gt;
&lt;li&gt;Then, a user enters the &lt;code&gt;cubrid server start demodb&lt;/code&gt; command which creates the&amp;nbsp;&lt;b&gt;cub_server&lt;/b&gt; process that mounts the &lt;b&gt;demodb&lt;/b&gt; database volume. As described in &lt;a target=&quot;_self&quot; href=&quot;/blog/cubrid-life/cubrid-database-processes/&quot;&gt;CUBRID Processes&lt;/a&gt;, the &lt;b&gt;cub_master&lt;/b&gt; process connects the &lt;b&gt;cub_server&lt;/b&gt; process with the &lt;b&gt;cub_cas&lt;/b&gt; process, which sends the requests, or the &lt;b&gt;csql&lt;/b&gt; program.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/987/411/cubrid_operation_procedure.png&quot; alt=&quot;cubrid_operation_procedure.png&quot; title=&quot;cubrid_operation_procedure.png&quot; class=&quot;iePngFix&quot; width=&quot;700&quot; height=&quot;818&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1: CUBRID Operation Procedure.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;As shown in &lt;b&gt;Figure 1&lt;/b&gt;, if a&amp;nbsp;JDBC application is connected to the server process which mounts the database volume file, the SQL statement can be executed in CUBRID. Two most popular methods to use CUBRID is to execute SQL manually using the command line&amp;nbsp;&lt;a target=&quot;_self&quot; href=&quot;/how_to_use_csql_utilities&quot;&gt;CSQL Interpreter&lt;/a&gt; program or to write a program which uses various APIs like JDBC, PHP, Node.js, etc.&lt;/p&gt;
&lt;blockquote class=&quot;q4&quot;&gt;
&lt;p&gt;&lt;b&gt;Note:&lt;br /&gt;&lt;/b&gt;As we have discussed, the JDBC program connects to the database server through a broker while CSQL Interpreter directly connects to the database server bypassing the broker. This is an important difference between APIs and CSQL.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a target=&quot;_self&quot; href=&quot;/wiki_tools/entry/cubrid-manager&quot;&gt;CUBRID Manager&lt;/a&gt;&amp;nbsp;database administration tool is developed on top of the JDBC driver. The SQL statement executed in CUBRID Manager are passed to the server through the JDBC API. Other database management functions that are available in CUBRID Manager (database creating/deleting, etc.) are executed through a &lt;b&gt;management utility&lt;/b&gt; called &lt;i&gt;CUBRID Manager Server&lt;/i&gt; which runs as a&amp;nbsp;separate manager server daemon&amp;nbsp;outside of the database.&lt;/p&gt;
&lt;p&gt;Now, let&apos;s take a look at CUBRID Manager as an example to see how an SQL statement is executed in CUBRID. Refer to &lt;b&gt;Figure 2&lt;/b&gt;&amp;nbsp;for this example.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The SQL statement entered in the query editor of the CUBRID Manager (for example, &lt;code&gt;SELECT * FROM olympic WHERE host_year &amp;gt; 1988 LIMIT 4;&lt;/code&gt;) is sent to &lt;a target=&quot;_self&quot; href=&quot;/wiki_apis/entry/cubrid-jdbc-driver&quot;&gt;CUBRID JDBC driver&lt;/a&gt;. This assumes that a database has already been selected in CUBRID Manager before executing this SQL, and&amp;nbsp;the JDBC connection has been established.&lt;/li&gt;
&lt;li&gt;In the JDBC connection process, the connection is made to the port of the host specified in the JDBC connection information (&lt;a target=&quot;_self&quot; href=&quot;/questions/236982&quot;&gt;JDBC Connection URL&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;The &lt;b&gt;cub_broker&lt;/b&gt;&amp;nbsp;process receives the connection and allocates a &lt;b&gt;cub_cas&lt;/b&gt; process for the session to the connection.&lt;/li&gt;
&lt;li&gt;Then, it sends the socket connection to the &lt;b&gt;cub_cas&lt;/b&gt; process so the connection between the JDBC driver and the &lt;b&gt;cub_cas&lt;/b&gt; process is established.&lt;/li&gt;
&lt;li&gt; Back to the SQL statement execution, the JDBC driver included in the CUBRID Manager sends the SQL statement of the query editor to the connected broker, the &lt;b&gt;cub_cas&lt;/b&gt; process.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The broker sequentially calls &lt;code&gt;db_open_buffer()&lt;/code&gt;, &lt;code&gt;db_compile_statement()&lt;/code&gt; and &lt;code&gt;db_execute_statement()&lt;/code&gt; among C APIs provided by the client library, to execute the received SQL statement. The &lt;code&gt;db_open_buffer()&lt;/code&gt; function parses the SQL statement, the &lt;code&gt;db_compile_statement()&lt;/code&gt; function compiles the execution plan, and the &lt;code&gt;db_execute_statement()&lt;/code&gt; function executes SQL by sending &lt;a target=&quot;_self&quot; href=&quot;/wiki_tutorials/entry/CUBRID_Query_Processing#XASL_Generation&quot;&gt;XASL&lt;/a&gt; (eXtended Access Spec Language) to the server.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/modules/editor/styles/default/files/attach/images/220547/987/411/sql_statement_execution_procedure.png&quot; alt=&quot;sql_statement_execution_procedure.png&quot; title=&quot;sql_statement_execution_procedure.png&quot; class=&quot;iePngFix&quot; width=&quot;684&quot; height=&quot;756&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 2: SQL Statement Execution Procedure in CUBRID.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;As shown in &lt;b&gt;Figure 2&lt;/b&gt;, the &lt;code&gt;qmgr_execute_query()&lt;/code&gt; function is executed in the &lt;b&gt;cub_cas&lt;/b&gt;, and the &lt;code&gt;xqmgr_execute_query()&lt;/code&gt; function is executed in the &lt;b&gt;cub_server&lt;/b&gt; process. The &lt;code&gt;qmgr_execute_query()&lt;/code&gt; function in the client &lt;b&gt;&lt;i&gt;is &lt;/i&gt;&lt;/b&gt;the &lt;code&gt;xqmgr_execute_query()&lt;/code&gt; function in the server. As shown above, CUBRID implements a communication interface of Remote Procedure Call (RPC) between a client and a server. In the server, the &lt;code&gt;qexec_execute_query()&lt;/code&gt;&amp;nbsp;and &lt;code&gt;qexec_execute_mainblock()&lt;/code&gt; functions of the query processing module are used to execute XASL.&lt;/p&gt;
&lt;p&gt;If you are interesting how queries are processed in CUBRID, I recommend you to read &lt;a target=&quot;_self&quot; href=&quot;/wiki_tutorials/entry/CUBRID_Query_Processing&quot;&gt;CUBRID Query Processing&lt;/a&gt;&amp;nbsp;which provides the detailed step by step explanation using real examples.&lt;/p&gt;
&lt;p&gt;By &lt;a target=&quot;_self&quot; href=&quot;http://www.linkedin.com/pub/kieun-park/39/a78/487&quot;&gt;Park Kieun&lt;/a&gt;, Senior Software Engineer and Architect at Service Platform Development Center &amp;amp; IT Service Center, NHN Corporation.&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="CUBRID Internals"/>
            <category term="CUBRID Processes"/>
            <category term="architecture"/>
            <category term="CUBRID Query Processing"/>
            <category term="CUBRID Service"/>
            
   </entry>
   <entry>
      <title>Announcing CUBRID 9.1 stable release with big improvements</title>
      <id>http://www.cubrid.org/blog/612686</id>
      <published>2013-03-15T03:51:03-07:00</published>
      <updated>2013-03-18T01:29:35-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/612686"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/612686#comment"/>
      <author>
         <name>Esen Sagynov</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&lt;img src=&quot;/files/attach/images/220547/686/612/cubrid_9_1_banner_blog.jpg&quot; alt=&quot;cubrid_9_1_banner_blog.jpg&quot; width=&quot;648&quot; height=&quot;297&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We released &lt;a href=&quot;/blog/news/announcing-cubrid-9-0-with-3x-performance-increase-and-sharding-support/&quot;&gt;CUBRID 9.0 &lt;i&gt;beta&lt;/i&gt;&lt;/a&gt; version in October last year. Since then we have been working hard on stabilizing the beta features, fixing bugs, and improving the overall engine performance. Today I am excited to announce the immediate availability of the CUBRID 9.1 stable release. You can download CUBRID Database Server from&amp;nbsp;&lt;a href=&quot;/?mid=downloads&amp;amp;item=cubrid&amp;amp;os=detect&amp;amp;cubrid=9.1.0&quot;&gt;http://www.cubrid.org/?mid=downloads&amp;amp;item=cubrid&amp;amp;os=detect&amp;amp;cubrid=9.1.0&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I would also like to announce that we will give a talk about &lt;a href=&quot;/blog/cubrid-life/cubrid-shard-talk-at-2013-percona-mysql-conference-dont-miss/&quot;&gt;CUBRID Database Sharding at Percona MySQL Conference&lt;/a&gt; on April 24, 2013, in Santa Clara, CA. Join us there to meet CUBRID Engineers and get the first-hand insight into the new CUBRID 9.1.&lt;/p&gt;
&lt;p&gt;Below I will provide an overview of the latest changes and improvements in CUBRID 9.1.&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;CUBRID 9.1 is an upgraded and stabilized version of CUBRID 9.0 Beta. To learn more about the biggest features introduced in 9.x family, refer to &lt;a href=&quot;/blog/news/announcing-cubrid-9-0-with-3x-performance-increase-and-sharding-support/&quot;&gt;9.0 official announcement&lt;/a&gt;. Issues found in the 9.0 Beta version have been fixed and stabilized in&amp;nbsp;this new&amp;nbsp;9.1 stable release. With a variety of query-related functionalities, CUBRID 9.1 offers improved query processing performance as well as improved query optimization. In addition, its multi-language related functionalities have been further improved. This new 9.1 release is accompanied by new &lt;a href=&quot;/?mid=downloads&amp;amp;item=any&amp;amp;os=detect&amp;amp;cubrid=9.1.0&quot;&gt;CUBRID Tools and Drivers&lt;/a&gt;&amp;nbsp;releases.&lt;/p&gt;
&lt;h2&gt;Backward Compatibility&lt;/h2&gt;
&lt;h3&gt;Database compatibility&lt;/h3&gt;
&lt;p&gt;As a database volume of CUBRID 9.1 is not compatible with the database of CUBRID 9.0 Beta, users of CUBRID 9.0 Beta or previous versions should&amp;nbsp;migrate their database. We have created a migration instructions which you can find in &lt;a href=&quot;/manual/91/en/upgrade.html&quot;&gt;Upgrade&lt;/a&gt;&amp;nbsp;section&amp;nbsp;of the Release Notes.&lt;/p&gt;
&lt;h3&gt;Driver compatibility&lt;/h3&gt;
&lt;p&gt;The JDBC and CCI driver of CUBRID 9.1 are compatible with CUBRID 9.0 Beta and CUBRID 2008 R4.x version. Some features that are fixed and improved for 9.1 are not supported when 9.1 drivers connect to the previous versions.&lt;/p&gt;
&lt;h2&gt;Major enhancements&lt;/h2&gt;
&lt;h3&gt;New SQL functions and index hints&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;New SQL analytics functions like &lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/function/analysis_fn.html?highlight=ntile#NTILE&quot;&gt;NTILE&lt;/a&gt;&lt;/code&gt;, &lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/function/analysis_fn.html?highlight=lead#LEAD&quot;&gt;LEAD&lt;/a&gt;&lt;/code&gt; and &lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/function/analysis_fn.html?highlight=lag#LAG&quot;&gt;LAG&lt;/a&gt;&lt;/code&gt;&amp;nbsp;have been introduced in CUBRID 9.1.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/function/numeric_fn.html?highlight=width_bucket#WIDTH_BUCKET&quot;&gt;WIDTH_BUCKET&lt;/a&gt;&lt;/code&gt; new SQL numeric function is also&amp;nbsp;introduced.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/function/numeric_fn.html?highlight=trunc#TRUNC&quot;&gt;TRUNC&lt;/a&gt;&lt;/code&gt; and &lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/function/numeric_fn.html?highlight=trunc#round&quot;&gt;ROUND&lt;/a&gt;&lt;/code&gt; functions now also accept the date types.&lt;/li&gt;
&lt;li&gt;New SQL Hints:          
&lt;ul&gt;
&lt;li&gt;Support a &lt;a href=&quot;/manual/91/en/release_note/r91.html#support-new-index-hint-clause-cubridsus-6675&quot;&gt;new index hint clause&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/manual/91/en/release_note/r91.html#sql-hints-for-update-join-and-delete-join-statement-cubridsus-9491&quot;&gt;SQL hints for Multi &lt;code&gt;UPDATE&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt;&lt;/a&gt; statement.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/manual/91/en/release_note/r91.html#index-hints-for-merge-statement-cubridsus-10134&quot;&gt;SQL hints for &lt;code&gt;MERGE&lt;/code&gt;&lt;/a&gt; statement.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Performance improvements and optimizations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The performance of data replication in HA environment has been significantly improved in CUBRID 9.1.&lt;br /&gt;&lt;img src=&quot;/files/attach/images/220547/686/612/data_replication_performance_comparison.png&quot; alt=&quot;data_replication_performance_comparison.png&quot; width=&quot;412&quot; height=&quot;106&quot; /&gt;&lt;/li&gt;
&lt;li&gt;Improved multi-key range optimization.&lt;/li&gt;
&lt;li&gt;Enhanced optimization of &lt;code&gt;ORDER BY&lt;/code&gt; and &lt;code&gt;GROUP BY&lt;/code&gt; clause.&lt;/li&gt;
&lt;li&gt;Improved analytic function performance.&lt;/li&gt;
&lt;li&gt;Improved performance of &lt;code&gt;INSERT ON DUPLICATE KEY UPDATE&lt;/code&gt; and &lt;code&gt;REPLACE&lt;/code&gt; statement.&lt;/li&gt;
&lt;li&gt;Improved search and delete performance for non-unique indexes with many duplicate keys.&lt;/li&gt;
&lt;li&gt;Improved delete performance when insert and delete operations are repeated.&lt;/li&gt;
&lt;li&gt;The overall performance of &lt;code&gt;SELECT&lt;/code&gt; operations has been improved by nearly 20%.&lt;br /&gt;&lt;img src=&quot;/files/attach/images/220547/686/612/select_operation_result_of_ycsb_benchmark.png&quot; alt=&quot;select_operation_result_of_ycsb_benchmark.png&quot; width=&quot;456&quot; height=&quot;270&quot; /&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Based on the results obtained from the basic performance test, we have found that the performance of &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;, and &lt;code&gt;UPDATE&lt;/code&gt; operations are almost same as that of 9.0 Beta.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Multi-language support&lt;/h3&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;In CUBRID 9.1 we now support &lt;a href=&quot;/manual/91/en/release_note/r91.html#change-collation-coercibility-level-cubridsus-10057&quot;&gt;collation for tables&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/query/show.html?highlight=show%20collation#show-collation&quot;&gt;SHOW COLLATION&lt;/a&gt;&lt;/code&gt; statement and new &lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/function/information_fn.html?highlight=charset#CHARSET&quot;&gt;CHARSET&lt;/a&gt;&lt;/code&gt;, &lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/function/information_fn.html?highlight=collation#COLLATION&quot;&gt;COLLATION&lt;/a&gt;&lt;/code&gt;, and &lt;code&gt;&lt;a href=&quot;/manual/91/en/sql/function/information_fn.html?highlight=coercibility#COERCIBILITY&quot;&gt;COERCIBILITY&lt;/a&gt;&lt;/code&gt;&amp;nbsp;functions&amp;nbsp;are now supported.&lt;/li&gt;
&lt;li&gt;Support collation with &lt;a href=&quot;/manual/91/en/release_note/r91.html#support-collation-with-expansion-sort-by-backward-accents-cubridsus-9407&quot;&gt;expansion which sorts French with backward accent order&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Improved and fixed restrictions and issues of 9.0 Beta version.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;CUBRID SHARD&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;We have added&amp;nbsp;&lt;code&gt;&lt;a href=&quot;/manual/91/en/shard.html?highlight=cubrid%20shard%20getid#checking-cubrid-shard-id&quot;&gt;cubrid shard getid&lt;/a&gt;&lt;/code&gt; command to verify the shard ID of the shard key.&lt;/li&gt;
&lt;li&gt;CUBRID SHARD is now available on Windows as well.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Administration utility&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;/manual/91/en/ha.html#cubrid-applyinfo&quot;&gt;cubrid applyinfo&lt;/a&gt;&lt;/code&gt; utility now also shows information about the replication delay.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&lt;a href=&quot;/manual/91/en/admin/admin_utils.html?highlight=killtran#killing-transactions&quot;&gt;cubrid killtran&lt;/a&gt;&lt;/code&gt; utility now has the ability to show the query execution information of each transaction as well as the&amp;nbsp;ability to remove transactions which executes a designated SQL.&lt;/li&gt;
&lt;li&gt;When a query timeout occurs,&amp;nbsp;added a functionality to log the query execution information to the server error log and the CAS log files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Behavioral Changes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CUBRID_LANG&lt;/code&gt; environment variable is no longer used.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CUBRID_CHARSET&lt;/code&gt; environment variable which sets the database charset instead of &lt;code&gt;CUBRID_LANG&lt;/code&gt; and the &lt;code&gt;CUBRID_MSG_LANG&lt;/code&gt; environment variable which sets the charset for utility and error messages.&lt;/li&gt;
&lt;li&gt;Change array execution functions such as &lt;code&gt;cci_execute_array&lt;/code&gt;, &lt;code&gt;cci_execute_batch&lt;/code&gt; function and &lt;code&gt;Statement.executeBatch&lt;/code&gt; and &lt;code&gt;PreparedStatement.executeBatch&lt;/code&gt; method of JDBC to commit whenever it executes an individual query under auto commit mode, while the previous versions commit once for entire execution.&lt;/li&gt;
&lt;li&gt;Change the behavior of &lt;code&gt;cci_execute_array&lt;/code&gt;, &lt;code&gt;cci_execute_batch&lt;/code&gt; and &lt;code&gt;cci_execute_result&lt;/code&gt; function when an error occurs while they are executing multiple statements. These functions now continue to execute the entire given queries while the previous versions stop execution and return an error. Users can access the results and identify the errors with &lt;code&gt;CCI_QUERY_RESULT_*&lt;/code&gt; macros.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OFF&lt;/code&gt; is no longer supported for &lt;code&gt;KEEP_CONNECTION&lt;/code&gt; broker parameter.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SELECT_AUTO_COMMIT&lt;/code&gt; broker parameter is no longer supported.&lt;/li&gt;
&lt;li&gt;Change the allowed value range of a broker parameter &lt;code&gt;APPL_SERVER_MAX_SIZE_HARD_LIMIT&lt;/code&gt; to &lt;code&gt;1 - 2,097,151&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Change the default value of a broker parameter &lt;code&gt;SQL_LOG_MAX_SIZE&lt;/code&gt; from &lt;code&gt;100 MB to 10 MB&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Change the behavior of the &lt;code&gt;call_stack_dump_activation_list&lt;/code&gt; parameter.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Numerous Improvements and Bug Fixes&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Fix many critical issues of the previous versions.&lt;/li&gt;
&lt;li&gt;Improve of fix many issues of stability, SQL, partitioning, HA, Sharding, utilities, and drivers.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;/ul&gt;
&lt;p&gt;For more details on changes, see the Release Notes in &lt;a href=&quot;/manual/91/en/release_note/r91.html&quot;&gt;English&lt;/a&gt; or &lt;a href=&quot;/manual/91/ko/release_note/r91.html&quot;&gt;Korean&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So far CUBRID 9.1 is our biggest release which we would like you to try. In fact we have released new improved drivers for &lt;a href=&quot;/wiki_apis/entry/cubrid-node-js-driver&quot;&gt;Node.js&lt;/a&gt;, &lt;a href=&quot;/wiki_apis/entry/cubrid-php-driver&quot;&gt;PHP&lt;/a&gt;, &lt;a href=&quot;/wiki_apis/entry/cubrid-pdo-driver&quot;&gt;PDO&lt;/a&gt;, &lt;a href=&quot;/wiki_apis/entry/cubrid-python-driver&quot;&gt;Python&lt;/a&gt;, &lt;a href=&quot;/wiki_apis/entry/cubrid-perl-driver&quot;&gt;Perl&lt;/a&gt;, &lt;a href=&quot;/wiki_apis/entry/cubrid-jdbc-driver&quot;&gt;JDBC&lt;/a&gt;, &lt;a href=&quot;/wiki_apis/entry/cubrid-odbc-driver&quot;&gt;ODBC&lt;/a&gt;, &lt;a href=&quot;/wiki_apis/entry/cubrid-oledb-driver&quot;&gt;OLEDB&lt;/a&gt;, &lt;a href=&quot;/wiki_apis/entry/cubrid-ado-net-driver&quot;&gt;ADO.NET&lt;/a&gt;, and &lt;a href=&quot;/wiki_apis/entry/cubrid-cci-driver&quot;&gt;C&lt;/a&gt;. So you should definitely try the new, more performant and stable CUBRID 9.1 Database.&lt;/p&gt;
&lt;p&gt;If you have any questions, feel free to leave your comment below.&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="New Release"/>
            <category term="performance"/>
            <category term="Sharding"/>
            <category term="HA"/>
            <category term="multilingual support"/>
            
   </entry>
   <entry>
      <title>CUBRID SHARD talk at 2013 Percona MySQL Conference. Don&apos;t miss!</title>
      <id>http://www.cubrid.org/blog/613198</id>
      <published>2013-03-15T03:42:45-07:00</published>
      <updated>2013-03-15T03:45:02-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/613198"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/613198#comment"/>
      <author>
         <name>Esen Sagynov</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&lt;img style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; height=&quot;239&quot; width=&quot;118&quot; alt=&quot;percona_cubrid_shard_118x239_speaking.png&quot; src=&quot;/files/attach/images/220547/198/613/percona_cubrid_shard_118x239_speaking.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I would like to announce that on April 24, 2013, six weeks from now, we will talk at Percona MySQL Conference &amp;amp; Expo in Santa Clara, CA. The topic of the presentation is &lt;strong&gt;Easy MySQL Database Sharding with CUBRID SHARD&lt;/strong&gt;. The presentation will be @ &lt;b&gt;3:30 PM in Ballroom A&lt;/b&gt;. Come and join us!&lt;/p&gt;
&lt;h2&gt;Abstract&lt;/h2&gt;
&lt;p&gt;If you ask companies who operate mission-critical services, they will tell:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;that a relational database system is still the best choice for mission-critical data;&lt;/li&gt;
&lt;li&gt;that service availability is more important than performance;&lt;/li&gt;
&lt;li&gt;that high performance is good, but predictable performance is the king.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is a fact, and we know it. At NHN we have over 30,000 Web servers that operate over 150 large scale Web and mobile services. At such scale we must know what scales, how to provide high-availability and operate at predictable speed.&lt;/p&gt;
&lt;p&gt;At Percona Live MySQL Conference 2013 I will talk about CUBRID SHARD, a universal database sharding solution for CUBRID, MySQL, and Oracle. CUBRID SHARD can be used with a heterogeneous database backend, i.e. some shards can be stored in CUBRID, some in MySQL or even Oracle. At NHN we deploy various combinations: MySQL only, MySQL + Oracle, MySQL + CUBRID, CUBRID only, and Oracle only. I will explain how DBAs can easily configure it, and how we have implemented this feature.&lt;/p&gt;
&lt;p&gt;CUBRID SHARD allows to store unlimited number of database shards and distribute data based on modulo, DATETIME, or hash/range calculations. The developers can even feed in their own library to calculate the SHARD_ID using some complicated custom algorithm. At the session I will show how easy it is to setup all this. No need for a third-party management tool. With CUBRID SHARD application developers do not need to modify the application logic to provide data sharding. This is DBAs job as all this is handled by the database system automatically.&lt;/p&gt;
&lt;p&gt;CUBRID SHARD is designed to be very efficient. It provides built-in (*) distributed load balancing and (*) connection and statement pooling. At the conference I will present several cases where CUBRID SHARD is deployed as a shard manager and a connection manager, or where it&apos;s used as a way for seamless data migration between different systems.&lt;/p&gt;
&lt;h2&gt;Who should come to the session?&lt;/h2&gt;
&lt;p&gt;If you run a service which spends money on a database solution, on tools you need to shard databases or manage connections, you should come and learn how CUBRID SHARD can provide your applications native scale-out through single database view.&lt;/p&gt;
&lt;p&gt;If you would like to learn more about CUBRID Database Sharding, see our &lt;a href=&quot;http://www.slideshare.net/cubrid/database-sharding-the-right-way-easy-reliable-and-open-source-highload-2012&quot;&gt;Database Sharding the Right Way: Easy, Reliable, and Open source&lt;/a&gt; I have presented at &lt;a href=&quot;/blog/cubrid-life/database-sharding-the-right-way-easy-reliable-open-source/&quot;&gt;2012 HighLoad++ Conference&lt;/a&gt;. More about CUBRID you can find at&amp;nbsp;&lt;a href=&quot;/wiki_tutorials/entry/important-facts-to-know-about-cubrid&quot;&gt;Important Facts to Know about CUBRID&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have questions, feel free to leave your comment below.&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="Sharding"/>
            <category term="conference"/>
            <category term="Percona"/>
            <category term="MySQL"/>
            
   </entry>
   <entry>
      <title>A free CUBRID Cloud Database Service for our dear users</title>
      <id>http://www.cubrid.org/blog/608542</id>
      <published>2013-03-11T00:10:26-07:00</published>
      <updated>2013-03-11T00:10:26-07:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/608542"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/608542#comment"/>
      <author>
         <name>Esen Sagynov</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;Hello reader,&lt;/p&gt;
&lt;p&gt;What do you know about CUBRID Database?&amp;nbsp;Let this be your first introduction to CUBRID.&amp;nbsp;Today I&amp;nbsp;would like to tell a story about what we do at CUBRID in order to improve the experience our users have when they get started with CUBRID Database.&lt;/p&gt;
&lt;p&gt;So far we have published numerous &lt;a href=&quot;/wiki_tutorials/entry/cubrid-installation-instructions&quot;&gt;installation instructions&lt;/a&gt;&amp;nbsp;and short &lt;a href=&quot;/wiki_tutorials/entry/how-to-using-cubrid-tutorials&quot;&gt;HOWTO tutorials&lt;/a&gt; which help our users to quickly get started with installing and configuring CUBRID Database. These include instructions for apt-get and yum package managers. Once their server is up and running, users can continue their learning experience with &lt;a href=&quot;/wiki_tutorials/entry/cubrid-tutorials&quot;&gt;more tutorials&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To improve user experience, couple months ago we have written multiple&amp;nbsp;&lt;a href=&quot;/?mid=wiki_tutorials&amp;amp;act=TS&amp;amp;category=wiki&amp;amp;is_keyword=cookbook&quot;&gt;Vagrant and Chef Cookbook&lt;/a&gt; tutorials which provide easy step by step instructions on how to create a clean virtual machine image for VirtualBox and install CUBRID and any other necessary software on a new Linux operating system in a matter of minutes.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.vagrantup.com&quot;&gt;Vagrant&lt;/a&gt; in combination with Chef cookbooks is a great tool and time saver for developers, especially for testers and those users who would like to just try a new software in a VM without polutting their host machine. You can fire up a single command like &lt;code&gt;vagrant up&lt;/code&gt;, and Vagrant will built up a new VM machine with all the software you need preinstalled and configured for you. How cool is that! In fact, I use Vagrant and Chef on every day basis to reproduce issues users have reported on CUBRID forums, or to quickly start hacking some new features for another project.&lt;/p&gt;
&lt;p&gt;While Vagrant is a great tool for local development, &lt;a href=&quot;http://matschaffer.github.com/knife-solo/&quot;&gt;Knife Solo&lt;/a&gt;&amp;nbsp;is the guy you need for remote &lt;a href=&quot;http://en.wikipedia.org/wiki/Provisioning#Server_provisioning&quot;&gt;server provisioning&lt;/a&gt;. Just like Vagrant, Knife Solo prepares and cooks the Chef cookbooks on a&amp;nbsp;remote server, be it a VM on your local machine or a remote Amazon EC2 server. And we have written a&amp;nbsp;&lt;a href=&quot;/wiki_tutorials/entry/install-cubrid-remotely-with-knife-solo-and-chef-cookbook&quot;&gt;Knife Solo tutorial&lt;/a&gt;&amp;nbsp;which introduces this tool and shows how to install CUBRID Database, its tools and drivers on a remote machine.&lt;/p&gt;
&lt;p&gt;For those users who wish to directly download a virtual machine with a preconfigured CUBRID Database, we have built and uploaded &lt;a href=&quot;/?mid=downloads&amp;amp;item=virtual_machines&amp;amp;vm_tool=any&amp;amp;vm_os=any&amp;amp;cubrid=any&quot;&gt;CentOS and Ubuntu VirtualBox images&lt;/a&gt; with different versions of CUBRID Server.&lt;/p&gt;
&lt;p&gt;To further improve the user experience, today&amp;nbsp;I am immensely happy to announce the &lt;b&gt;CUBRID Cloud Database Service&lt;/b&gt;&amp;nbsp;at&amp;nbsp;&lt;a href=&quot;http://www.cloud.cubrid.org&quot;&gt;http://cloud.cubrid.org&lt;/a&gt;. We have come from installing CUBRID manually on a user machine to installing automatically on a VM or a remote server, to not having to install CUBRID at all. Now you can request a connection information to a remote CUBRID cloud database for free as soon as you need. All you need is a valid email address.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/files/attach/images/220547/542/608/cubrid_cloud_database_service_screenshot.png&quot; alt=&quot;cubrid_cloud_database_service_screenshot.png&quot; width=&quot;702&quot; height=&quot;260&quot; style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1: CUBRID Cloud Database Service front page.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Once requested, you will receive a confirmation email address. You confirm your email, and we will start cooking your very own CUBRID cloud database. In a minute or so you will receive a second email with the database credentials.&amp;nbsp;This will include the remote database host IP address, the port number, your database name, a username, and a password. We will also include a short getting started tutorial for you to take off quickly.&lt;/p&gt;
&lt;p&gt;We have built this CUBRID Cloud Service for educational purpose. We want our users be able to get their hands on a CUBRID database as soon as they need. You can use this cloud database for testing, for learning CUBRID, or for building non-critical demo applications.&lt;/p&gt;
&lt;p&gt;To discuss CUBRID Cloud Service, we have created a dedicated &lt;a href=&quot;/forum/605411&quot;&gt;forum thread&lt;/a&gt;. You are welcome to join us!&amp;nbsp;If you want to chat with our engineers, head to &lt;a href=&quot;http://webchat.freenode.net/?channels=cubrid&quot;&gt;#cubrid&lt;/a&gt; freenode chat room. We will be glad to see you there!&lt;/p&gt;
&lt;p&gt;So, go ahead and &lt;a href=&quot;http://www.cloud.cubrid.org&quot;&gt;creat your first CUBRID cloud database&lt;/a&gt;!&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="CUBRID Cloud Service"/>
            <category term="cloud"/>
            <category term="database"/>
            
   </entry>
   <entry>
      <title>Overview of Bootstrap from Twitter</title>
      <id>http://www.cubrid.org/blog/400843</id>
      <published>2012-07-30T23:10:56-07:00</published>
      <updated>2013-03-06T05:13:47-08:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/400843"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/400843#comment"/>
      <author>
         <name>kyungilpark</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/twitter_bootstrap.jpg&quot; alt=&quot;twitter_bootstrap.jpg&quot; title=&quot;twitter_bootstrap.jpg&quot; width=&quot;593&quot; height=&quot;269&quot; style=&quot;&quot; /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt;&amp;nbsp;Bootstrap 2.1.0 has been released yesterday on August 20, 2012. Check out their &lt;a target=&quot;_self&quot; href=&quot;http://blog.getbootstrap.com/2012/08/20/bootstrap-2-1-0-released/&quot;&gt;official blog&lt;/a&gt;&amp;nbsp;for release notes.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Bootstrap&lt;/b&gt; is a front-end toolkit&amp;nbsp;open sourced&amp;nbsp;by Twitter which provides flexible HTML, CSS, and JavaScript-based design templates, a variety of UI components and interactions for building a beautiful website. In this article I will provide an overview of Bootstrap, describe its characteristics, and will show how to start building websites with it.&lt;/p&gt;
&lt;h2&gt;Bootstrap from Twitter&lt;/h2&gt;
&lt;p&gt;Developing a Web UI looks easy; however, so many developers encounter a number of difficulties when trying to develop it. Different from general UI development which requires a single client environment, Web UI development requires Cross Browsing that satisfies compatibility among a variety of browser environments.&lt;/p&gt;
&lt;p&gt;There are five browsers that are mainly used in PCs - Internet Explorer, Firefox, Chrome, Safari and Opera - and additional work is necessary depending on the version and the operating system. In addition, we need to consider the current mobile environment that has a variety of screen sizes, such as smartphone and tablet PC, and the browsers specialized for each device type.&lt;/p&gt;
&lt;p&gt;These various and complex browser environments make it difficult to process Cross Browsing for the small- and mid-size Web sites. &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt; is the front-end toolkit from Twitter which tries to clear this difficulty and provide a start point that allows developers to quickly and easily implement a flexible web site.&lt;/p&gt;
&lt;p&gt;Bootstrap is an open source front-end toolkit developed by Mark Otto, a Twitter UI designer, and Jacob Thornton, a Twitter developer. As its meaning &quot;&lt;i&gt;to start up a system by turning on the power of a computer or pressing a reset key&lt;/i&gt;,&quot; Bootstrap is a starting point for building websites which provides flexible HTML, CSS and JavaScript-based design templates, variety of frequently-used UI components and interactions.&lt;/p&gt;
&lt;h2&gt;Grid System&lt;/h2&gt;
&lt;p&gt;Grid is a basic element for layout design. Generally, the screen is split by using the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tag and CSS to place elements on the webpage layout. Popular CSS frameworks that standardize screen split and provide a grid layout system are &lt;a href=&quot;http://www.blueprintcss.org&quot;&gt;Blueprint&lt;/a&gt;, &lt;a href=&quot;http://960.gs&quot;&gt;960 grid&lt;/a&gt; and &lt;a href=&quot;http://yuilibrary.com/yui/docs/cssgrids/&quot;&gt;YUI CSS grids&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Bootstrap also provides its own grid layout system. The grid system of Bootstrap consists of &lt;b&gt;12-column grid&lt;/b&gt; and there are two versions: default and fluid. In addition, it has four design patterns for a variety of screen sizes. The patterns are linked to the responsive design to be discussed later.&lt;/p&gt;
&lt;h3&gt;Default Grid System&lt;/h3&gt;
&lt;p&gt;The default grid system utilizes a 12-column grid that renders out at the width of 940 pixels.&lt;/p&gt;
&lt;p&gt;A row is expressed by using &lt;code&gt;row&lt;/code&gt; and a column is expressed by using &lt;code&gt;span*&lt;/code&gt;. The &lt;code&gt;span*&lt;/code&gt; class can be &lt;code&gt;span1-12&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The space between columns is 20 pixels and the width of the &lt;code&gt;span1&lt;/code&gt; class is 60 pixels. As the number of the &lt;code&gt;span*&lt;/code&gt; class increases by one, the width increases by 80 pixels, so the width of the &lt;code&gt;span12&lt;/code&gt; class is 940 pixels.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_1.png&quot; alt=&quot;figure_1.png&quot; title=&quot;figure_1.png&quot; class=&quot;iePngFix&quot; width=&quot;570&quot; height=&quot;187&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 1. 12-column Grid System.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The markup for the third row in Figure 1 is as shown below, expressed as 300 pixels + 20 pixels + 620 pixels (total 940 pixels) on the screen.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:xml&quot;  title=&quot;&quot;&gt;&amp;lt;div class=&quot;row&quot;&amp;gt;
    &amp;lt;div class=&quot;span4&quot;&amp;gt;&amp;hellip;&amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;span8&quot;&amp;gt;&amp;hellip;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Fluid Grid System&lt;/h3&gt;
&lt;p&gt;The fluid grid system uses percentage for column widths instead of fixed pixels. To use the fluid grid system, make any row fluid simply by changing to &lt;code&gt;row-fluid&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:xml&quot;  title=&quot;&quot;&gt;&amp;lt;div class=&quot;row-fluid&quot;&amp;gt;
    &amp;lt;div class=&quot;span4&quot;&amp;gt;&amp;hellip;&amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;span8&quot;&amp;gt;&amp;hellip;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Offsetting Columns&lt;/h3&gt;
&lt;p&gt;Add the &lt;code&gt;offset*&lt;/code&gt; class to a column to offset the column to the right. However, offsetting columns is available for the default grid system only.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_2.png&quot; alt=&quot;figure_2.png&quot; title=&quot;figure_2.png&quot; class=&quot;iePngFix&quot; width=&quot;579&quot; height=&quot;114&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 2. Offsetting Columns&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In Figure 2, the markup of the first row can be written as follows. The second row &amp;lt;div&amp;gt; will be offset to right as much as four-grid width (offset4).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:xml&quot;  title=&quot;&quot;&gt;&amp;lt;div class=&quot;row&quot;&amp;gt;
    &amp;lt;div class=&quot;span4&quot;&amp;gt;&amp;hellip;&amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;span4 offset4&quot;&amp;gt;&amp;hellip;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Nesting Columns&lt;/h3&gt;
&lt;p&gt;To nest your content as shown in Figure 3, just add a new &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; tag containing &lt;code&gt;row&lt;/code&gt; and set of &lt;code&gt;span*&lt;/code&gt; columns within an existing &lt;code&gt;.span*&lt;/code&gt; column.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_3.png&quot; alt=&quot;figure_3.png&quot; title=&quot;figure_3.png&quot; class=&quot;iePngFix&quot; width=&quot;476&quot; height=&quot;78&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 3. Nesting Columns&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For the default grid, the sum of nested rows should be the number of columns of its parents.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:xml&quot;  title=&quot;&quot;&gt;&amp;lt;div class=&quot;row&quot;&amp;gt;
    &amp;lt;div class=&quot;span6&quot;&amp;gt;
    Level 1 of column
        &amp;lt;div class=&quot;row&quot;&amp;gt;
            &amp;lt;div class=&quot;span3&quot;&amp;gt;Level 2&amp;lt;/div&amp;gt;
            &amp;lt;div class=&quot;span3&quot;&amp;gt;Level 2&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For nesting with a fluid grid, the sum of nested rows should be 12, not the parent column.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:xml&quot;  title=&quot;&quot;&gt;&amp;lt;div class=&quot;row-fluid&quot;&amp;gt;
    &amp;lt;div class=&quot;span6&quot;&amp;gt;
    Level 1 of column
        &amp;lt;div class=&quot;row-fluid&quot;&amp;gt;
            &amp;lt;div class=&quot;span6&quot;&amp;gt;Level 2&amp;lt;/div&amp;gt;
            &amp;lt;div class=&quot;span6&quot;&amp;gt;Level 2&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Responsive Design&lt;/h2&gt;
&lt;p&gt;Responsive Design requires to design the layout of a Web page&amp;nbsp;using the &lt;b&gt;CSS3 media queries&lt;/b&gt;&amp;nbsp;in a way so that the layout automatically adapts to the screen size and resolution of various devices such as smartphones, PC, and tablet PC.&lt;/p&gt;
&lt;p&gt;Bootstrap supports a flexible screen layout with its grid system and Responsive Design. The size of the grid is changed according to the screen size as shown in the following table.&lt;/p&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Table 1. Changed Grid Size by Device.&lt;/strong&gt;&lt;/div&gt;
&lt;table border=&quot;0&quot; style=&quot;border-collapse: collapse; margin: 0 auto;&quot; align=&quot;center&quot;&gt;
&lt;colgroup&gt;&lt;col style=&quot;width: 170px;&quot;&gt;&lt;/col&gt;&lt;col style=&quot;width: 136px;&quot;&gt;&lt;/col&gt;&lt;col style=&quot;width: 142px;&quot;&gt;&lt;/col&gt;&lt;col style=&quot;width: 191px;&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt; 
&lt;tbody valign=&quot;top&quot;&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-right: 7px; border: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Label&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: solid 0.5pt; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Layout width&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: solid 0.5pt; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Column width&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: solid 0.5pt; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Gutter width&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Smartphones&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;480 pixels and lower&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot; colspan=&quot;2&quot;&gt;
&lt;p&gt;Fluid columns, no fixed widths&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Portrait tablet PCs&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;767 pixels and lower&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot; colspan=&quot;2&quot;&gt;
&lt;p&gt;Fluid columns, no fixed widths&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Landscape tablet PCs&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;768 pixels and higher&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;42 pixels&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;20 pixels&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Default&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;980 pixels and higher&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;60 pixels&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;20 pixels&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Wide-screen monitor&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;1200 pixels and higher&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;70 pixels&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;30 pixels&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The following figure shows the changed layouts with responsive design according to the screen size.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_4.png&quot; alt=&quot;figure_4.png&quot; title=&quot;figure_4.png&quot; class=&quot;iePngFix&quot; width=&quot;563&quot; height=&quot;184&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 4. Responsive Design by Screen Size.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CSS that makes media queries responsive to the device size is as follows.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:css&quot;  title=&quot;&quot;&gt;// Landscape phones and down
@media (max-width: 480px) { ... }

// Landscape phone to portrait tablet
@media (max-width: 767px) { ... }

// Portrait tablet to landscape and desktop
@media (min-width: 768px) and (max-width: 979px) { ... }

// Large desktop
@media (min-width: 1200px) { ... }&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In addition, this CSS includes a selector as a utility that displays the optimized contents on the device.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Table 2. Responsive CSS Classes by Device.&lt;/strong&gt;&lt;/p&gt;
&lt;table border=&quot;0&quot; style=&quot;border-collapse: collapse; margin: 0 auto;&quot; align=&quot;center&quot;&gt;
&lt;colgroup&gt;&lt;col style=&quot;width: 161px;&quot;&gt;&lt;/col&gt;&lt;col style=&quot;width: 159px;&quot;&gt;&lt;/col&gt;&lt;col style=&quot;width: 159px;&quot;&gt;&lt;/col&gt;&lt;col style=&quot;width: 159px;&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt; 
&lt;tbody valign=&quot;top&quot;&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Class&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: solid 0.5pt; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Phones&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;480 pixels and lower&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: solid 0.5pt; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Tablet PCs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;767 pixels and lower&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: solid 0.5pt; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Desktops&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;768 pixels and higher&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;.visible-phone&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Visible&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Hidden&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Hidden&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;.visible-tablet&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Hidden&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Visible&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Hidden&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;.visible-desktop&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Hidden&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Hidden&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Visible&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;.hidden-phone&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Hidden&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Visible&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Visible&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;.hidden-tablet&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Visible&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Hidden&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Visible&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;.hidden-desktop&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Visible&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Visible&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Hidden&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;CSS with a Clean and Organized Look&lt;/h2&gt;
&lt;p&gt;Bootstrap provides buttons and a variety of styles offering a clean and organized look with the default CSS.&lt;/p&gt;
&lt;p&gt;The following table shows the default button designs of Bootstrap.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Table 3. CSS Class by Button Type.&lt;/strong&gt;&lt;/p&gt;
&lt;table border=&quot;0&quot; style=&quot;border-collapse: collapse; margin: 0 auto;&quot; align=&quot;center&quot;&gt;
&lt;colgroup&gt;&lt;col style=&quot;width: 115px;&quot;&gt;&lt;/col&gt;&lt;col style=&quot;width: 115px;&quot;&gt;&lt;/col&gt;&lt;col style=&quot;width: 409px;&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt; 
&lt;tbody valign=&quot;top&quot;&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Button&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: solid 0.5pt; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;class=&quot;&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: solid 0.5pt; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/button_default.png&quot; alt=&quot;button_default.png&quot; title=&quot;button_default.png&quot; class=&quot;iePngFix&quot; width=&quot;64&quot; height=&quot;30&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;btn&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Gray default button with gradation&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/button_primary.png&quot; alt=&quot;button_primary.png&quot; title=&quot;button_primary.png&quot; class=&quot;iePngFix&quot; width=&quot;69&quot; height=&quot;30&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;btn btn-primary&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Button indicating something that needs to be visually highlighted or specialized&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/button_info.png&quot; alt=&quot;button_info.png&quot; title=&quot;button_info.png&quot; class=&quot;iePngFix&quot; width=&quot;44&quot; height=&quot;30&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;btn btn-info&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Button that can replace the default button&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/button_success.png&quot; alt=&quot;button_success.png&quot; title=&quot;button_success.png&quot; class=&quot;iePngFix&quot; width=&quot;75&quot; height=&quot;30&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;btn btn-success&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Button indicating a successful or positive behavior&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/button_warning.png&quot; alt=&quot;button_warning.png&quot; title=&quot;button_warning.png&quot; class=&quot;iePngFix&quot; width=&quot;72&quot; height=&quot;30&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;btn btn-warning&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Warning button&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/button_danger.png&quot; alt=&quot;button_danger.png&quot; title=&quot;button_danger.png&quot; class=&quot;iePngFix&quot; width=&quot;65&quot; height=&quot;30&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;btn btn-danger&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Button indicating danger or a negative effect&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: solid 0.5pt; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/button_inverse.png&quot; alt=&quot;button_inverse.png&quot; title=&quot;button_inverse.png&quot; class=&quot;iePngFix&quot; width=&quot;64&quot; height=&quot;30&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;btn btn-inverse&lt;/p&gt;
&lt;/td&gt;
&lt;td style=&quot;padding-left: 7px; padding-right: 7px; border-top: none; border-left: none; border-bottom: solid 0.5pt; border-right: solid 0.5pt;&quot;&gt;
&lt;p&gt;Dark gray button that can be used generally without any special meaning&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The following table shows the default form designs of Bootstrap.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_5.png&quot; alt=&quot;figure_5.png&quot; title=&quot;figure_5.png&quot; class=&quot;iePngFix&quot; width=&quot;555&quot; height=&quot;403&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 5. CSS Class for Form.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Initially, Bootstrap did not support Internet Explorer. However, it has been changed to be compatible with Internet Explorer 7 and above. Therefore, form design for Internet Explorer is not identical according to the version. A minor difference may be seen according to CSS support, such as gradation and rounded border. However, the overall layout and colors remain the same.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_6.png&quot; alt=&quot;figure_6.png&quot; title=&quot;figure_6.png&quot; class=&quot;iePngFix&quot; width=&quot;572&quot; height=&quot;233&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 6. Comparison of Examples of Expressing Form Design in Internet Explorer.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CSS Reset uses Nicolas Gallagher&apos;s &lt;a href=&quot;http://necolas.github.com/normalize.css/&quot;&gt;normalize.css&lt;/a&gt; and UI icon image uses a set of icons provided by Glyphicons. The icon set is a single image in which the CSS Sprite technique is used.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_7.png&quot; alt=&quot;figure_7.png&quot; title=&quot;figure_7.png&quot; class=&quot;iePngFix&quot; width=&quot;492&quot; height=&quot;182&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 7. Glyphicons Icon Set.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The following is an example of a UI component where the icon set is applied.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_8.png&quot; alt=&quot;figure_8.png&quot; title=&quot;figure_8.png&quot; class=&quot;iePngFix&quot; width=&quot;563&quot; height=&quot;187&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 8. UI Component with Icon Set.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Bootstrap CSS is written in LESS so it is easy to modify and reproduce a theme. This will be discussed later.&lt;/p&gt;
&lt;h2&gt;UI Component and jQuery Plug-in&lt;/h2&gt;
&lt;p&gt;There are UI patterns that are frequently used for producing webpages. UI components refers to a bundle of markup, CSS and JavaScript for easy pattern reuse.&lt;/p&gt;
&lt;p&gt;Bootstrap has a default CSS that provides a variety of easy-to-use UI components. Some components that require dynamic interaction can be controlled by jQuery plug-in type JavaScript.&lt;/p&gt;
&lt;p&gt;A component that uses the default CSS has the button group, dropdown list, navigation, tab, Move Page button, thumbnail layout, warning display and close icon. For a more detailed component list and examples, see &lt;a href=&quot;http://twitter.github.com/bootstrap/components.html&quot;&gt;http://twitter.github.com/bootstrap/components.html&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Components that control the interaction by using the jQuery plug-in are modal layer, dropdown, toggle tap and tooltip. For a more detailed component list and examples, see &lt;a href=&quot;http://twitter.github.com/bootstrap/javascript.html&quot;&gt;http://twitter.github.com/bootstrap/javascript.html&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote class=&quot;q4&quot;&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;NHN has open sourced&amp;nbsp;&lt;a target=&quot;_self&quot; href=&quot;http://html.nhndesign.com/uio_factory&quot;&gt;UIO Factory&lt;/a&gt;,&amp;nbsp;which provides developers a static UI pattern set, as well as Jindo framework-based &lt;a target=&quot;_self&quot; href=&quot;http://dev.naver.com/projects/jindo/&quot;&gt;Jindo Component&lt;/a&gt;&amp;nbsp;which&amp;nbsp;provides components for dynamic UI.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;LESS&lt;/h2&gt;
&lt;p&gt;Different from general programming language, CSS has no inheritance or variable. Therefore, developers should modify the code when they need to modify just the screen height. It is quite cumbersome to write and manage CSS. To solve this problem, the CSS preprocessors have been developed.&lt;/p&gt;
&lt;p&gt;CSS preprocessors have self-defined syntax by expanding the existing CSS syntax. The expanded syntax allows for describing variables, mixin, inheritance, operation, and function, and creating the final CSS that is compatible with the browser by compiling the code written with the expanded CSS. Some people have been inconvenienced by not having dynamic and object-oriented concept from CSS3.&lt;/p&gt;
&lt;p&gt;The most popular CSS preprocessors are &lt;a href=&quot;http://lesscss.org/&quot;&gt;LESS&lt;/a&gt;, &lt;a href=&quot;http://sass-lang.com/&quot;&gt;Sass&lt;/a&gt; and &lt;a href=&quot;http://learnboost.github.com/stylus/&quot;&gt;Stylus&lt;/a&gt;, and the syntax and functions are similar. Bootstrap uses LESS as its CSS preprocessor.&lt;/p&gt;
&lt;p&gt;Even though it has significant benefits, most domestic sites have not applied the CSS preprocessors so far. As well as the inconvenience of compiling, in most cases, homepage design has been outsourced just for one-time so the existing CSS has not been reused and there are not many professionals who can create well-structured markup and CSS. In foreign countries, after releasing Bootstrap on&amp;nbsp;&lt;a href=&quot;https://github.com/&quot;&gt;Github&lt;/a&gt;, an active movement for applying CSS preprocessors is made and many developers started to create projects for which CSS preprocessors are changed to Sass or Stylus instead of LESS.&lt;/p&gt;
&lt;p&gt;Let&apos;s discuss LESS in detail.&lt;/p&gt;
&lt;h3&gt;LESS Syntax&lt;/h3&gt;
&lt;p&gt;LESS syntax uses a syntax that expands the functions only on the standard CSS syntax.&lt;/p&gt;
&lt;h4&gt;Variable Declaration&lt;/h4&gt;
&lt;p&gt;To declare a variable, use the &lt;code&gt;@&lt;/code&gt; symbol.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:css&quot;  title=&quot;&quot;&gt;@mainColor: #0982c1;
@siteWidth: 1024px;
@borderStyle: dotted;

body {
  color: @mainColor;
  border: 1px @borderStyle @mainColor;
  max-width: @siteWidth;
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;Mixin Function&lt;/h4&gt;
&lt;p&gt;You can create a mixin function similar to the class selector as shown below.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:css&quot;  title=&quot;&quot;&gt;/* LESS mixin error with (optional) argument @borderWidth which defaults to 2px if not specified */
.error(@borderWidth: 2px) {
border: @borderWidth solid #F00;
color: #F00;
}

.generic-error {
padding: 20px;
margin: 4px;
.error(); /* Applies styles from mixin error */
}
.login-error {
left: 12px;
position: absolute;
top: 20px;
.error(5px); /* Applies styles from mixin error with argument @borderWidth equal to 5px */
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;Inheritance&lt;/h4&gt;
&lt;p&gt;LESS defines the mixin function as a class selector. Therefore, the general class selector can be used as a mixin function so that inheritance can be expressed as shown below.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:css&quot;  title=&quot;&quot;&gt;.block {
margin: 10px 5px;
padding: 2px;
}

p {
.block; /* Inherit styles from &apos;.block&apos; */
border: 1px solid #EEE;
}
ul, ol {
.block; /* Inherit styles from &apos;.block&apos; */
color: #333;
text-transform: uppercase;
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;Operator&lt;/h4&gt;
&lt;p&gt;A simple operator can be used for the operable attributes as shown below.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:css&quot;  title=&quot;&quot;&gt;body {
margin: (14px/2);
top: 50px + 100px;
right: 100px - 50px;
left: 10 * 10;
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;Nested Selector&lt;/h4&gt;
&lt;p&gt;Nested selector is expressed as shown below.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:css&quot;  title=&quot;&quot;&gt;section {
margin: 10px;

nav {
height: 25px;

a {
color: #0982C1;

&amp;amp;:hover {
text-decoration: underline;
}
}
}
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;When compiling a nested selector, the following CSS is made.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:css&quot;  title=&quot;&quot;&gt;section {
margin: 10px;
}
section nav {
height: 25px;
}
section nav a {
color: #0982C1;
}
section nav a:hover {
text-decoration: underline;
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Bootstrap LESS&lt;/h3&gt;
&lt;p&gt;There are a lot of pre-defined LESS variables and mixins related to the layouts and components. By modifying the predefined variables and mixins, it is simple to  change and create a variety of themes.&lt;/p&gt;
&lt;p&gt;The following is an example of LESS variables and values defined by Bootstrap by default. For more details, see &lt;a href=&quot;http://twitter.github.com/bootstrap/less.html&quot;&gt;http://twitter.github.com/bootstrap/less.html#variables&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_9.png&quot; alt=&quot;figure_9.png&quot; title=&quot;figure_9.png&quot; class=&quot;iePngFix&quot; width=&quot;553&quot; height=&quot;236&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 9. A Variety of LESS Variables of Bootstrap.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The following is an example defined in Bootstrap by default. For more details, see &lt;a href=&quot;http://twitter.github.com/bootstrap/less.html&quot;&gt;http://twitter.github.com/bootstrap/less.html#mixins&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_11.png&quot; alt=&quot;figure_11.png&quot; title=&quot;figure_11.png&quot; class=&quot;iePngFix&quot; width=&quot;553&quot; height=&quot;401&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 10. A Variety of LESS Mixins of Bootstrap.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;LESS Compiling&lt;/h3&gt;
&lt;p&gt;LESS compiling is classified into client side and server side.&lt;/p&gt;
&lt;p&gt;For client side compiling, the &lt;b&gt;&lt;span style=&quot;font-family: monospace;&quot;&gt;less.js&lt;/span&gt;&lt;/b&gt; file is saved in the Web server and linked as shown below.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:xml&quot;  title=&quot;&quot;&gt;&amp;lt;link rel=&quot;stylesheet/less&quot; type=&quot;texr/css&quot; href=&quot;bootstrap.less&quot;&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot; src=&quot;less.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For server side compiling, download the compiler from the node.js package manager and then install and use it.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush:bash&quot;  title=&quot;&quot;&gt;$ npm install &amp;ndash;g less
$ lessc bootstrap.less &amp;gt; bootstrap.css&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Customizing&lt;/h2&gt;
&lt;p&gt;The Bootstrap homepage allows developers to customize a set of CSS and jQuery plug-in by changing the variables applied to LESS and selecting the desired CSS and jQuery plug-in.&amp;nbsp;You can select the components and jQuery plug-ins and download the desired CSS and jQuery JavaScript.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_12.png&quot; alt=&quot;figure_12.png&quot; title=&quot;figure_12.png&quot; class=&quot;iePngFix&quot; width=&quot;503&quot; height=&quot;364&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 11. Bootstrap Customizing Page.&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Even though there is no LESS compiler, you can change the values applied to the LESS variables as desired on the Customizing Page.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_13.png&quot; alt=&quot;figure_13.png&quot; title=&quot;figure_13.png&quot; class=&quot;iePngFix&quot; width=&quot;503&quot; height=&quot;231&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 12. LESS Variable Value Customizing.&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot;&gt;Select the components and jQuery plug-ins, modify the LESS variable values, and then click the Download button to download the .zip file compressing the selected CSS and JavaScript.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/843/400/figure_14.png&quot; alt=&quot;figure_14.png&quot; title=&quot;figure_14.png&quot; class=&quot;iePngFix&quot; width=&quot;503&quot; height=&quot;135&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;strong&gt;Figure 13. Customizing Result Download.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As well as the customizing page, you can use a variety of themes from &lt;a href=&quot;http://bootswatch.com/&quot;&gt;http://bootswatch.com/&lt;/a&gt;, &lt;a href=&quot;http://wrapbootstrap.com/&quot;&gt;http://wrapbootstrap.com/&lt;/a&gt;, and &lt;a href=&quot;http://stylebootstrap.info/&quot;&gt;http://stylebootstrap.info/&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;If we take a deeper look into Bootstrap from Twitter, we can see very little new technology. There seems to be nothing special.  Nevertheless, Bootstrap is very popular which is proved by the number of &lt;a href=&quot;https://github.com/popular/watched&quot;&gt;watches&lt;/a&gt;&amp;nbsp;and &lt;a href=&quot;https://github.com/popular/forked&quot;&gt;forks&lt;/a&gt;&amp;nbsp;of Bootstrap project on Github. Also there are a variety of Bootstrap-related sites. There are a large number of well designed components accompanied by a set of jQuery plugins. It is a great framework if you want to build beautiful Web sites quickly.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;line-height: normal;&quot;&gt;By Kyungil Park, Senior Software Engineer, NHN Platform Ajax Team, NHN Corporation.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote class=&quot;q4&quot;&gt;
&lt;p&gt;&lt;span style=&quot;line-height: normal;&quot;&gt;&lt;b&gt;About the author:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;line-height: normal;&quot;&gt;I develop the JavaScript CI server and a variety of tools in NHN Platform Ajax Team. I like everything related to development. Dreaming of being a gray-haired developer...&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Bootstrap, from Twitter: &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;http://twitter.github.com/bootstrap/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Stepping Out Width Bootstrap from Twitter: &lt;a href=&quot;http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/stepping-out-with-bootstrap-from-twitter/&quot;&gt;http://webdesign.tutsplus.com/tutorials/htmlcss-tutorials/stepping-out-with-bootstrap-from-twitter/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CSS3 Media Queries: &lt;a href=&quot;http://www.w3.org/TR/css3-mediaqueries/&quot;&gt;http://www.w3.org/TR/css3-mediaqueries/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Sass vs. LESS vs. Stylus: &lt;a href=&quot;http://net.tutsplus.com/tutorials/html-css-techniques/sass-vs-less-vs-stylus-a-preprocessor-shootout/&quot;&gt;http://net.tutsplus.com/tutorials/html-css-techniques/sass-vs-less-vs-stylus-a-preprocessor-shootout/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;20 Resources for Bootstrap Lovers: &lt;a href=&quot;http://designshack.net/articles/css/20-awesome-resources-for-twitter-bootstrap-lovers/&quot;&gt;http://designshack.net/articles/css/20-awesome-resources-for-twitter-bootstrap-lovers/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;</content>
                  <category term="Bootstrap"/>
            <category term="Twitter"/>
            <category term="Web development"/>
            <category term="CSS"/>
            <category term="LESS"/>
            <category term="JavaScript"/>
            <category term="jQuery"/>
            
   </entry>
   <entry>
      <title>What is SPDY? Deployment Recommendations</title>
      <id>http://www.cubrid.org/blog/504186</id>
      <published>2012-11-25T16:22:07-08:00</published>
      <updated>2013-03-06T05:04:53-08:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/504186"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/504186#comment"/>
      <author>
         <name>Se Hoon Park</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In the middle of this year a &lt;a target=&quot;_self&quot; href=&quot;http://news.cnet.com/8301-1023_3-57472566-93/facebook-endorses-googles-spdy-networking-protocol/&quot;&gt;news report&lt;/a&gt;&amp;nbsp;announced that Facebook is planning to support&amp;nbsp;Google&apos;s&amp;nbsp;SPDY protocol in large scale, and that they are already implementing SPDY/v2. Here is the &lt;a target=&quot;_self&quot; href=&quot;http://lists.w3.org/Archives/Public/ietf-http-wg/2012JulSep/0251.html&quot;&gt;official response&lt;/a&gt; from Facebook that I have found on this topic.&amp;nbsp;Among various efforts devised and suggested&amp;nbsp;by Google&amp;nbsp;to make the Web faster,&amp;nbsp;I think SPDY will be&amp;nbsp;the one to become a new industry standard, and it will be included in HTTP/2.0.&lt;/p&gt;
&lt;p&gt;As an acronym of &lt;b&gt;SPeeDy&lt;/b&gt;, SPDY is a new protocol Google has suggested as a part of its efforts to &quot;&lt;i&gt;make the Web faster&lt;/i&gt;.&quot; It was suggested as a protocol to use the present and future Internet environment more efficiently by addressing the disadvantages of HTTP devised in the early Internet environment.&lt;/p&gt;
&lt;p&gt;In this article, I will provide a brief introduction to the features and merits of SPDY. I will explain about the state of SPDY&amp;nbsp;support,&amp;nbsp;and what to do and what to consider when it is introduced.&lt;/p&gt;
&lt;h2&gt;When was the latest version of HTTP released?&lt;/h2&gt;
&lt;p&gt;HTTP version 0.9 was first announced in 1991, and HTTP 1.0 and 1.1 were released in 1996 and 1999, respectively, and since then nothing has been changed in HTTP for the last 10 years. These days, however, a webpage has a size 20 times bigger with 20 times more HTTP requests than a webpage in the 1990s. The &lt;b&gt;Table 1&lt;/b&gt;&amp;nbsp;below shows the data quoted from Google I/O 2012.&lt;/p&gt;
&lt;table style=&quot;margin: 0 auto;&quot;&gt;
&lt;caption&gt;&lt;b&gt;Table 1: Comparison of Mean Webpage Size in 2010 and 2012.&lt;/b&gt;&lt;/caption&gt; &lt;thead&gt; 
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt; &lt;th&gt;Mean page size&lt;/th&gt; &lt;th&gt;Mean # of requests per page&lt;/th&gt; &lt;th&gt;Mean No. of domains&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2010 Nov. 15&lt;/td&gt;
&lt;td&gt;702 KB&lt;/td&gt;
&lt;td&gt;74&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2012 May 5&lt;/td&gt;
&lt;td&gt;1059 KB&lt;/td&gt;
&lt;td&gt;84&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The capacity of the Yahoo! main page in 1996 was 34 KB. That is only 1/30 of the mean webpage capacity in 2012.&amp;nbsp;There is a significant gap even between 2010 and 2012, let alone between the 1990s and 2012. This is because the mean page size and number of requests are ever increasing as User UX is becoming more and more sophisticated along with the dissemination of high-speed Internet.&lt;/p&gt;
&lt;p&gt;The characteristics of today&apos;s webpage have changed from that in the past as follows:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Consists of much more resources.&lt;/li&gt;
&lt;li&gt;Uses multiple domains.&lt;/li&gt;
&lt;li&gt;Operates more dynamically.&lt;/li&gt;
&lt;li&gt;Emphasizes security more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Considering how today&apos;s web environment is different from the past, Google has announced the SPDY protocol, which complemented the disadvantages of HTTP.&amp;nbsp;SPDY focuses especially on resolving the problem of load latency.&lt;/p&gt;
&lt;h2&gt;Features of SPDY&lt;/h2&gt;
&lt;p&gt;The &lt;b&gt;Figure 1&lt;/b&gt;&amp;nbsp;below shows the layers of SPDY compared to the traditional TCP/IP layer model.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/186/504/http_vs_spdy.png&quot; alt=&quot;http_vs_spdy.png&quot; title=&quot;http_vs_spdy.png&quot; class=&quot;iePngFix&quot; width=&quot;567&quot; height=&quot;266&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1: HTTP vs. SPDY.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The features of SPDY can be summarized as follows:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Always operates on Transport Layer Security (TLS). 
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;Transport Layer Security (TLS) is the next version of Secure Sockets Layer (SSL). TLS and SSL are sometimes used to refer to the same protocol because they are the name for two different versions of the same protocol, and this also applies to this article.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Therefore, SPDY applies only to websites written with HTTPS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;HTTP Header compression&lt;/h3&gt;
&lt;p&gt;As HTTP headers have many redundant contents whenever a request is made, you can improve the performance significantly just by compressing headers. According to a report by Google, it is possible to reduce the size by 10-35% by compressing HTTP headers even in the initial request, and reduce the size of headers by 80-97% when requests are made several times (long-lived connection). Also, when the upload bandwidth is relatively small, as in mobile devices, this HTTP header compression is more useful. These days, as the HTTP header is 2 KB on average and is growing bigger, the merit of compressing HTTP headers is expected to grow in the future.&lt;/p&gt;
&lt;h3&gt;Binary protocol&lt;/h3&gt;
&lt;p&gt;As it uses binary framing rather than text-based framing, it provides faster parsing and is less sensitive to errors.&lt;/p&gt;
&lt;h3&gt;Multiplexing&lt;/h3&gt;
&lt;p&gt;SPDY handles multiple independent streams in a single connection concurrently. For this reason, unlike HTTP which handles one request at a time in a single connection with response to requests made consecutively, SPDY handles multiple requests and responses concurrently with a small number of connections. In addition, unlike HTTP pipelining in which if one response is delayed, the others are all delayed, SPDY handles each request and response independently as it uses a FIFO queue.&lt;/p&gt;
&lt;h3&gt;Full-duplex interleaving and stream prioritization&lt;/h3&gt;
&lt;p&gt;As SPDY allows interleaving in which one stream in a process can be interleaved with another and stream prioritization, data of higher priority can jump into the process of transportation of data of lower priority and can be transported earlier.&lt;/p&gt;
&lt;h3&gt;Server push&lt;/h3&gt;
&lt;p&gt;Servers can push content without client requests unlike Comet and Long-polling. Unlike methods such as inlining, SPDY supports resource caching and uses the same bandwidth as that of inlining or a smaller bandwidth. When implementing server push, however, you need to implement additional Web server application logic.&lt;/p&gt;
&lt;h3&gt;No need to re-write a website&lt;/h3&gt;
&lt;p&gt;Except for some features that require additional implementation, such as server push, you don&apos;t need to change a website itself to apply SPDY. However, the browser and the server should support SPDY. SPDY can be applied completely and transparently to browser users. In other words, there is no protocol scheme like &quot;spdy://.&quot; The browser also displays nothing with regard to the use of the SPDY protocol.&lt;/p&gt;
&lt;p&gt;Based on such characteristics of SPDY, the following table shows the difference between HTTP and SPDY.&lt;/p&gt;
&lt;table style=&quot;margin: 0 auto;&quot;&gt;
&lt;caption&gt;&lt;b&gt;Table 2: HTTP/1.1 vs. SPDY.&lt;/b&gt;&lt;/caption&gt; &lt;thead&gt; 
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt; &lt;th&gt;HTTP&lt;/th&gt; &lt;th&gt;SPDY&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Secure&lt;/td&gt;
&lt;td&gt;Not Default&lt;/td&gt;
&lt;td&gt;Default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Header Compression&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiplexing&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full-Duplex&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prioritization&lt;/td&gt;
&lt;td&gt;No, (instead, a browser employs heuristics.)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Server push&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DNS Lookup&lt;/td&gt;
&lt;td&gt;More&lt;/td&gt;
&lt;td&gt;Less&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connections&lt;/td&gt;
&lt;td&gt;More&lt;/td&gt;
&lt;td&gt;Less&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Therefore, it can be said that SPDY is a protocol designed to use TCP connection more efficiently by improving the data transfer format and connection management of HTTP.&amp;nbsp;As a result of such efforts, in a test with the top 25 websites, SPDY worked 39-55% faster compared to HTTP + SSL.&lt;/p&gt;
&lt;h2&gt;Why does SPDY need TLS?&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;Why does SPDY use TLS even though using TLS causes latency due to encryption/decryption?&lt;/b&gt; Google&apos;s &lt;a target=&quot;_self&quot; href=&quot;http://www.chromium.org/spdy/spdy-whitepaper/&quot;&gt;SPDY Whitepaper&lt;/a&gt; states the following answer for this question:&amp;nbsp;&lt;/p&gt;
&lt;blockquote class=&quot;q1&quot;&gt;
&lt;p&gt;&lt;i&gt;&quot;In the long term, the importance of web security will be emphasized more and more, and thus we want to get a better security in the future by specifying TLS as a sub protocol of SPDY.&amp;nbsp;We need TLS for compatibility with the current network infrastructure. In other words, we need it to prevent any compatibility issue with the communication going through the existing proxy.&amp;rdquo;&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Despite this reason, when looking into the implementation of the actual SPDY, you can see that SPDY depends much on TLS&apos;s Next Protocol Negotiation (NPN) extension mechanism. This TLS NPN extension mechanism determines whether a request coming from Port 443 is SPDY or not and identifies the version of SPDY used by the request, to decide whether to use SPDY to handle the next communication. Without TLS NPN, you will need to get additional RTT to use SPDY.&lt;/p&gt;
&lt;h2&gt;Efforts for Standardization&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;SPDY is being developed as an open networking protocol and has been suggested to IETF as a method of HTTP/2.0. SPDY is a sub-project of the Google Chromium project, and thus Chromium client implementations and server tools are all being developed with open sources.&lt;/p&gt;
&lt;h2&gt;Future of SPDY&lt;/h2&gt;
&lt;p&gt;Most recently SPDY Draft 3 was released, and SPDY Draft 4 is under development.&amp;nbsp;The features likely to be added in Draft 4 are as follows:&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Name resolution push&lt;/li&gt;
&lt;li&gt;Certificate data push&lt;/li&gt;
&lt;li&gt;Explicit proxy support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The final goal of SPDY is to provide a page within &quot;a single connection setup time + bytes/bandwidth time&quot;.&lt;/p&gt;
&lt;h2&gt;Browsers, Servers, Libraries and Web Services Supporting SPDY&lt;/h2&gt;
&lt;p&gt;Currently a variety of browsers and servers support SPDY, and Google, who originally suggested SPDY, already provides almost all of its services with SPDY. The browsers, servers, libraries and services supporting SPDY are as follows.&lt;/p&gt;
&lt;h3&gt;Browsers Supporting SPDY&lt;/h3&gt;
&lt;p&gt;As of July 2012, the following is a list of browsers which support the SPDY protocol.&lt;/p&gt;
&lt;h4&gt;Google Chrome/Chromium&lt;/h4&gt;
&lt;p&gt;Chrome and Chromium have supported SPDY from their initial version. If you enter the following URI, you can inspect SPDY sessions in Chrome/Chromium: &lt;a target=&quot;_self&quot; href=&quot;/chrome://net-internals/#events&amp;amp;q=type:SPDY_SESSION%20is:active&quot;&gt;chrome://net-internals/#events&amp;amp;q=type:SPDY_SESSION%20is:active&lt;/a&gt;. For example, if you visit &lt;a target=&quot;_self&quot; href=&quot;http://www.gmail.com&quot;&gt;www.gmail.com&lt;/a&gt;, in the&amp;nbsp;&lt;a target=&quot;_self&quot; href=&quot;/chrome://net-internals/#events&amp;amp;q=type:SPDY_SESSION%20is:active&quot;&gt;chrome://&lt;/a&gt;&amp;nbsp;tab&amp;nbsp;you can see multiple SPDY sessions being created. Android mobile Chrome also supports SPDY.&lt;/p&gt;
&lt;h4&gt;Firefox 11 and later versions&lt;/h4&gt;
&lt;p&gt;While added in version 11, SPDY was not enabled by default until Firefox version 13. If you enter &lt;a target=&quot;_self&quot; href=&quot;/about:config&quot;&gt;about:config&lt;/a&gt;&amp;nbsp;in FF, which is the URI for Firefox settings, and see &lt;code&gt;network.http.spdy.enabled&lt;/code&gt;, you can check whether support for SPDY has been enabled or not. Android mobile Firefox 14 also supports SPDY.&lt;/p&gt;
&lt;h4&gt;Amazon Silk&lt;/h4&gt;
&lt;p&gt;The Silk browser equipped in Kindle Fire, an Android-based e-book reader from Amazon, also supports SPDY. It communicates with Amazon EC2 service by using SPDY.&lt;/p&gt;
&lt;h4&gt;Default browser of Android 3.0 and higher&lt;/h4&gt;
&lt;p&gt;The default browser of Android 3.0 (Honeycomb) and 4.0 (Ice Cream Sandwich) supports SPDY.&lt;/p&gt;
&lt;p&gt;For more information about which browsers support SPDY, see&amp;nbsp;&lt;a target=&quot;_self&quot; href=&quot;http://caniuse.com/spdy&quot;&gt;http://caniuse.com/spdy&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Servers and Libraries Supporting SPDY&lt;/h3&gt;
&lt;p&gt;Support for SPDY is being vitalized mainly by major web servers and application servers, and a variety of libraries that implement SPDY are also being developed.&lt;/p&gt;
&lt;h4&gt;Nginx&lt;/h4&gt;
&lt;p&gt;Nginx released a beta version of SPDY module on June 15, 2012, and has continuously provided &lt;a target=&quot;_self&quot; href=&quot;http://nginx.org/patches/spdy&quot;&gt;patches&lt;/a&gt;. See &lt;a target=&quot;_self&quot; href=&quot;http://www.slideshare.net/profyclub_ru/spdy-146-14829935&quot;&gt;SPDY: 146% faster&lt;/a&gt;&amp;nbsp;Slideshare presentation by Nginx team to learn more about it.&lt;/p&gt;
&lt;h4&gt;Jetty&lt;/h4&gt;
&lt;p&gt;Jetty also provides the &lt;a target=&quot;_self&quot; href=&quot;http://wiki.eclipse.org/Jetty/Feature/SPDY&quot;&gt;SPDY module&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Apache&lt;/h4&gt;
&lt;p&gt;The &lt;a target=&quot;_self&quot; href=&quot;http://code.google.com/p/mod-spdy/&quot;&gt;SPDY module for Apache 2.2&lt;/a&gt; is also being developed.&lt;/p&gt;
&lt;h4&gt;Libraries&lt;/h4&gt;
&lt;p&gt;In addition, SPDY implementation structures for Python, Ruby and node.js servers have already been developed or are currently being developed.&amp;nbsp;There are a variety of versions for &lt;a target=&quot;_self&quot; href=&quot;http://libspdy.org/index.html&quot;&gt;SPDY C library&lt;/a&gt;, including &lt;b&gt;libspdy&lt;/b&gt;, &lt;b&gt;spindly&lt;/b&gt; and &lt;b&gt;spdylay&lt;/b&gt;.&amp;nbsp;A library to use &lt;a target=&quot;_self&quot; href=&quot;https://github.com/sorced-jim/SPDY-for-iPhone&quot;&gt;SPDY on iOS&lt;/a&gt; is also being developed.&lt;/p&gt;
&lt;h4&gt;Netty&lt;/h4&gt;
&lt;p&gt;Netty began to provide &lt;a target=&quot;_self&quot; href=&quot;https://netty.io/Blog/Netty+331+released+-+SPDY+Protocol+%21&quot;&gt;SPDY package&lt;/a&gt; from its 3.3.1 version released in 2012.&lt;/p&gt;
&lt;h4&gt;Tomcat&lt;/h4&gt;
&lt;p&gt;SPDY support in&amp;nbsp;Tomcat is currently under development and it should come in Tomcat version 8.&lt;/p&gt;
&lt;h3&gt;Services Using SPDY&lt;/h3&gt;
&lt;p&gt;As mentioned earlier, Google has already converted almost all of its services, including search, Gmail and Google plus, into HTTPS, and provides them through SPDY. In addition, when Google App Engine uses&amp;nbsp;HTTPS, it also supports SPDY. Twitter also uses SPDY when providing service via&amp;nbsp;HTTPS.&lt;/p&gt;
&lt;p&gt;However, among numerous Web sites on the Internet, only a few websites use SPDY. According to a &lt;a target=&quot;_self&quot; href=&quot;http://news.netcraft.com/archives/2012/05/02/may-2012-web-server-survey.html&quot;&gt;survey by Netcraft&lt;/a&gt; conducted in May 2012, of a total of 660 million websites only 339 websites are currently using SPDY. In other words, except for Google and Twitter, there is hardly any major website using SPDY.&lt;/p&gt;
&lt;h2&gt;When SPDY is Not Very Efficient&lt;/h2&gt;
&lt;p&gt;SPDY is not always fast. Sometimes you may not get any performance improvement with SPDY. Such situations are as follows.&lt;/p&gt;
&lt;h3&gt;When using only HTTP&lt;/h3&gt;
&lt;p&gt;As SPDY always requires SSL, you need additional SSL handshake time. Therefore, when you convert an HTTP site into HTTPS to support SPDY, you may not obtain distinct performance improvement due to SSL handshake.&lt;/p&gt;
&lt;h3&gt;When there are too many domains&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;SPDY operates by domain.&lt;/b&gt; This means that it requires as many connections as the number of domains, and that request multiplexing is available only in a single domain. Moreover, as it is difficult to make all domains support SPDY, you may not get the merits of SPDY when there are too many domains. Especially when a CDN does not support SPDY, you may not expect the performance improvement with SPDY.&lt;/p&gt;
&lt;h3&gt;When HTTP is not the bottleneck&lt;/h3&gt;
&lt;p&gt;For most pages, HTTP is not the bottleneck. For example, in cases when a resource can be downloaded only after another resource is downloaded, SPDY will not be that effective.&lt;/p&gt;
&lt;h3&gt;When Round-Trip-Time (RTT) is low&lt;/h3&gt;
&lt;p&gt;SPDY is more efficient when RTT is high.&amp;nbsp;When RTT is very low, for example,&amp;nbsp;in communications between servers within IDC, SPDY has few merits.&lt;/p&gt;
&lt;h3&gt;When resource in a page is very small&lt;/h3&gt;
&lt;p&gt;For pages with six or fewer resources, SPDY has few merits because the value of reusing connection is not significant.&lt;/p&gt;
&lt;h2&gt;Things to Do to Introduce SPDY&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;When you introduce SPDY, you need to carry out the following tasks to apply it most efficiently.&lt;/p&gt;
&lt;h3&gt;Application Level&lt;/h3&gt;
&lt;h4&gt;Use only one connection&lt;/h4&gt;
&lt;p&gt;For better SPDY performance and more efficient use of Internet resources, you need to use as few connections as possible. If you use a small number of connections when using SPDY, you can see the benefits such as putting data into packets in a better way, getting better header compression efficiency, reducing the frequency of checking the status of connection and reducing the frequency of handshake. Also, in terms of Internet resources, with a small number of connections, you can also have a more efficient TCP and reduce Bufferbloat.&lt;/p&gt;
&lt;blockquote class=&quot;q4&quot;&gt;
&lt;p&gt;&lt;b&gt;Bufferbloat&lt;/b&gt; is a phenomenon in which excess buffering of packets at a router or a switch causes high latency and reduced throughput. With the idea of avoiding packet discards as much as possible and low memory prices, the buffer size of a router or a switch is continuously increasing. The packets that should have been discarded earlier could survive longer and as a result these packets hinder TCP congestion avoidance algorithm, deteriorating the overall network performance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Avoid domain sharding&lt;/h4&gt;
&lt;p&gt;Domain sharding is a kind of expedient used to avoid the restriction on the number of concurrent downloads (&lt;i&gt;&lt;a target=&quot;_self&quot; href=&quot;http://stackoverflow.com/a/985704/556678&quot;&gt;in general&lt;/a&gt;, six downloads per hostname in modern browsers&lt;/i&gt;) in web applications. If you use SPDY and comply with &quot;use a single connection&quot; recommendation, you don&apos;t need to use domain sharding. To make it worse, domain sharding causes additional DNS queries and makes applications more complex.&lt;/p&gt;
&lt;h4&gt;Use server push instead of inlining&lt;/h4&gt;
&lt;p&gt;Inlining stylesheets or scripts is often used to reduce the number of HTTP requests, thus RTT, in web applications. However, inlining makes Web pages less cacheable and increases the size of webpages due to base64 encoding. If you use the SPDY server push feature used to push content, you can avoid these problems.&lt;/p&gt;
&lt;h4&gt;Use request prioritization&lt;/h4&gt;
&lt;p&gt;You can enable the client to inform the server of the relative priority of resources by using the request prioritization feature of SPDY. The simple common heuristic prioritization could be &lt;code&gt;html &amp;gt; js, css &amp;gt; *&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Choose the proper size of a SPDY frame&lt;/h4&gt;
&lt;p&gt;Although SPDY spec allows large frames, sometimes a small frame is more desirable. This is because a small frame allows interleaving to work better.&lt;/p&gt;
&lt;h3&gt;SSL Level&lt;/h3&gt;
&lt;h4&gt;Use a smaller, full certificate chain&lt;/h4&gt;
&lt;p&gt;The size of a certificate chain makes a huge influence on the performance of the initialization of a connection. If there are more certificates in a certificate chain, it will take more time to verify the validity of certificates, and more space will be occupied in &lt;b&gt;initcwnd&lt;/b&gt;.&lt;/p&gt;
&lt;blockquote class=&quot;q4&quot;&gt;
&lt;p&gt;&lt;b&gt;initcwnd:&lt;/b&gt; the initial value used in TCP initial congestion window and TCP congestion control algorithm. The congestion window is a sender-side window to control the size according to TCP congestion control algorithm, which is different from the TCP window, which is a receiver-side limit on the size.&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In addition, if a server does not provide a full certificate chain, the client will use additional RTT to get certificates in the middle. Therefore, if a large, incomplete certificate chain is used, it will take longer time for an application to use the connection.&lt;/p&gt;
&lt;h4&gt;Use a wildcard certificate (e.g., *.naver.com) if possible&lt;/h4&gt;
&lt;p&gt;If you use wildcard certificates, you can reduce the number of connections and use the connection sharing of SPDY. As a wildcard certificate is provided by a certification institute, however, you may need to discuss with the institute and pay extra costs.&lt;/p&gt;
&lt;h4&gt;Do not set the size of SSL write buffer too large&lt;/h4&gt;
&lt;p&gt;If SSL write buffer is too large, TLS application record will be put on multiple packets. As an application can process only after the entire TLS application record is completed, the record put on multiple packets will cause additional latency. Google servers use 2 KB buffers.&lt;/p&gt;
&lt;h3&gt;TCP Level&lt;/h3&gt;
&lt;h4&gt;Set the initcwnd of the server to at least 10&lt;/h4&gt;
&lt;p&gt;&lt;b&gt;Initcwnd&lt;/b&gt; is the main bottleneck that affects the initial loading time of a page. If you use only HTTP, you can avoid this problem by attaining the initial congestion window size of &lt;code&gt;n &amp;times; initcwnd&lt;/code&gt; by opening multiple connections concurrently. As a single connection is advantageous in SPDY, however, it is better to set &lt;b&gt;initcwnd&lt;/b&gt; to a large value from the beginning. This value in old Linux kernels is fixed to 2-3, and the method to adjust this value is not provided. As this value was determined according to the reliability and bandwidth of TCP network when it was first considered, it is not suitable to today&apos;s TCP network with higher stability and bandwidth. The method to adjust this value was added in Linux Kernel 3.0, and the latest Linux kernels already use the default value of 10 or higher.&lt;/p&gt;
&lt;h4&gt;Disable tcp_slow_start_after_idle&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;tcp_slow_start_after_idle&lt;/code&gt; on Linux is set to &lt;b&gt;1&lt;/b&gt;. This causes a congestion window to return to the size of &lt;b&gt;initcwnd&lt;/b&gt; when the connection goes idle, and makes TCP Slow Start restart.&lt;/p&gt;
&lt;blockquote class=&quot;q4&quot;&gt;
&lt;p&gt;&lt;b&gt;TCP Slow Start&lt;/b&gt; is an algorithm that works by sending packets to the congestion window of the initcwnd size and increasing the TCP congestion window up to the maximum value allowed by the network or up to the TCP window of the receiver side. If the initcwnd value is small, it takes more round-trips until the window reaches the maximum size allowed by the network, and as a result, the initial page loading time will increase.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As this will eliminate the advantage of a single connection of SPDY, this setting should be disabled. You can change the setting by using the &lt;b&gt;sysctl&lt;/b&gt; command. It is also advantageous to disable this setting when using HTTP keepalive.&lt;/p&gt;
&lt;h2&gt;If SPDY is Really Introduced &amp;hellip;&lt;/h2&gt;
&lt;p&gt;In conclusion, to actually introduce SPDY, you need to consider a variety of matters and modify applications and servers. You cannot ignore the costs of introducing the protocol, either. For a Web application written for Tomcat, which does not yet support SPDY, you should consider the cost required to change the Web application server, as well as the cost required to implement the server push functionality.&lt;/p&gt;
&lt;p&gt;Except for the costs required to introduce SPDY, &lt;b&gt;what should we take into account first when we introduce SPDY in a real service?&lt;/b&gt; I chose three matters to consider.&lt;/p&gt;
&lt;h3&gt;The service should be the one that already uses HTTPS&lt;/h3&gt;
&lt;p&gt;You cannot get many advantages when introducing SPDY for services using only HTTP. You should pay the costs for introducing SSL as well.&lt;/p&gt;
&lt;h3&gt;You should be able to change the Linux kernel&lt;/h3&gt;
&lt;p&gt;Even CentOS 6.3, the latest version released on July 9, 2012, still uses the kernel 2.6.32. Adjustment of &lt;b&gt;initcwnd&lt;/b&gt; is supported only from the kernel 3.0, and you need to change the kernel if possible because the performance improvement you can get by adjusting &lt;b&gt;initcwnd&lt;/b&gt; is very significant.&lt;/p&gt;
&lt;h3&gt;Consider the ratio of users of SPDY supported browsers&lt;/h3&gt;
&lt;p&gt;In Korea, many users still use IE which does not support SPDY. On mobile devices, iOS does not yet support SPDY, while Android 3.0 or higher supports SPDY. Therefore, until there are sufficient users of SPDY-supported browsers, you should carefully compare the advantages you can get from the performance improvement derived from SPDY with the costs required to introduce the protocol.&lt;/p&gt;
&lt;p&gt;By Sehoon Park, Senior Engineer at Web Platform Development Lab, NHN Corporation.&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="SPDY"/>
            <category term="HTTP"/>
            <category term="HTTPS"/>
            <category term="Protocol"/>
            <category term="Google"/>
            <category term="Facebook"/>
            <category term="performance"/>
            <category term="Web development"/>
            <category term="Server push"/>
            
   </entry>
   <entry>
      <title>Understanding TCP/IP Network Stack &amp; Writing Network Apps</title>
      <id>http://www.cubrid.org/blog/594523</id>
      <published>2013-02-25T16:40:05-08:00</published>
      <updated>2013-02-25T16:56:51-08:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/594523"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/594523#comment"/>
      <author>
         <name>Hyeongyeop Kim</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;We cannot imagine Internet service without TCP/IP. All Internet services we have developed and used at &lt;a href=&quot;/blog/tags/NHN&quot;&gt;NHN&lt;/a&gt; are based on a solid basis, TCP/IP. Understanding how data is transferred via the network will help you to improve performance through tuning, troubleshooting, or introduction to a new technology.&lt;/p&gt;
&lt;p&gt;This article will describe the overall operation scheme of the network stack based on data flow and control flow in Linux OS and the hardware layer.&lt;/p&gt;
&lt;h2&gt;Key Characteristics of TCP/IP&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;How should I design a network protocol to transmit data quickly while keeping the data order without any data loss?&lt;/b&gt; TCP/IP has been designed with this consideration. The following are the key characteristics of TCP/IP required to understand the concept of the stack.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TCP and IP&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Technically, since TCP and IP have different layer structures, it would be correct to describe them separately. However, here we will describe them as one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;1. Connection-oriented&lt;/h4&gt;
&lt;p&gt;First, a connection is made between two endpoints (local and remote) and then data is transferred. Here, the &quot;TCP connection identifier&quot; is a combination of addresses of the two endpoints, having &lt;code&gt;&amp;lt;local IP address, local port number, remote IP address, remote port number&amp;gt;&lt;/code&gt; type.&lt;/p&gt;
&lt;h4&gt;2. Bidirectional Byte Stream&lt;/h4&gt;
&lt;p&gt;Bidirectional data communication is made by using byte stream.&lt;/p&gt;
&lt;h4&gt;3. In-order Delivery&lt;/h4&gt;
&lt;p&gt;A receiver receives data in the order of sending data from a sender. For that, the order of data is required. To mark the order, 32-bit integer data type is used.&lt;/p&gt;
&lt;h4&gt;4. Reliability through ACK&lt;/h4&gt;
&lt;p&gt;When a sender did not receive ACK (acknowledgement) from a receiver after sending data to the receiver, the sender TCP re-sends the data to the receiver. Therefore, the sender TCP buffers unacknowledged data from the receiver.&lt;/p&gt;
&lt;h4&gt;5. Flow Control&lt;/h4&gt;
&lt;p&gt;A sender sends as much data as a receiver can afford. A receiver sends the maximum number of bytes that it can receive (&lt;i&gt;unused buffer size&lt;/i&gt;, &lt;i&gt;receive window&lt;/i&gt;) to the sender. The sender sends as much data as the size of bytes that the receiver&apos;s &lt;i&gt;receive window&lt;/i&gt; allows.&lt;/p&gt;
&lt;h4&gt;6. Congestion Control&lt;/h4&gt;
&lt;p&gt;The &lt;a href=&quot;http://en.wikipedia.org/wiki/Congestion_window&quot;&gt;congestion window&lt;/a&gt; is used separately from the &lt;i&gt;receive window&lt;/i&gt; to prevent network congestion by limiting the volume of data flowing in the network. Like the receive window, the sender sends as much data as the size of bytes that the receiver&apos;s &lt;i&gt;congestion window&lt;/i&gt; allows by using a variety of algorithms such as TCP Vegas, Westwood, BIC, and CUBIC. Different from flow control, congestion control is implemented by the sender only.&lt;/p&gt;
&lt;h2&gt;Data Transmission&lt;/h2&gt;
&lt;p&gt;As indicated by its name, a network stack has many layers. The following &lt;strong&gt;Figure 1&lt;/strong&gt; shows the layer types.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;254&quot; width=&quot;556&quot; alt=&quot;operation_process_by_each_layer_of_tcp_ip.png&quot; src=&quot;/files/attach/images/220547/523/594/operation_process_by_each_layer_of_tcp_ip.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1: Operation Process by Each Layer of TCP/IP Network Stack for Data Transmission.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;There are several layers and the layers are briefly classified into three areas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User area&lt;/li&gt;
&lt;li&gt;Kernel area&lt;/li&gt;
&lt;li&gt;Device area&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Tasks at the user area and the kernel area are performed by the CPU. The &lt;i&gt;user area&lt;/i&gt; and the &lt;i&gt;kernel area&lt;/i&gt; are called &quot;&lt;b&gt;host&lt;/b&gt;&quot; to distinguish them from the device area. Here, the device is the &lt;i&gt;Network Interface Card&lt;/i&gt; (NIC) that sends and receives packets. It is a more accurate term than the commonly used &quot;LAN card&quot;.&lt;/p&gt;
&lt;p&gt;Let&apos;s take a look at the user area. First, the application creates data to send (the &quot;&lt;b&gt;User data&lt;/b&gt;&quot; box in &lt;b&gt;Figure 1&lt;/b&gt;) and then calls the &lt;code&gt;write()&lt;/code&gt; system call to send the data. Assume that the socket (&lt;b&gt;fd&lt;/b&gt; in &lt;b&gt;Figure 1&lt;/b&gt;) has been already created. When the system call is called, the area is switched to the kernel area.&lt;/p&gt;
&lt;p&gt;POSIX-series operating systems including Linux and Unix expose the socket to the application by using a file descriptor. In the POSIX-series operating system, the socket is a kind of a file. The file layer executes a simple examination and calls the socket function by using the socket structure connected to the file structure.&lt;/p&gt;
&lt;p&gt;The kernel socket has two buffers.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;One is the &lt;i&gt;send socket buffer&lt;/i&gt; for sending;&lt;/li&gt;
&lt;li&gt;And the other is the &lt;i&gt;receive socket buffer&lt;/i&gt; for receiving.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When the write system call is called, the data in the user area is copied to the kernel memory and then added to the end of the send socket buffer. This is to send data in order. In the &lt;b&gt;Figure 1&lt;/b&gt;, the light-gray box refers to the data in the socket buffer. Then, TCP is called.&lt;/p&gt;
&lt;p&gt;There is the TCP Control Block (TCB) structure connected to the socket. The TCB includes data required for processing the TCP connection. Data in the TCB are &lt;i&gt;connection state&lt;/i&gt; (&lt;code&gt;LISTEN&lt;/code&gt;, &lt;code&gt;ESTABLISHED&lt;/code&gt;, &lt;code&gt;TIME_WAIT&lt;/code&gt;), &lt;i&gt;receive window&lt;/i&gt;, &lt;i&gt;congestion window&lt;/i&gt;, &lt;i&gt;sequence number&lt;/i&gt;, &lt;i&gt;resending timer&lt;/i&gt;, etc.&lt;/p&gt;
&lt;p&gt;If the current TCP state allows for data transmission, a new TCP segment (in other words, a packet) is created. If data transmission is impossible due to flow control or such a reason, the system call is ended here and then the mode is returned to the user mode (in other words, the control is passed to the application).&lt;/p&gt;
&lt;p&gt;There are two TCP segments as shown in &lt;b&gt;Figure 2&lt;/b&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;TCP header;&lt;/li&gt;
&lt;li&gt;And payload.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; height=&quot;416&quot; width=&quot;575&quot; alt=&quot;tcp_frame_structure.png&quot; src=&quot;/files/attach/images/220547/523/594/tcp_frame_structure.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 2: TCP Frame Structure (&lt;a href=&quot;http://www.skullbox.net/tcpudp.php&quot;&gt;source&lt;/a&gt;).&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The payload includes the data saved in the unacknowledged send socket buffer. The maximum length of the payload is the maximum value among the receive window, congestion window, and maximum segment size (MSS).&lt;/p&gt;
&lt;p&gt;Then, TCP checksum is computed. In this checksum computation, pseudo header information (IP addresses, segment length, and protocol number) is included. One or more packets can be transmitted according to the TCP state.&lt;/p&gt;
&lt;p&gt;In fact, since the current network stack uses the checksum offload, the TCP checksum is computed by NIC, not by the kernel. However, we assume that the kernel computes the TCP checksum for convenience.&lt;/p&gt;
&lt;p&gt;The created TCP segment goes down to the IP layer. The IP layer adds an IP header to the TCP segment and performs IP routing. &lt;b&gt;IP routing&lt;/b&gt; is a procedure of searching the next hop IP in order to go to the destination IP.&lt;/p&gt;
&lt;p&gt;After the IP layer has computed and added the IP header checksum, it sends the data to the Ethernet layer.&amp;nbsp;The Ethernet layer searches for the MAC address of the next hop IP by using the Address Resolution Protocol (ARP). It then adds the Ethernet header to the packet. The host packet is completed by adding the Ethernet header.&lt;/p&gt;
&lt;p&gt;After IP routing is performed, the transmit interface (NIC) is known as the result of IP routing. The interface is used for transmitting a packet to the next hop IP and the IP. Therefore, the transmit NIC driver is called.&lt;/p&gt;
&lt;p&gt;At this time, if a packet capture program such as tcpdump or Wireshark is running, the kernel copies the packet data onto the memory buffer that the program uses. In that way, the receiving packet is directly captured on the driver. Generally, the traffic shaper function is implemented to run on this layer.&lt;/p&gt;
&lt;p&gt;The driver requests packet transmission according to the driver-NIC communication protocol defined by the NIC manufacturer.&lt;/p&gt;
&lt;p&gt;After receiving the packet transmission request, the NIC copies the packets from the main memory to its memory and then sends it to the network line. At this time, by complying with the Ethernet standard, it adds the IFG (Inter-Frame Gap), preamble, and CRC to the packet. The IFG and preamble are used to distinguish the start of the packet (as a networking term, framing), and the CRC is used to protect the data (the same purpose as TCP and IP checksum). Packet transmission is started based on the physical speed of the Ethernet and the condition of Ethernet flow control. It is like getting the floor and speaking in a conference room.&lt;/p&gt;
&lt;p&gt;When an NIC sends a packet, the NIC generates interrupts on the host CPU. Every interrupt has its own interrupt number and the OS searches an adequate driver to handle the interrupt by using the number. The driver registers a function to handle the interrupt (an interrupt handler) when the driver is started. The OS calls the interrupt handler and then the interrupt handler returns the transmitted packet to the OS.&lt;/p&gt;
&lt;p&gt;So far we have discussed the procedure of data transmission through the kernel and the device when an application performs write. However, without a direct write request from the application, the kernel can transmit a packet by directly calling TCP. For example, when an ACK is received and the receive window is expanded, the kernel creates a TCP segment including the data left in the socket buffer and sends the TCP segment to the receiver.&lt;/p&gt;
&lt;h2&gt;Data Receiving&lt;/h2&gt;
&lt;p&gt;Now, let&apos;s take a look at how data is received. Data receiving is a procedure for how the network stack handles a packet coming in. &lt;b&gt;Figure 3&lt;/b&gt; shows how the network stack handles a packet received.&lt;/p&gt;
&lt;p&gt;&lt;img style=&quot;display: block; margin-left: auto; margin-right: auto;&quot; height=&quot;254&quot; width=&quot;556&quot; alt=&quot;operation_process_by_each_layer_of_tcp_ip_for_data_received.png&quot; src=&quot;/files/attach/images/220547/523/594/operation_process_by_each_layer_of_tcp_ip_for_data_received.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 3: Operation Process by Each Layer of TCP/IP Network Stack for Handling Data Received.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;First, the NIC writes the packet onto its memory. It checks whether the packet is valid by performing the CRC check and then sends the packet to the memory buffer of the host. This buffer is a memory that has already been requested by the driver to the kernel and allocated for receiving packets. After the buffer has been allocated, the driver tells the memory address and size to the NIC. When there is no host memory buffer allocated by the driver even though the NIC receives a packet, the NIC may drop the packet.&lt;/p&gt;
&lt;p&gt;After sending the packet to the host memory buffer, the NIC sends an interrupt to the host OS.&lt;/p&gt;
&lt;p&gt;Then, the driver checks whether it can handle the new packet or not. So far, the driver-NIC communication protocol defined by the manufacturer is used.&lt;/p&gt;
&lt;p&gt;When the driver should send a packet to the upper layer, the packet must be wrapped in a packet structure that the OS uses for the OS to understand the packet. For example, &lt;b&gt;sk_buff&lt;/b&gt; of Linux, &lt;b&gt;mbuf&lt;/b&gt; of BSD-series kernel, and &lt;b&gt;NET_BUFFER_LIST&lt;/b&gt; of Microsoft Windows are the packet structures of the corresponding OS. The driver sends the wrapped packets to the upper layer.&lt;/p&gt;
&lt;p&gt;The Ethernet layer checks whether the packet is valid and then de-multiplexes the upper protocol (network protocol). At this time, it uses the ethertype value of the Ethernet header. The IPv4 ethertype value is &lt;b&gt;0x0800&lt;/b&gt;. It removes the Ethernet header and then sends the packet to the IP layer.&lt;/p&gt;
&lt;p&gt;The IP layer also checks whether the packet is valid. In other words, it checks the IP header checksum. It logically determines whether it should perform IP routing and make the local system handle the packet, or send the packet to the other system. If the packet must be handled by the local system, the IP layer de-multiplexes the upper protocol (transport protocol) by referring to the proto value of the IP header. The TCP proto value is 6. It removes the IP header and then sends the packet to the TCP layer.&lt;/p&gt;
&lt;p&gt;Like the lower layer, the TCP layer checks whether the packet is valid. It also checks the TCP checksum. As mentioned before, since the current network stack uses the checksum offload, the TCP checksum is computed by NIC, not by the kernel.&lt;/p&gt;
&lt;p&gt;Then it searches the TCP control block where the packet is connected. At this time, &lt;code&gt;&amp;lt;source IP, source port, target IP, target port&amp;gt;&lt;/code&gt; of the packet is used as an identifier. After searching the connection, it performs the protocol to handle the packet. If it has received new data, it adds the data to the receive socket buffer. According to the TCP state, it can send a new TCP packet (for example, an ACK packet). Now TCP/IP receiving packet handling has completed.&lt;/p&gt;
&lt;p&gt;The size of the receive socket buffer is the TCP receive window. To a certain point, the TCP throughput increases when the receive window is large. In the past, the socket buffer size had been adjusted on the application or the OS configuration. The latest network stack has a function to adjust the receive socket buffer size, i.e., the receive window, automatically.&lt;/p&gt;
&lt;p&gt;When the application calls the read system call, the area is changed to the kernel area and the data in the socket buffer is copied to the memory in the user area. The copied data is removed from the socket buffer. And then the TCP is called. The TCP increases the receive window because there is new space in the socket buffer. And it sends a packet according to the protocol status. If no packet is transferred, the system call is terminated.&lt;/p&gt;
&lt;h2&gt;Network Stack Development Direction&lt;/h2&gt;
&lt;p&gt;The functions of network stack layers described so far are the most basic functions. The network stack in the early 1990s had few more functions than the functions described above. However, the latest network stack has many more functions and complexity as the network stack implementation structure gets higher.&lt;/p&gt;
&lt;p&gt;The latest network stack is classified by purpose as follows.&lt;/p&gt;
&lt;h3&gt;Packet Processing Procedure Manipulation&lt;/h3&gt;
&lt;p&gt;It is a function like Netfilter (firewall, NAT) and traffic control. By inserting the user-controllable code to the basic processing flow, the function can work differently according to the user configuration.&lt;/p&gt;
&lt;h3&gt;Protocol Performance&lt;/h3&gt;
&lt;p&gt;It aims to improve the throughput, latency, and stability that the TCP protocol can achieve within the given network environment. Various congestion control algorithms and additional TCP functions such as SACK are the typical examples. The protocol improvement will not be discussed here since it is out of the scope.&lt;/p&gt;
&lt;h3&gt;Packet Processing Efficiency&lt;/h3&gt;
&lt;p&gt;The packet processing efficiency aims to improve the maximum number of packets that can be processed per second by reducing the CPU cycle, memory usage, and memory accesses that one system consumes to process packets. There have been several attempts to reduce the latency in the system. The attempts include stack parallel processing, header prediction, zero-copy, single-copy, checksum offload, TSO, LRO, RSS, etc.&lt;/p&gt;
&lt;h2&gt;Control Flow in the Stack&lt;/h2&gt;
&lt;p&gt;Now, we will take a more detailed look at the internal flow of the Linux network stack. Like a subsystem which is not a network stack, a network stack basically runs as the event-driven way that reacts when the event occurs. Therefore, there is no separated thread to execute the stack. &lt;b&gt;Figure 1&lt;/b&gt; and &lt;b&gt;Figure 3&lt;/b&gt; showed the simplified diagrams of control flow. &lt;b&gt;Figure 4&lt;/b&gt;&amp;nbsp;below illustrates more exact control flow.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;421&quot; width=&quot;558&quot; alt=&quot;control_flow_in_stack.png&quot; src=&quot;/files/attach/images/220547/523/594/control_flow_in_stack.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 4: Control Flow in the Stack.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;At Flow (1) in Figure 4, an application calls a system call to execute (use) the TCP. For example, calls the read system call and the write system call and then executes TCP. However, there is no packet transmission.&lt;/p&gt;
&lt;p&gt;Flow (2) is same as Flow (1) if it requires packet transmission after executing TCP. It creates a packet and sends down the packet to the driver. A queue is in front of the driver. The packet comes into the queue first, and then the queue implementation structure decides the time to send the packet to the driver. This is queue discipline (&lt;b&gt;qdisc&lt;/b&gt;) of Linux. The function of Linux traffic control is to manipulate the qdisc. The default qdisc is a simple First-In-First-Out (FIFO) queue. By using another qdisc, operators can achieve various effects such as artificial packet loss, packet delay, transmission rate limit, etc. At Flow (1) and Flow (2), the process thread of the application also executes the driver.&lt;/p&gt;
&lt;p&gt;Flow (3) shows the case in which the timer used by the TCP has expired. For example, when the &lt;b&gt;TIME_WAIT&lt;/b&gt; timer has expired, the TCP is called to delete the connection.&lt;/p&gt;
&lt;p&gt;Like Flow (3), Flow (4) is the case in which the timer used by the TCP has expired and the TCP execution result packet should be transmitted. For example, when the retransmit timer has expired, the packet of which ACK has not been received is transmitted.&lt;/p&gt;
&lt;p&gt;Flow (3) and Flow (4) show the procedure of executing the timer softirq that has processed the timer interrupt.&lt;/p&gt;
&lt;p&gt;When the NIC driver receives an interrupt, it frees the transmitted packet. In most cases, execution of the driver is terminated here. Flow (5) is the case of packet accumulation in the transmit queue. The driver requests softirq and the softirq handler executes the transmit queue to send the accumulated packet to the driver.&lt;/p&gt;
&lt;p&gt;When the NIC driver receives an interrupt and finds a newly received packet, it requests softirq. The softirq that processes the received packet calls the driver and transmits the received packet to the upper layer. In Linux, processing the received packet as shown above is called New API (NAPI). It is similar to polling because the driver does not directly transmit the packet to the upper layer, but the upper layer directly gets the packet. The actual code is called NAPI poll or poll.&lt;/p&gt;
&lt;p&gt;Flow (6) shows the case that completes execution of TCP, and Flow (7) shows the case that requires additional packet transmission. All of Flow (5), (6), and (7) are executed by the softirq which has processed the NIC interrupt.&lt;/p&gt;
&lt;h2&gt;How to Process Interrupt and Received Packet&lt;/h2&gt;
&lt;p&gt;Interrupt processing is complex; however, you need to understand the performance issue related to processing of packets received. Figure 5 shows the procedure of processing an interrupt.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;314&quot; width=&quot;539&quot; alt=&quot;processing_interrupt_softirq_and_received_packet.png&quot; src=&quot;/files/attach/images/220547/523/594/processing_interrupt_softirq_and_received_packet.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 5: Processing Interrupt, softirq, and Received Packet.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Assume that the CPU 0 is executing an application program (user program). At this time, the NIC receives a packet and generates an interrupt for the CPU 0. Then the CPU executes the kernel interrupt (called irq) handler. This handler refers to the interrupt number and then calls the driver interrupt handler. The driver frees the packet transmitted and then calls the &lt;code&gt;napi_schedule()&lt;/code&gt; function to process the received packet. This function requests the softirq (software interrupt).&lt;/p&gt;
&lt;p&gt;After execution of the driver interrupt handler has been terminated, the control is passed to the kernel handler. The kernel handler executes the interrupt handler for the softirq.&lt;/p&gt;
&lt;p&gt;After the interrupt context has been executed, the softirq context will be executed. The interrupt context and the softirq context are executed by an identical thread. However, they use different stacks. And, the interrupt context blocks hardware interrupts; however, the softirq context allows for hardware interrupts.&lt;/p&gt;
&lt;p&gt;The softirq handler that processes the received packet is the &lt;code&gt;net_rx_action()&lt;/code&gt; function. This function calls the &lt;code&gt;poll()&lt;/code&gt; function of the driver. The &lt;code&gt;poll()&lt;/code&gt; function calls the &lt;code&gt;netif_receive_skb()&lt;/code&gt; function and then sends the received packets one by one to the upper layer. After processing the softirq, the application restarts execution from the stopped point in order to request a system call.&lt;/p&gt;
&lt;p&gt;Therefore, the CPU that has received the interrupt processes the received packets from the first to the last. In Linux, BSD, and Microsoft Windows, the processing procedure is basically the same on this wise.&lt;/p&gt;
&lt;p&gt;When you check the server CPU utilization, sometimes you can check that only one CPU executes the softirq hard among the server CPUs. The phenomenon occurs due to the way of processing received packets explained so far. To solve the problem, multi-queue NIC, RSS, and RPS have been developed.&lt;/p&gt;
&lt;h2&gt;Data Structure&lt;/h2&gt;
&lt;p&gt;The followings are some key data structures. Take a look at them and review the code.&lt;/p&gt;
&lt;h3&gt;sk_buff structure&lt;/h3&gt;
&lt;p&gt;First, there is the &lt;b&gt;sk_buff&lt;/b&gt; structure or &lt;b&gt;skb&lt;/b&gt; structure that means a packet. &lt;b&gt;Figure 6&lt;/b&gt; shows some of the &lt;b&gt;sk_buff&lt;/b&gt; structure. As the functions have been advanced, they get more complicated. However, the basic functions are very common that anyone can think.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;354&quot; width=&quot;548&quot; alt=&quot;packet_structure_sk_buff.png&quot; src=&quot;/files/attach/images/220547/523/594/packet_structure_sk_buff.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 6: Packet Structure sk_buff.&lt;/b&gt;&lt;/p&gt;
&lt;h3&gt;Including Packet Data and &lt;i&gt;meta data&lt;/i&gt;&lt;/h3&gt;
&lt;p&gt;The structure directly includes the packet data or refers to it by using a pointer. In &lt;b&gt;Figure 6&lt;/b&gt;, some of the packets (from Ethernet to buffer) refer to using the data pointer and the additional data (frags) refer to the actual page.&lt;/p&gt;
&lt;p&gt;The necessary information such as header and payload length is saved in the meta data area. For example, in &lt;b&gt;Figure 6&lt;/b&gt;, the mac_header, the network_header, and the transport_header have the corresponding pointer data that points the starting position of the Ethernet header, IP header and TCP header, respectively. This way makes TCP protocol processing easy.&lt;/p&gt;
&lt;h3&gt;How to Add or Delete a Header&lt;/h3&gt;
&lt;p&gt;The header is added or deleted as up and down each layer of the network stack. Pointers are used for more efficient processing. For example, to remove the Ethernet header, just increase the head pointer.&lt;/p&gt;
&lt;h3&gt;How to Combine and Divide Packet&lt;/h3&gt;
&lt;p&gt;The linked list is used for efficient execution of tasks such as adding or deleting packet payload data to the socket buffer, or packet chain. The next pointer and the prev pointer are used for this purpose.&lt;/p&gt;
&lt;h3&gt;Quick Allocation and Free&lt;/h3&gt;
&lt;p&gt;As a structure is allocated whenever creating a packet, the quick allocator is used. For example, if data is transmitted at the speed of 10-Gigabit Ethernet, more than one million packets per second must be created and deleted.&lt;/p&gt;
&lt;h2&gt;TCP Control Block&lt;/h2&gt;
&lt;p&gt;Second, there is a structure that represents the TCP connection. Previously, it was abstractly called a TCP control block. Linux uses tcp_sock for the structure. In &lt;b&gt;Figure 7&lt;/b&gt;, you can see the relationship among the file, the socket, and the &lt;b&gt;tcp_sock&lt;/b&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;360&quot; width=&quot;522&quot; alt=&quot;tcp_connection_structure.png&quot; src=&quot;/files/attach/images/220547/523/594/tcp_connection_structure.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 7: TCP Connection Structure.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;When a system call has occurred, it searches the file in the file descriptor used by the application that has called the system call. For the Unix-series OS, the socket, the file and the device for general file system for storage are abstracted to a file. Therefore, the file structure includes the least information. For a socket, a separate socket structure saves the socket-related information and the file refers to the socket as a pointer. The socket refers to the &lt;b&gt;tcp_sock&lt;/b&gt; again. The &lt;b&gt;tcp_sock&lt;/b&gt; is classified into sock, inet_sock, etc to support various protocols except TCP. It may be considered as a kind of polymorphism.&lt;/p&gt;
&lt;p&gt;All status information used by the TCP protocol is saved in the tcp_sock. For example, the sequence number, receive window, congestion control, and retransmit timer are saved in the &lt;b&gt;tcp_sock&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;The send socket buffer and the receive socket buffer are the &lt;b&gt;sk_buff&lt;/b&gt; lists and they include the &lt;b&gt;tcp_sock&lt;/b&gt;. The dst_entry, the IP routing result, is referred to in order to avoid too frequent routing. The dst_entry allows for easy search of the ARP result, i.e., the destination MAC address. The dst_entry is part of the routing table. The structure of the routing table is very complex that it will not be discussed in this document. The NIC to be used for packet transmission is searched by using the &lt;b&gt;dst_entry&lt;/b&gt;. The NIC is expressed as the net_device structure.&lt;/p&gt;
&lt;p&gt;Therefore, by searching just the file, it is very easy to find all structures (from the file to the driver) required to process the TCP connection with the pointer. The size of the structures is the memory size used by one TCP connection. The memory size is a few KBs (excluding the packet data). As more functions have been added, the memory usage has been gradually increased.&lt;/p&gt;
&lt;p&gt;Finally, let&apos;s see the TCP connection lookup table. It is a hash table used to search the TCP connection where the received packet belongs. The hash value is calculated by using the input data of &lt;code&gt;&amp;lt;source IP, target IP, source port, target port&amp;gt;&lt;/code&gt; of the packet and the Jenkins hash algorithm. It is told that the hash function has been selected by considering defense against attacks to the hash table.&lt;/p&gt;
&lt;h2&gt;Following Code: How to Transmit Data&lt;/h2&gt;
&lt;p&gt;We will check the key tasks performed by the stack by following the actual Linux kernel source code. Here, we will observe two paths which are frequently used.&lt;/p&gt;
&lt;p&gt;First, this is a path used to transmit data when an application calls the write system call.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf, ...)

{

struct file *file;

[...]

file = fget_light(fd, &amp;amp;fput_needed);

[...] ===&amp;gt;

ret = filp-&amp;gt;f_op-&amp;gt;aio_write(&amp;amp;kiocb, &amp;amp;iov, 1, kiocb.ki_pos);



struct file_operations {

[...]

ssize_t (*aio_read) (struct kiocb *, const struct iovec *, ...)

ssize_t (*aio_write) (struct kiocb *, const struct iovec *, ...)

[...]

};



static const struct file_operations socket_file_ops = {

[...]

.aio_read = sock_aio_read,

.aio_write = sock_aio_write,

[...]

};&lt;/pre&gt;
&lt;p&gt;When the application calls the write system call, the kernel performs the &lt;code&gt;write()&lt;/code&gt; function of the file layer. First, the actual file structure of the file descriptor fd is fetched. And then the &lt;b&gt;aio_write&lt;/b&gt; is called. This is the function pointer. In the file structure, you will see the &lt;b&gt;file_operations&lt;/b&gt; structure pointer. The structure is generally called function table and includes the function pointers such as aio_read and &lt;b&gt;aio_write&lt;/b&gt;. The actual table for the socket is socket_file_ops. The aio_write function used by the socket is sock_aio_write. The function table is used for the purpose that is similar to the Java interface. It is generally used for the kernel to perform code abstraction or refactoring.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, ..)

{

[...]

struct socket *sock = file-&amp;gt;private_data;

[...] ===&amp;gt;

return sock-&amp;gt;ops-&amp;gt;sendmsg(iocb, sock, msg, size);



struct socket {

[...]

struct file *file;

struct sock *sk;

const struct proto_ops *ops;

};



const struct proto_ops inet_stream_ops = {

.family = PF_INET,

[...]

.connect = inet_stream_connect,

.accept = inet_accept,

.listen = inet_listen, .sendmsg = tcp_sendmsg,

.recvmsg = inet_recvmsg,

[...]

};



struct proto_ops {

[...]

int (*connect) (struct socket *sock, ...)

int (*accept) (struct socket *sock, ...)

int (*listen) (struct socket *sock, int len);

int (*sendmsg) (struct kiocb *iocb, struct socket *sock, ...)

int (*recvmsg) (struct kiocb *iocb, struct socket *sock, ...)

[...]

};&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;sock_aio_write()&lt;/code&gt; function gets the socket structure from the file and then calls &lt;b&gt;sendmsg&lt;/b&gt;. It is also the function pointer. The socket structure includes the &lt;b&gt;proto_ops&lt;/b&gt; function table. The proto_ops implemented by the IPv4 TCP is inet_stream_ops and the sendmsg is implemented by &lt;b&gt;tcp_sendmsg&lt;/b&gt;.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;int tcp_sendmsg(struct kiocb *iocb, struct socket *sock,

struct msghdr *msg, size_t size)

{

struct sock *sk = sock-&amp;gt;sk;

struct iovec *iov;

struct tcp_sock *tp = tcp_sk(sk);

struct sk_buff *skb;

[...]

mss_now = tcp_send_mss(sk, &amp;amp;size_goal, flags);



/* Ok commence sending. */

iovlen = msg-&amp;gt;msg_iovlen;

iov = msg-&amp;gt;msg_iov;

copied = 0;

[...]

while (--iovlen &amp;gt;= 0) {

int seglen = iov-&amp;gt;iov_len;

unsigned char __user *from = iov-&amp;gt;iov_base;



iov++;

while (seglen &amp;gt; 0) {

int copy = 0;

int max = size_goal;

[...]

skb = sk_stream_alloc_skb(sk,

select_size(sk, sg),

sk-&amp;gt;sk_allocation);

if (!skb)

goto wait_for_memory;

/*

* Check whether we can use HW checksum.

*/

if (sk-&amp;gt;sk_route_caps &amp;amp; NETIF_F_ALL_CSUM)

skb-&amp;gt;ip_summed = CHECKSUM_PARTIAL;

[...]

skb_entail(sk, skb);

[...]

/* Where to copy to? */

if (skb_tailroom(skb) &amp;gt; 0) {

/* We have some space in skb head. Superb! */

if (copy &amp;gt; skb_tailroom(skb))

copy = skb_tailroom(skb);

if ((err = skb_add_data(skb, from, copy)) != 0)

goto do_fault;

[...]

if (copied)

tcp_push(sk, flags, mss_now, tp-&amp;gt;nonagle);

[...]

}&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;tcp_sengmsg&lt;/b&gt; gets tcp_sock (i.e.,TCP control block) from the socket and copies the data that the application has requested to transmit to the send socket buffer. When copying data to sk_buff, how many bytes will one sk_buff include? One sk_buff copies and includes MSS (tcp_send_mss) bytes to help the code that actually creates packets. Maximum Segment Size (MSS) stands for the maximum payload size that one TCP packet includes. By using TSO and GSO, one sk_buff can save more data than MSS. This will be discussed later, not in this document.&lt;/p&gt;
&lt;p&gt;The &lt;b&gt;sk_stream_alloc_skb&lt;/b&gt; function creates a new &lt;b&gt;sk_buff&lt;/b&gt;, and &lt;b&gt;skb_entail&lt;/b&gt; adds the new &lt;b&gt;sk_buff&lt;/b&gt; to the tail of the &lt;b&gt;send_socket_buffer&lt;/b&gt;. The &lt;b&gt;skb_add_data&lt;/b&gt; function copies the actual application data to the data buffer of the &lt;b&gt;sk_buff&lt;/b&gt;. All the data is copied by repeating the procedure (creating an &lt;b&gt;sk_buff&lt;/b&gt; and adding it to the send socket buffer) several times. Therefore, &lt;b&gt;sk_buffs&lt;/b&gt; at the size of the MSS are in the send socket buffer as a list. Finally, the &lt;b&gt;tcp_push&lt;/b&gt; is called to make the data which can be transmitted now as a packet, and the packet is sent.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;static inline void tcp_push(struct sock *sk, int flags, int mss_now, ...)

[...] ===&amp;gt;

static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, ...)

int nonagle,

{

struct tcp_sock *tp = tcp_sk(sk);

struct sk_buff *skb;

[...]

while ((skb = tcp_send_head(sk))) {

[...]

cwnd_quota = tcp_cwnd_test(tp, skb);

if (!cwnd_quota)

break;



if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now)))

break;

[...]

if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))

break;



/* Advance the send_head. This one is sent out.

* This call will increment packets_out.

*/

tcp_event_new_data_sent(sk, skb);

[...]&lt;/pre&gt;
&lt;p&gt;The &lt;b&gt;tcp_push&lt;/b&gt; function transmits as many of the &lt;b&gt;sk_buffs&lt;/b&gt; in the send socket buffer as the TCP allows in sequence. First, the &lt;b&gt;tcp_send_head&lt;/b&gt; is called to get the first &lt;b&gt;sk_buff&lt;/b&gt; in the socket buffer and the &lt;b&gt;tcp_cwnd_test&lt;/b&gt; and the &lt;b&gt;tcp_snd_wnd_test&lt;/b&gt; are performed to check whether the congestion window and the receive window of the receiving TCP allow new packets to be transmitted. Then, the &lt;b&gt;tcp_transmit_skb&lt;/b&gt; function is called to create a packet.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,

int clone_it, gfp_t gfp_mask)

{

const struct inet_connection_sock *icsk = inet_csk(sk);

struct inet_sock *inet;

struct tcp_sock *tp;

[...]





if (likely(clone_it)) {

if (unlikely(skb_cloned(skb)))

skb = pskb_copy(skb, gfp_mask);

else

skb = skb_clone(skb, gfp_mask);

if (unlikely(!skb))

return -ENOBUFS;

}



[...]

skb_push(skb, tcp_header_size);

skb_reset_transport_header(skb);

skb_set_owner_w(skb, sk);



/* Build TCP header and checksum it. */

th = tcp_hdr(skb);

th-&amp;gt;source = inet-&amp;gt;inet_sport;

th-&amp;gt;dest = inet-&amp;gt;inet_dport;

th-&amp;gt;seq = htonl(tcb-&amp;gt;seq);

th-&amp;gt;ack_seq = htonl(tp-&amp;gt;rcv_nxt);

[...]

icsk-&amp;gt;icsk_af_ops-&amp;gt;send_check(sk, skb);

[...]

err = icsk-&amp;gt;icsk_af_ops-&amp;gt;queue_xmit(skb);

if (likely(err &amp;lt;= 0))

return err;



tcp_enter_cwr(sk, 1);



return net_xmit_eval(err);

}&lt;/pre&gt;
&lt;p&gt;&lt;b&gt;tcp_transmit_skb&lt;/b&gt; creates the copy of the given &lt;b&gt;sk_buff&lt;/b&gt; (pskb_copy). At this time, it does not copy the entire data of the application but the metadata. And then it calls &lt;b&gt;skb_push&lt;/b&gt; to secure the header area and records the header field value. Send_check computes the TCP checksum. With the checksum offload, the payload data is not computed. Finally, &lt;b&gt;queue_xmit&lt;/b&gt; is called to send the packet to the IP layer. Queue_xmit for IPv4 is implemented by the &lt;b&gt;ip_queue_xmit&lt;/b&gt; function.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;int ip_queue_xmit(struct sk_buff *skb)

[...]

rt = (struct rtable *)__sk_dst_check(sk, 0);

[...]

/* OK, we know where to send it, allocate and build IP header. */

skb_push(skb, sizeof(struct iphdr) + (opt ? opt-&amp;gt;optlen : 0));

skb_reset_network_header(skb);

iph = ip_hdr(skb);

*((__be16 *)iph) = htons((4 &amp;lt;&amp;lt; 12) | (5 &amp;lt;&amp;lt; 8) | (inet-&amp;gt;tos &amp;amp; 0xff));

if (ip_dont_fragment(sk, &amp;amp;rt-&amp;gt;dst) &amp;amp;&amp;amp; !skb-&amp;gt;local_df)

iph-&amp;gt;frag_off = htons(IP_DF);

else

iph-&amp;gt;frag_off = 0;

iph-&amp;gt;ttl = ip_select_ttl(inet, &amp;amp;rt-&amp;gt;dst);

iph-&amp;gt;protocol = sk-&amp;gt;sk_protocol;

iph-&amp;gt;saddr = rt-&amp;gt;rt_src;

iph-&amp;gt;daddr = rt-&amp;gt;rt_dst;

[...]

res = ip_local_out(skb);

[...] ===&amp;gt;

int __ip_local_out(struct sk_buff *skb)

[...]

ip_send_check(iph);

return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL,

skb_dst(skb)-&amp;gt;dev, dst_output);

[...] ===&amp;gt;

int ip_output(struct sk_buff *skb)

{

struct net_device *dev = skb_dst(skb)-&amp;gt;dev;

[...]

skb-&amp;gt;dev = dev;

skb-&amp;gt;protocol = htons(ETH_P_IP);



return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, dev,

ip_finish_output,

[...] ===&amp;gt;

static int ip_finish_output(struct sk_buff *skb)

[...]

if (skb-&amp;gt;len &amp;gt; ip_skb_dst_mtu(skb) &amp;amp;&amp;amp; !skb_is_gso(skb))

return ip_fragment(skb, ip_finish_output2);

else

return ip_finish_output2(skb);&lt;/pre&gt;
&lt;p&gt;The &lt;b&gt;ip_queue_xmit&lt;/b&gt; function executes tasks required by the IP layers. &lt;b&gt;__sk_dst_check&lt;/b&gt; checks whether the cached route is valid. If there is no cached route or the cached route is invalid, it performs IP routing. And then it calls skb_push to secure the IP header area and records the IP header field value. After that, as following the function call, &lt;b&gt;ip_send_check&lt;/b&gt; computes the IP header checksum and calls the netfilter function. IP fragment is created when &lt;b&gt;ip_finish_output&lt;/b&gt; function needs IP fragmentation. No fragmentation is generated when TCP is used. Therefore, ip_finish_output2 is called and it adds the Ethernet header. Finally, a packet is completed.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;int dev_queue_xmit(struct sk_buff *skb)

[...] ===&amp;gt;

static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, ...)

[...]

if (...) {

....

} else

if ((q-&amp;gt;flags &amp;amp; TCQ_F_CAN_BYPASS) &amp;amp;&amp;amp; !qdisc_qlen(q) &amp;amp;&amp;amp;



qdisc_run_begin(q)) {

[...]

if (sch_direct_xmit(skb, q, dev, txq, root_lock)) {

[...] ===&amp;gt;

int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, ...)

[...]

HARD_TX_LOCK(dev, txq, smp_processor_id());

if (!netif_tx_queue_frozen_or_stopped(txq))

ret = dev_hard_start_xmit(skb, dev, txq);



HARD_TX_UNLOCK(dev, txq);

[...]

}



int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, ...)

[...]

if (!list_empty(&amp;amp;ptype_all))

dev_queue_xmit_nit(skb, dev);

[...]

rc = ops-&amp;gt;ndo_start_xmit(skb, dev);

[...]

}&lt;/pre&gt;
&lt;p&gt;The completed packet is transmitted through the &lt;b&gt;dev_queue_xmit&lt;/b&gt; function. First, the packet passes via the qdisc. If the default qdisc is used and the queue is empty, the &lt;b&gt;sch_direct_xmit&lt;/b&gt; function is called to directly send down the packet to the driver, skipping the queue. &lt;b&gt;Dev_hard_start_xmit&lt;/b&gt; function calls the actual driver. Before calling the driver, the device TX is locked first. This is to prevent several threads from accessing the device simultaneously. As the kernel locks the device TX, the driver transmission code does not need an additional lock. It is closely related to the parallel processing that will be discussed next time.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ndo_start_xmit&lt;/b&gt; function calls the driver code. Just before, you will see &lt;b&gt;ptype_all&lt;/b&gt; and &lt;b&gt;dev_queue_xmit_nit&lt;/b&gt;. The ptype_all is a list that includes the modules such as packet capture. If a capture program is running, the packet is copied by ptype_all to the separate program. Therefore, the packet that tcpdump shows is the packet transmitted to the driver. When checksum offload or TSO is used, the NIC manipulates the packet. So the tcpdump packet is different from the packet transmitted to the network line. After completing packet transmission, the driver interrupt handler returns the &lt;b&gt;sk_buff&lt;/b&gt;.&lt;/p&gt;
&lt;h2&gt;Following Code: How to Receive Data&lt;/h2&gt;
&lt;p&gt;The general executed path is to receive a packet and then to add the data to the receive socket buffer. After executing the driver interrupt handler, follow the napi poll handle first.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;static void net_rx_action(struct softirq_action *h)

{

struct softnet_data *sd = &amp;amp;__get_cpu_var(softnet_data);

unsigned long time_limit = jiffies + 2;

int budget = netdev_budget;

void *have;



local_irq_disable();



while (!list_empty(&amp;amp;sd-&amp;gt;poll_list)) {

struct napi_struct *n;

[...]

n = list_first_entry(&amp;amp;sd-&amp;gt;poll_list, struct napi_struct,

poll_list);

if (test_bit(NAPI_STATE_SCHED, &amp;amp;n-&amp;gt;state)) {

work = n-&amp;gt;poll(n, weight);

trace_napi_poll(n);

}

[...]

}



int netif_receive_skb(struct sk_buff *skb)

[...] ===&amp;gt;

static int __netif_receive_skb(struct sk_buff *skb)

{

struct packet_type *ptype, *pt_prev;

[...]

__be16 type;

[...]

list_for_each_entry_rcu(ptype, &amp;amp;ptype_all, list) {

if (!ptype-&amp;gt;dev || ptype-&amp;gt;dev == skb-&amp;gt;dev) {

if (pt_prev)

ret = deliver_skb(skb, pt_prev, orig_dev);

pt_prev = ptype;

}

}

[...]

type = skb-&amp;gt;protocol;

list_for_each_entry_rcu(ptype,

&amp;amp;ptype_base[ntohs(type) &amp;amp; PTYPE_HASH_MASK], list) {

if (ptype-&amp;gt;type == type &amp;amp;&amp;amp;



(ptype-&amp;gt;dev == null_or_dev || ptype-&amp;gt;dev == skb-&amp;gt;dev ||

ptype-&amp;gt;dev == orig_dev)) {

if (pt_prev)

ret = deliver_skb(skb, pt_prev, orig_dev);

pt_prev = ptype;

}

}



if (pt_prev) {

ret = pt_prev-&amp;gt;func(skb, skb-&amp;gt;dev, pt_prev, orig_dev);



static struct packet_type ip_packet_type __read_mostly = {

.type = cpu_to_be16(ETH_P_IP),

.func = ip_rcv,

[...]

};&lt;/pre&gt;
&lt;p&gt;As mentioned before, the net_rx_action function is the softirq handler that receives a packet. First, the driver that has requested the napi poll is retrieved from the &lt;b&gt;poll_list&lt;/b&gt; and the poll handler of the driver is called. The driver wraps the received packet with sk_buff and then calls &lt;b&gt;netif_receive_skb&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;When there is a module that requests all packets, the &lt;b&gt;netif_receive_skb&lt;/b&gt; sends packets to the module. Like packet transmission, the packets are transmitted to the module registered to the ptype_all list. The packets are captured here.&lt;/p&gt;
&lt;p&gt;Then, the packets are transmitted to the upper layer based on the packet type. The Ethernet packet includes 2-byte ethertype field in the header. The value indicates the packet type. The driver records the value in &lt;b&gt;sk_buff&lt;/b&gt; (skb-&amp;gt;protocol). Each protocol has its own packet_type structure and registers the pointer of the structure to the ptype_base hash table. IPv4 uses &lt;b&gt;ip_packet_type&lt;/b&gt;. The Type field value is the IPv4 ethertype (&lt;b&gt;ETH_P_IP&lt;/b&gt;) value. Therefore, the IPv4 packet calls the &lt;b&gt;ip_rcv&lt;/b&gt; function.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;int ip_rcv(struct sk_buff *skb, struct net_device *dev, ...)

{

struct iphdr *iph;

u32 len;

[...]

iph = ip_hdr(skb);

[...]

if (iph-&amp;gt;ihl &amp;lt; 5 || iph-&amp;gt;version != 4)

goto inhdr_error;



if (!pskb_may_pull(skb, iph-&amp;gt;ihl*4))

goto inhdr_error;



iph = ip_hdr(skb);



if (unlikely(ip_fast_csum((u8 *)iph, iph-&amp;gt;ihl)))

goto inhdr_error;



len = ntohs(iph-&amp;gt;tot_len);

if (skb-&amp;gt;len &amp;lt; len) {

IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS);

goto drop;

} else if (len &amp;lt; (iph-&amp;gt;ihl*4))

goto inhdr_error;

[...]

return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL,

ip_rcv_finish);

[...] ===&amp;gt;

int ip_local_deliver(struct sk_buff *skb)

[...]

if (ip_hdr(skb)-&amp;gt;frag_off &amp;amp; htons(IP_MF | IP_OFFSET)) {

if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))

return 0;

}



return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, skb, skb-&amp;gt;dev, NULL,

ip_local_deliver_finish);

[...] ===&amp;gt;





static int ip_local_deliver_finish(struct sk_buff *skb)

[...]

__skb_pull(skb, ip_hdrlen(skb));

[...]

int protocol = ip_hdr(skb)-&amp;gt;protocol;

int hash, raw;

const struct net_protocol *ipprot;

[...]

hash = protocol &amp;amp; (MAX_INET_PROTOS - 1);

ipprot = rcu_dereference(inet_protos[hash]);

if (ipprot != NULL) {

[...]

ret = ipprot-&amp;gt;handler(skb);

[...] ===&amp;gt;



static const struct net_protocol tcp_protocol = {

.handler = tcp_v4_rcv,

[...]

};&lt;/pre&gt;
&lt;p&gt;The &lt;b&gt;ip_rcv&lt;/b&gt; function executes tasks required by the IP layers. It examines packets such as the length and header checksum. After passing through the netfilter code, it performs the &lt;b&gt;ip_local_deliver&lt;/b&gt; function. If required, it assembles IP fragments. Then, it calls &lt;b&gt;ip_local_deliver_finish&lt;/b&gt; through the netfilter code. The &lt;b&gt;ip_local_deliver_finish&lt;/b&gt; function removes the IP header by using the __skb_pull and then searches the upper protocol whose value is identical to the IP header protocol value. Similar to the Ptype_base, each transport protocol registers its own &lt;b&gt;net_protocol&lt;/b&gt; structure in &lt;b&gt;inet_protos&lt;/b&gt;. IPv4 TCP uses &lt;b&gt;tcp_protocol&lt;/b&gt; and calls &lt;b&gt;tcp_v4_rcv&lt;/b&gt; that has been registered as a handler.&lt;/p&gt;
&lt;p&gt;When packets come into the TCP layer, the packet processing flow varies depending on the TCP status and the packet type. Here, we will see the packet processing procedure when the expected next data packet has been received in the &lt;b&gt;ESTABLISHED&lt;/b&gt; status of the TCP connection. This path is frequently executed by the server receiving data when there is no packet loss or out-of-order delivery.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;int tcp_v4_rcv(struct sk_buff *skb)

{

const struct iphdr *iph;

struct tcphdr *th;

struct sock *sk;

[...]

th = tcp_hdr(skb);



if (th-&amp;gt;doff &amp;lt; sizeof(struct tcphdr) / 4)

goto bad_packet;

if (!pskb_may_pull(skb, th-&amp;gt;doff * 4))

goto discard_it;

[...]

th = tcp_hdr(skb);

iph = ip_hdr(skb);

TCP_SKB_CB(skb)-&amp;gt;seq = ntohl(th-&amp;gt;seq);

TCP_SKB_CB(skb)-&amp;gt;end_seq = (TCP_SKB_CB(skb)-&amp;gt;seq + th-&amp;gt;syn + th-&amp;gt;fin +

skb-&amp;gt;len - th-&amp;gt;doff * 4);

TCP_SKB_CB(skb)-&amp;gt;ack_seq = ntohl(th-&amp;gt;ack_seq);

TCP_SKB_CB(skb)-&amp;gt;when = 0;

TCP_SKB_CB(skb)-&amp;gt;flags = iph-&amp;gt;tos;

TCP_SKB_CB(skb)-&amp;gt;sacked = 0;



sk = __inet_lookup_skb(&amp;amp;tcp_hashinfo, skb, th-&amp;gt;source, th-&amp;gt;dest);

[...]

ret = tcp_v4_do_rcv(sk, skb);&lt;/pre&gt;
&lt;p&gt;First, the &lt;b&gt;tcp_v4_rcv&lt;/b&gt; function validates the received packets. When the header size is larger than the data offset (&lt;code&gt;th-&amp;gt;doff &amp;lt; sizeof(struct tcphdr) / 4&lt;/code&gt;), it is the header error. And then &lt;b&gt;__inet_lookup_skb&lt;/b&gt; is called to look for the connection where the packet belongs from the TCP connection hash table. From the sock structure found, all required structures such as &lt;b&gt;tcp_sock&lt;/b&gt; and socket can be got.&lt;/p&gt;
&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)

[...]

if (sk-&amp;gt;sk_state == TCP_ESTABLISHED) { /* Fast path */

sock_rps_save_rxhash(sk, skb-&amp;gt;rxhash);

if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb-&amp;gt;len)) {

[...] ===&amp;gt;

int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,

[...]

/*

* Header prediction.

*/

if ((tcp_flag_word(th) &amp;amp; TCP_HP_BITS) == tp-&amp;gt;pred_flags &amp;amp;&amp;amp;



TCP_SKB_CB(skb)-&amp;gt;seq == tp-&amp;gt;rcv_nxt &amp;amp;&amp;amp;



!after(TCP_SKB_CB(skb)-&amp;gt;ack_seq, tp-&amp;gt;snd_nxt))) {

[...]

if ((int)skb-&amp;gt;truesize &amp;gt; sk-&amp;gt;sk_forward_alloc)

goto step5;



NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS);



/* Bulk data transfer: receiver */

__skb_pull(skb, tcp_header_len);

__skb_queue_tail(&amp;amp;sk-&amp;gt;sk_receive_queue, skb);

skb_set_owner_r(skb, sk);

tp-&amp;gt;rcv_nxt = TCP_SKB_CB(skb)-&amp;gt;end_seq;

[...]

if (!copied_early || tp-&amp;gt;rcv_nxt != tp-&amp;gt;rcv_wup)

__tcp_ack_snd_check(sk, 0);

[...]

step5:

if (th-&amp;gt;ack &amp;amp;&amp;amp; tcp_ack(sk, skb, FLAG_SLOWPATH) &amp;lt; 0)

goto discard;



tcp_rcv_rtt_measure_ts(sk, skb);



/* Process urgent data. */

tcp_urg(sk, skb, th);



/* step 7: process the segment text */

tcp_data_queue(sk, skb);



tcp_data_snd_check(sk);

tcp_ack_snd_check(sk);

return 0;

[...]

}&lt;/pre&gt;
&lt;p&gt;The actual protocol is executed from the &lt;b&gt;tcp_v4_do_rcv&lt;/b&gt; function. If the TCP is in the ESTABLISHED status, &lt;b&gt;tcp_rcv_esablished&lt;/b&gt; is called. Processing of the &lt;b&gt;ESTABLISHED&lt;/b&gt; status is separately handled and optimized since it is the most common status. The &lt;b&gt;tcp_rcv_established&lt;/b&gt; first executes the header prediction code. The header prediction is also quickly processed to detect in the common state. The common case here is that there is no data to transmit and the received data packet is the packet that must be received next time, i.e., the sequence number is the sequence number that the receiving TCP expects. In this case, the procedure is completed by adding the data to the socket buffer and then transmitting ACK.&lt;/p&gt;
&lt;p&gt;Go forward and you will see the sentence comparing truesize with sk_forward_alloc. It is to check whether there is any free space in the receive socket buffer to add new packet data. If there is, header prediction is &quot;hit&quot; (prediction succeeded). Then &lt;b&gt;__skb_pull&lt;/b&gt; is called to remove the TCP header. After that, &lt;b&gt;__skb_queue_tail&lt;/b&gt; is called to add the packet to the receive socket buffer. Finally, &lt;b&gt;__tcp_ack_snd_check&lt;/b&gt; is called for transmitting ACK if necessary. In this way, packet processing is completed.&lt;/p&gt;
&lt;p&gt;If there is not enough free space, a slow path is executed. The tcp_data_queue function newly allocates the buffer space and adds the data packet to the socket buffer. At this time, the receive socket buffer size is automatically increased if possible. Different from the quick path, &lt;b&gt;tcp_data_snd_check&lt;/b&gt; is called to transmit a new data packet if possible. Finally, &lt;b&gt;tcp_ack_snd_check&lt;/b&gt; is called to create and transmit the ACK packet if necessary.&lt;/p&gt;
&lt;p&gt;The amount of code executed by the two paths is not much. This is accomplished by optimizing the common case. In other words, it means that the uncommon case will be processed significantly more slowly. The out-of-order delivery is one of the uncommon cases.&lt;/p&gt;
&lt;h2&gt;How to Communicate between Driver and NIC&lt;/h2&gt;
&lt;p&gt;Communication between a driver and the NIC is the bottom of the stack and most people do not care about it. However, the NIC is executing more and more tasks to solve the performance issue. Understanding the basic operation scheme will help you understand the additional technology.&lt;/p&gt;
&lt;p&gt;A driver and the NIC asynchronously communicate. First, a driver requests packet transmission (call) and the CPU performs another task without waiting for the response. And then the NIC sends packets and notifies the CPU of that, the driver returns the received packets (returns the result). Like packet transmission, packet receiving is asynchronous. First, a driver requests packet receiving and the CPU performs another task (call). Then, the NIC receives packets and notifies the CPU of that, and the driver processes the received packets received (returns the result).&lt;/p&gt;
&lt;p&gt;Therefore, a space to save the request and the response is necessary. In most cases, the NIC uses the ring structure. The ring is similar to the common queue structure. With the fixed number of entries, one entry saves one request data or one response data. The entries are sequentially used in turn. The name &quot;ring&quot; is generally used since the fixed entries are reused in turn.&lt;/p&gt;
&lt;p&gt;As following the packet transmission procedure shown in the following &lt;b&gt;Figure 8&lt;/b&gt;, you will see how the ring is used.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;284&quot; width=&quot;542&quot; alt=&quot;driver_nic_communication_how_to_transmit_packet.png&quot; src=&quot;/files/attach/images/220547/523/594/driver_nic_communication_how_to_transmit_packet.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 8: Driver-NIC Communication: How to Transmit Packet.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The driver receives packets from the upper layer and creates the send descriptor that the NIC can understand. The send descriptor includes the packet size and the memory address by default. As the NIC needs the physical address to access the memory, the driver should change the virtual address of the packets to the physical address. Then, it adds the send descriptor to the TX ring (1). The TX ring is the send descriptor ring.&lt;/p&gt;
&lt;p&gt;Next, it notifies the NIC of the new request (2). The driver directly writes the data to a specific NIC memory address. In this way, Programmed I/O (PIO) is the data transmission method in which the CPU directly sends data to the device.&lt;/p&gt;
&lt;p&gt;The notified NIC gets the send descriptor of the TX ring from the host memory (3). Since the device directly accesses the memory without intervention of the CPU, the access is called Direct Memory Access (DMA).&lt;/p&gt;
&lt;p&gt;After getting the send descriptor, the NIC determines the packet address and the size and then gets the actual packets from the host memory (4). With the checksum offload, the NIC computes the checksum when the NIC gets the packet data from the memory. Therefore, overhead rarely occurs.&lt;/p&gt;
&lt;p&gt;The NIC sends packets (5) and then writes the number of packets that are sent to the host memory (6). Then, it sends an interrupt (7). The driver reads the number of packets that are sent and then returns the packets that have been sent so far.&lt;/p&gt;
&lt;p&gt;In the following &lt;b&gt;Figure 9&lt;/b&gt;, you will see the procedure of receiving packets.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;290&quot; width=&quot;542&quot; alt=&quot;driver_nic_cmomunication_how_to_receive_packets.png&quot; src=&quot;/files/attach/images/220547/523/594/driver_nic_cmomunication_how_to_receive_packets.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 9: Driver-NIC Communication: How to Receive Packets.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;First, the driver allocates the host memory buffer for receiving packets and then creates the receive descriptor. The receive descriptor includes the buffer size and the memory address by default. Like the send descriptor, it saves the physical address that the DMA uses in the receive descriptor. Then, it adds the receive descriptor to the RX ring (1). It is the receive request and the RX ring is the receive request ring.&lt;/p&gt;
&lt;p&gt;Through the PIO, the driver notifies that there is a new descriptor in the NIC (2). The NIC gets the new descriptor of the RX ring. And then it saves the size and location of the buffer included in the descriptor to the NIC memory (3).&lt;/p&gt;
&lt;p&gt;After the packets have been received (4), the NIC sends the packets to the host memory buffer (5). If the checksum offload function is existing, the NIC computes the checksum at this time. The actual size of received packets, the checksum result, and any other information are saved in the separate ring (the receive return ring) (6). The receive return ring saves the result of processing the receive request, i.e., the response. And then the NIC sends an interrupt (7). The driver gets packet information from the receive return ring and processes the received packets. If necessary, it allocates new memory buffer and repeats Step (1) and Step (2).&lt;/p&gt;
&lt;p&gt;To tune the stack, most people say that the ring and interrupt setting should be adjusted. When the TX ring is large, a lot of send requests can be made at once. When the RX ring is large, a lot of packet receives can be done at once. A large ring is useful for the workload that has a huge burst of packet transmission/receiving. In most cases, the NIC uses a timer to reduce the number of interrupts since the CPU may suffer from large overhead to process interrupts. To avoid flooding the host system with too many interrupts, interrupts are collected and sent regularly(interrupt coalescing) while sending and receiving the packets.&lt;/p&gt;
&lt;h2&gt;Stack Buffer and Flow Control&lt;/h2&gt;
&lt;p&gt;Flow control is executed in several stages in the stack.&amp;nbsp;&lt;b&gt;Figure 10&lt;/b&gt; shows buffers used to transmit data. First, an application creates data and adds it to the send socket buffer. If there is no free space in the buffer, the system call is failed or the blocking occurs in the application thread. Therefore, the application data rate flowing into the kernel must be controlled by using the socket buffer size limit.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;400&quot; width=&quot;288&quot; alt=&quot;buffers_related_to_packet_transmission.png&quot; src=&quot;/files/attach/images/220547/523/594/buffers_related_to_packet_transmission.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 10: Buffers Related to Packet Transmission.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The TCP creates and sends packets to the driver through the transmit queue (qdisc). It is a typical FIFO queue type and the maximum length of the queue is the value of txqueuelen which can be checked by executing the ifconfig command. Generally, it is thousands of packets.&lt;/p&gt;
&lt;p&gt;The TX ring is between the driver and the NIC. As mentioned before, it is considered as a transmission request queue. If there is no free space in the queue, no transmission request is made and the packets are accumulated in the transmit queue. If too many packets are accumulated, packets are dropped.&lt;/p&gt;
&lt;p&gt;The NIC saves the packets to transmit in the internal buffer. The packet rate from this buffer is affected by the physical rate (ex: 1 Gb/s NIC cannot offer performance of 10 Gb/s). And with the Ethernet flow control, packet transmission is stopped if there is no free space in the receive NIC buffer.&lt;/p&gt;
&lt;p&gt;When the packet rate from the kernel is faster than the packet rate from the NIC, packets are accumulated in the buffer of the NIC. If there is no free space in the buffer, processing of transmission request from the TX ring is stopped. More and more requests are accumulated in the TX ring and finally there is no free space in the queue. The driver cannot make any transmission request and the packets are accumulated in the transmit queue. Like this, backpressure is sent from the bottom to the top through many buffers.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Figure 11&lt;/b&gt; shows the buffers that the receive packets are passing. The packets are saved in the receive buffer of the NIC. From the view of flow control, the RX ring between the driver and the NIC is considered as a packet buffer. The driver gets packets coming into the RX ring and then sends them to the upper layer. There is no buffer between the driver and the upper layer since the NIC driver that is used by the server system uses NAPI by default. Therefore, it can be considered as the upper layer directly gets packets from the RX ring. The payload data of packets is saved in the receive socket buffer. The application gets the data from the socket buffer later.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;362&quot; width=&quot;303&quot; alt=&quot;buffers_related_to_packaet_receiving.png&quot; src=&quot;/files/attach/images/220547/523/594/buffers_related_to_packaet_receiving.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 11: Buffers Related to Packet Receiving.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The driver that does not support NAPI saves packets in the backlog queue. Later, the NAPI handler gets packets. Therefore, the backlog queue can be considered as a buffer between the upper layer and the driver.&lt;/p&gt;
&lt;p&gt;If the packet processing rate of the kernel is slower than the packet flow rate into the NIC, the RX ring space is full. And the space of the buffer in the NIC is full, too. When the Ethernet flow control is used, the NIC sends a request to stop transmission to the transmission NIC or makes the packet drop.&lt;/p&gt;
&lt;p&gt;There is no packet drop due to lack of space in the receive socket buffer because the TCP supports end-to-end flow control. However, packet drop occurs due to lack of space in the socket buffer when the application rate is slow because the UDP does not support flow control.&lt;/p&gt;
&lt;p&gt;The sizes of the TX ring and the RX ring used by the driver in &lt;b&gt;Figure 10&lt;/b&gt; and &lt;b&gt;Figure 11&lt;/b&gt; are the sizes of the rings shown by the ethtool. For most workloads which regard throughput as important, it will be helpful to increase the ring size and the socket buffer size. Increasing the sizes reduces the possibility of failures caused by lack of space in the buffer while receiving and transmitting a lot of packets at a fast rate.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Initially, I planned to explain only the things that would be helpful for you to develop network programs, execute performance tests, and perform troubleshooting. In spite of my initial plan, the amount of description included in this document is not small. I hope this document will help you to develop network applications and monitor their performance. The TCP/IP protocol itself is very complicated and has many exceptions. However, you don&apos;t need to understand every line of TCP/IP-related code of the OS to understand performance and analyze the phenomena. Just understanding its context will be very helpful for you.&lt;/p&gt;
&lt;p&gt;With continuous advancement of system performance and implementation of the OS network stack, the latest server can offer 10-20 Gb/s TCP throughput without any problem. These days, there are too many technology types related to performance, such as TSO, LRO, RSS, GSO, GRO, UFO, XPS, IOAT, DDIO, and TOE, just like alphabet soup, to make us confused.&lt;/p&gt;
&lt;p&gt;In the next article, I will explain about the network stack from the performance perspective and discuss the problems and effects of this technology.&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;/?mid=community&amp;amp;act=dispMemberInfo&amp;amp;member_srl=595649&amp;amp;tab=blogs&quot;&gt;Hyeongyeop Kim&lt;/a&gt;, Senior Engineer at Performance Engineering Lab, NHN Corporation.&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="TCP"/>
            <category term="IP"/>
            <category term="Networking"/>
            <category term="performance"/>
            
   </entry>
   <entry>
      <title>How is SSD Changing Software Architecture?</title>
      <id>http://www.cubrid.org/blog/594303</id>
      <published>2013-02-24T20:38:58-08:00</published>
      <updated>2013-02-25T16:16:20-08:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/594303"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/594303#comment"/>
      <author>
         <name>Hye Jeong Lee</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;This is the second article on &lt;a href=&quot;/blog/tags/SSD/&quot;&gt;SSD&lt;/a&gt; and the performance implications of switching to SSD. In the first article,&amp;nbsp;&lt;a href=&quot;/blog/dev-platform/will-the-use-of-ssd-increase-the-speed-of-dbms/&quot;&gt;Will the use of SSD increase the speed of DBMS?&lt;/a&gt;,&amp;nbsp;we have reviewed how much performance gain we would see if we switched from HDD to SSD for a DBMS like CUBRID, and&amp;nbsp;what factors would affect the performance.&lt;/p&gt;
&lt;p&gt;In this article, I will compare the SSD structure to that of HDD and discuss how software architecture is changing.&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Last year in July Amazon released a new cloud product - &lt;i&gt;High I/O Quadruple Extra Large&lt;/i&gt;. This product uses 2 TB Solid-State Drive (SSD). So now even cloud products have started using SSD. That means the SSD price is becoming low enough to be adopted by cloud products. The operational know-how for cloud services is now established. &lt;b&gt;Then, can we assume that this is the era for using SSDs?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;A Solid-State Drive uses NAND flash memory and its operation is different from the operation of a&amp;nbsp;Hard Disk Drive. To develop a storage system, including a database, we needed to fully understand the HDD structure for higher performance. &lt;b&gt;Do we also need to fully understand the SSD structure for greater performance?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;The answer is Yes.&lt;/b&gt; As SSDs become popular, software architecture is changing. The architecture designed according to the HDD characteristics is being redesigned considering the SSD characteristics.&lt;/p&gt;
&lt;h2&gt;Introduction to the Experiences of EC2 Users&lt;/h2&gt;
&lt;p&gt;Below&amp;nbsp;I will use some of the reviews&amp;nbsp;posted on Amazon High IO Instance related&amp;nbsp;High Scalability&amp;nbsp;&lt;a href=&quot;http://highscalability.com/blog/2012/7/25/vertical-scaling-ascendant-how-are-ssds-changing-architectur.html&quot;&gt;blog&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Case #1:&amp;nbsp;Conversocial&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Conversocial, the social CRM firm, was using MongoDB when the High IO product was released, requiring MongoDB to run on High IO. Compared to the previous HDD, the average response time was &lt;a href=&quot;http://www.colinhowe.co.uk/2012/jul/23/ssds-on-aws--impact-on-conversocial/&quot;&gt;reduced&lt;/a&gt; by 43% (from 392 ms to 274 ms), the large data for random IO was reduced by 74% (from 877 ms to 504 ms), and the iowait was reduced from 90% to 3%.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Case #2:&amp;nbsp;Netflix&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Netflix, the DVD rental site, has posted a &lt;a href=&quot;http://techblog.netflix.com/2012/07/benchmarking-high-performance-io-with.html&quot;&gt;long article&lt;/a&gt; related to SSD as well. In the previous configuration, the performance was 100K IOPS or 1 GB/sec. As hi1.4xlarge was used, the response to the average read request was reduced from 10 ms to 2.2 ms and the 99% request response time was reduced from 65 ms to 10 ms.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Case #3: MySQL on EC2&lt;/h3&gt;
&lt;p&gt;Though SSD adoption does not guarantee enhanced performance all the time, on the High Scalability page we can also see the following statement:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;According to the &lt;a href=&quot;http://www.dbasquare.com/2012/07/20/amazon-ec2-now-powered-by-high-performance-storage-ssd/&quot;&gt;benchmark&lt;/a&gt;, now we can choose EC2 to run&amp;nbsp;MySQL on.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Implications&lt;/h3&gt;
&lt;p&gt;If you use HDDs, you should prepare the memory based on the working set. If the size exceeds, increase the number of equipments for horizontal partitioning.&lt;/p&gt;
&lt;p&gt;On the other hand, SSDs can help to reduce the required memory and can delay introduction of horizontal partitioning. For example, Netflix has removed the memcached layer for 48 IO instances. Then it replaced the layer with 15 instances where no cache was involved. Finally, the DBMS did not need to use additional cache to reduce IO time.&lt;/p&gt;
&lt;p&gt;Combined with the flexibility of EC2, SSDs can cut costs. For example, for a large capacity &lt;a href=&quot;http://news.ycombinator.com/item?id=4264962&quot;&gt;index of the genome mapping&lt;/a&gt;, the index operation can be performed intensively for a few hours per week. For the rest of the time, there is no need to perform the computation. Without EC2, you must purchase an expensive equipment, use it periodically, and leave it unused for most of the time. With EC2&amp;nbsp;you can save on the equipment, and pay for only what you use.&lt;/p&gt;
&lt;p&gt;While the popularization of SSD cuts costs as well as enhances the performance, the cost-cutting effect can be further maximized when SSDs are combined with cloud products.&lt;/p&gt;
&lt;h2&gt;Characteristic Comparisons between SSD and HDD IO&lt;/h2&gt;
&lt;p&gt;An SSD is a non-volatile memory, running in an electronic manner. Compared to HDDs, SSDs provide lower seek times, fewer mechanical delays, and lower fault rates. Therefore, they provide a very fast random read. However, an &lt;b&gt;overhead occurs in random write&lt;/b&gt;. The reason is that SSDs cannot overwrite data while writing data. An SSD is divided into many layers in the order of block, page, row, and cell. Data can be written by changing some cells to 0 while all cells in the block have been initialized to 1. To raise 0 to 1, high voltage is required. However, high voltage affects the neighboring cells (&lt;a href=&quot;http://en.wikipedia.org/wiki/Write_amplification&quot;&gt;write amplification&lt;/a&gt;). Therefore, writing data requires two stages of erase and program.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;/files/attach/images/220547/303/594/ssd_block_read.png&quot; alt=&quot;ssd_block_read.png&quot; width=&quot;640&quot; height=&quot;650&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1: SSD Cell Structure (&lt;a href=&quot;http://blog.csdn.net/shenyan008/article/details/8026283&quot;&gt;source&lt;/a&gt;).&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;An SSD writes by page and the number of writes on the page is limited (write endurance). If the endurance is exceeded, the block fails. To solve this problem, SSD manufacturers use the following methods on their firmware:&lt;/p&gt;
&lt;h3&gt;Wear Leveling&lt;/h3&gt;
&lt;p&gt;Uses blocks equally for lifetime extension. Counts the number of writes per block, and selects and uses the blocks with the fewest counts.&lt;/p&gt;
&lt;h3&gt;Write Gathering&lt;/h3&gt;
&lt;p&gt;If there is an erased empty block, gathers the blocks in use, in order to make the blocks empty. In addition, metadata is updated whenever data is written. As write positions are scattered, metadata update times become longer. Sometimes, the time is almost the same as HDD seek time. Therefore, to reduce write overhead, several write requests are gathered and executed at once.&lt;/p&gt;
&lt;h3&gt;Garbage Collection&lt;/h3&gt;
&lt;p&gt;The write unit is page and the erase unit is block. Among blocks, blocks that have the largest number of unused pages are initialized (erased). It is a type of defragmentation method; first, back up valid pages in a block and then initialize the block to an empty block, then push the valid pages backed up on another block into the empty block.&lt;/p&gt;
&lt;p&gt;Firmware runs differently by manufacturer. This is the competitive element of an SSD. Manufacturers keep their secrets and provide products by level. There are two levels, the low-end Multi Level Cell (MLC) and the high-end Single Level Cell (SLC). The two show significant differences in reliability and speed.&lt;/p&gt;
&lt;p&gt;When comparing the performance of an SSD to that of HDD, an SSD is generally 120,000 random reads and 10,000~85,000 random writes, based on IOPS. However, an HDD with 15,000 RPM generally shows performance of 175~210 IOPS. As a result, SSD shows 50~600 times of high performance, compared to an HDD.&lt;/p&gt;
&lt;p&gt;An SSD has no seek time, so it provides faster IO than an HDD. However, there is overhead in random write, as we have discussed earlier. The write optimization method of each manufacturer cannot be known. So, the exact IO pattern can be determined by testing each product. However, forecasting the write optimization method seems possible to a certain level. The next chapter will show how to optimize IO under these SSD constraints.&lt;/p&gt;
&lt;h2&gt;Trials to Optimize IO on SSD&lt;/h2&gt;
&lt;p&gt;An HDD is significantly slower than the memory. The performance of 10,000 RPM HDD is different from the performance of DDR3-2500 by approximately 800 times. Since HDDs have been used, many methods have been created to improve storage system performance. For example, when the OS and the device driver receive IO requests, they schedule the requests to minimize seek time. When an SSD is used, they do not schedule requests because SSD firmware performs that scheduling.&lt;/p&gt;
&lt;p&gt;Systems like a DBMS effectively implement the buffer (cache) to minimize IO on HDDs. As a result, when the hit rate is high, replacing an HDD to an SSD may improve the performance but slightly. However, with SSD, there is no need to keep the buffer size large, you may not need to retain a large memory capacity.&lt;/p&gt;
&lt;p&gt;In addition, a variety of methods are used to write data compactly, minimizing movement of the HDD head. However, these methods are not necessary since the random read of SSD is fast.&lt;/p&gt;
&lt;p&gt;The operation methods of SSD firmware are not open. So, it is difficult to model the IO pattern at the OS or device driver.&lt;/p&gt;
&lt;p&gt;However, at the application level, the architecture is being changed considering that the performance of random read and sequential write of SSD is great but random write performance is poor. Let&apos;s see how the architecture is changed.&lt;/p&gt;
&lt;h2&gt;Log Structured File System&lt;/h2&gt;
&lt;p&gt;As the memory capacity of a server increases, random read occurs less often than before due to memory cache. Therefore, random write becomes an important performance issue. An HDD performs an in-place write. If the random IO becomes larger, the head must move, causing an increase of seek time and degradation of performance. To compensate for that, there is a way to log the write history only and perform data write occasionally. This method is called journal file system or logging file system. Furthermore, you can avoid the in-place write by writing the data, instead of the history, whenever logging is performed. This is called log-structured file system (LFS).&lt;/p&gt;
&lt;p&gt;When writing data, the LFS reads the previous version to create the latest version and appends the latest version to the end of a file.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;￼&lt;img src=&quot;/files/attach/images/220547/303/594/architecture_of_log_structured_file_system.jpg&quot; alt=&quot;architecture_of_log_structured_file_system.jpg&quot; width=&quot;519&quot; height=&quot;176&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 2: Architecture of Log Structured File System (source).&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;At this time, the previous version is marked as an empty space. The version is always appended at the end of the file whenever it is required, only the sequential write is needed, so you can obtain the good performance at the early stage. However, as empty space increases, data is fragmented and an overhead occurs to gather the fragmented data. LFS writes a file with the serial chunk unit, called &lt;b&gt;segment&lt;/b&gt;. In order to reduce the overhead of metadata updates, which occurs per write, several writes are collected and written at once. Since most of segments are partially written, a task (GC) to create an empty segment is performed. It is similar to the efficient write of an SSD where data is gathered and written on sequential spaces with defragmentation for creating an empty space.&lt;/p&gt;
&lt;p&gt;&amp;nbsp; If an SSD does not perform wear leveling and write gathering, the file system will be more effective. The Journaling Flash File System (JFFS2), which is frequently used for embedded devices, is an example of the file system.&lt;/p&gt;
&lt;p&gt;On the performance side, in some cases, LFS can reduce disk usage by 40% compared to general file systems. However, LFS uses most of its time gathering segments. So, performance is lowered because it must process the segments at a certain period.&lt;/p&gt;
&lt;h2&gt;B-Tree Performance and Copy on-write B-Tree&lt;/h2&gt;
&lt;p&gt;B-Tree is a data architecture frequently used by file systems and databases (eg. &lt;a href=&quot;/wiki_tutorials/entry/important-facts-to-know-about-cubrid&quot;&gt;CUBRID&lt;/a&gt;). &lt;b&gt;Will the B-Tree work well on an SSD?&lt;/b&gt; The following graph shows the performance result calculated by measuring the B-Tree insert on the X25M SSD with three workloads.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;530&quot; width=&quot;700&quot; alt=&quot;performance_of_b_tree_insert_on_ssd.png&quot; src=&quot;/files/attach/images/220547/303/594/performance_of_b_tree_insert_on_ssd.png&quot; /&gt;￼&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 3: Performance of B-Tree Insert on SSD (source).&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The &lt;b&gt;red color&lt;/b&gt; is the &lt;i&gt;random write at 4 K size&lt;/i&gt;, the &lt;b&gt;green color&lt;/b&gt; is the &lt;i&gt;sequential write at 4 K size&lt;/i&gt;, and the &lt;b&gt;blue color&lt;/b&gt; is the &lt;i&gt;random write at 512 K size&lt;/i&gt;. At 4 K size, it seems natural that the sequential write shows the highest performance. An interesting thing is that the write performance is significantly lowered at 512 K size when the device capacity (160 G) is exceeded. First, performance is degraded when device capacity is full with the write volume. Why? The reason is that most SSDs have a log structure due to wear leveling and error correction. Originally, a block is 512 K; however, the latest MLC devices allow erasing data with the larger size. Finally, write can erase hundreds of MB with device firmware execution.&lt;/p&gt;
&lt;p&gt;Anyway, an SSD shows better performance of the sequential write than the random write. Is there a B-Tree that has a method allowing sequential write? Copy on-write (CoW) copies the path of B-Tree. It copies the traversed nodes whenever the nodes of the tree are changed, and then changes the nodes to create a new tree. See the following two sides:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Traverses the tree to find a key&lt;/li&gt;
&lt;li&gt;Rewrites the path&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the case of (1) for the CoW, the random IO (random write) occurs (of course, IO may not occur when cache is used); however, case (2) is completely the sequential write. Because the existing nodes are immutable, only the sequential write occurs (append only). This method has already been used in file systems such as ZFS, WAFL, and Btrfs.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;227&quot; width=&quot;283&quot; alt=&quot;cow_b_tree_structure.png&quot; src=&quot;/files/attach/images/220547/303/594/cow_b_tree_structure.png&quot; /&gt;￼&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 4: CoW B-Tree Structure (source).&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Then, does the CoW B-Tree work well with the log-structured storage structure of an SSD?&lt;/b&gt; Basically, it works well as it is &apos;append only&apos;. However, there are two issues: space blowup and garbage collection. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;CoW B-tree potentially creates a large space blowup. If a 16-byte key/value should be saved in an index with a depth of 3 and the block size is 256 K, data write should perform as much as 256*3 K (768 K). Compared to the small change, larger data should be written. In addition, as the size of space blowup becomes larger, GC should perform more tasks. Since GC runs when there are few IO, performance may be degraded.&lt;/p&gt;
&lt;h2&gt;Fractal Tree&lt;/h2&gt;
&lt;p&gt;At B-Tree, sequential insert is performed quickly because it has optimum locality by changing only specific pages. However, random insert causes high entropy. At the early stage, most pages are loaded on the memory. As time goes by, the possibility that some pages to be accessed in seeking are on the disk (aging) becomes higher. Especially, when terminal pages are scattered and saved on the disk, performance worsens.&lt;/p&gt;
&lt;p&gt;In the DAM model, IO is performed in the unit of block size between memory and storage. Generally, IO is performed by seeking the optimum block size for tuning. However, B-Tree generally uses one key but loads all blocks on the disk, consuming a lot of IO bandwidth. To optimize IO, the Cache Oblivious model is sometimes used. For this model, the IO size should be decided based on the algorithm applied because it is impossible to estimate optimum block size. In addition, as with LFS, B-Tree requires append to reduce random IO.&lt;/p&gt;
&lt;p&gt;Fractal Tree is based on them. First, data is inserted as several arrays which are increased exponentially. When insert is performed, the entry is saved in the smallest array. Arrays where data is inserted are merged into a larger array; at this time, the arrays are sorted in the order of keys. This is called &lt;b&gt;Doubling Array&lt;/b&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;327&quot; width=&quot;455&quot; alt=&quot;data_insert_process_in_fractal_tree.png&quot; src=&quot;/files/attach/images/220547/303/594/data_insert_process_in_fractal_tree.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 5: Data Insert Process in Fractal Tree (source).&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This array performs sequential write whenever the array grows. In this structure, insert is performed quickly. However, if the key should be navigated, binary navigation is performed so it performs more slowly than B-Tree. In order to improve this, the forward pointer is made and the tree is configured with levels. This is called &lt;b&gt;Fractal Cascading&lt;/b&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img height=&quot;167&quot; width=&quot;427&quot; alt=&quot;fractal_cascading.png&quot; src=&quot;/files/attach/images/220547/303/594/fractal_cascading.png&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 6: Fractal Cascading.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;This method is used by &lt;b&gt;TokuDB&lt;/b&gt;, one of the MySQL storage engines. TokuDB is storage for write-intensive workloads.&lt;/p&gt;
&lt;h2&gt;Stratified B-Tree&lt;/h2&gt;
&lt;p&gt;Weak points of the CoW B-Tree are space blowup and performance degradation caused by GC. The &lt;b&gt;Stratified B-Tree&lt;/b&gt; makes up for the weak points. It is one of the versioned dictionaries. It follows the Cache Oblivious model similar to Fractal Tree. It is a hierarchical tree, which runs by using Doubling Array and has the forward pointer. The difference is that it has the version by key.&lt;/p&gt;
&lt;p&gt;First, when a key is changed, the existing key version is maintained with the entry &lt;code&gt;{key, version, value_or_pointer}&lt;/code&gt;. When Insert comes in, the key value is saved in the memory buffer, arranged, and written in the array with the lowest level when flushed. After that, as the arrays grow, the key versions of arrays with the same level may be duplicated. In this case, the arrays are promoted and then demoted by disjointing them to avoid version duplication. The reason for demoting arrays is a concept, called &lt;b&gt;density&lt;/b&gt;. Density is the density degree of a live key in an array based on version &lt;code&gt;v&lt;/code&gt;. When the density is low, unnecessary keys should be searched when range query is performed based on version &lt;code&gt;v&lt;/code&gt;. On the contrary, when density is high, most keys are under the corresponding condition. However, a great deal of space blowup is made because data should be duplicated to increase the density. Finally, Stratified B-Tree promotes arrays to prevent each array version from being different, and then demotes the arrays with high density in order to improve the range query performance.&lt;/p&gt;
&lt;p&gt;This tree provides slow point query performance, but is good for analysis query and range query for big data. In addition, &lt;b&gt;Acunu&lt;/b&gt; is a storage platform implemented with this method. It is used for NoSQL including Cassandra.&lt;/p&gt;
&lt;h2&gt;Changes in Software Architecture Caused by SSD&lt;/h2&gt;
&lt;p&gt;So far, I have introduced how the software architecture of storage systems is being changed in the era of SSDs. When SSDs are generalized, products leading the marketplace will be software with architecture suitable for SSDs. No one knows whether HDD era winners will hold dominant positions in the SSD era or if a new hero will appear. Successful methods for existing HDDs are not suitable for SSDs. Therefore, it is very interesting to imagine the changes we will meet in this ongoing evolution.&lt;/p&gt;
&lt;p&gt;By &lt;a href=&quot;/?mid=community&amp;amp;act=dispMemberInfo&amp;amp;member_srl=240584&amp;amp;tab=blogs&quot;&gt;Hyejeong Lee&lt;/a&gt;, Senior Software Engineer at Storage System Development Team, NHN Corporation.&lt;/p&gt;
&lt;p&gt;My other posts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/dev-platform/nosql-benchmarking/&quot;&gt;NoSQL Benchmarking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/dev-platform/availability-and-operational-stability-of-nosql/&quot;&gt;Availability and Operational Stability of NoSQL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</content>
                  <category term="SSD"/>
            <category term="HDD"/>
            <category term="performance"/>
            <category term="DBMS"/>
            <category term="EC2"/>
            <category term="Amazon"/>
            <category term="TokuDB"/>
            
   </entry>
   <entry>
      <title>The Principles of Java Application Performance Tuning</title>
      <id>http://www.cubrid.org/blog/576432</id>
      <published>2013-02-07T01:26:09-08:00</published>
      <updated>2013-02-07T17:38:50-08:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/576432"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/576432#comment"/>
      <author>
         <name>Se Hoon Park</name>
                  <uri>http://www.cubrid.org</uri>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;This is the fifth article in the series of &quot;&lt;a href=&quot;/blog/tags/Garbage%20Collection/&quot;&gt;Become a Java GC Expert&lt;/a&gt;&quot;.&amp;nbsp;In the first issue &lt;a target=&quot;_self&quot; href=&quot;/blog/dev-platform/understanding-java-garbage-collection/&quot;&gt;Understanding Java Garbage Collection&lt;/a&gt; we have learned about the processes for different GC algorithms, about how GC works, what Young and Old Generation is, what you should know about the 5 types of GC in the new JDK 7, and what the performance implications are for each of these GC types.&lt;/p&gt;
&lt;p&gt;In the second article &lt;a target=&quot;_self&quot; href=&quot;/blog/dev-platform/how-to-monitor-java-garbage-collection/&quot;&gt;How to Monitor Java Garbage Collection&lt;/a&gt;&amp;nbsp;we have explained how &lt;a target=&quot;_self&quot; href=&quot;/blog/dev-platform/understanding-jvm-internals/&quot;&gt;JVM&lt;/a&gt; actually runs the Garbage Collection in the real time, how we can monitor GC, and which tools we can use to make this process faster and more effective.&lt;/p&gt;
&lt;p&gt;In the third article &lt;a target=&quot;_self&quot; href=&quot;/blog/dev-platform/how-to-tune-java-garbage-collection/&quot;&gt;How to Tune Java Garbage Collection&lt;/a&gt;&amp;nbsp;we have shown some of the best options&amp;nbsp;based on real cases as our examples that&amp;nbsp;you can use for GC tuning. Also we have explained how to minimize the number of objects passed to Old Area,&amp;nbsp;decreasing Full GC time, as well as how to set GC type and the memory size.&lt;/p&gt;
&lt;p&gt;In the fourth article &lt;a href=&quot;/blog/dev-platform/maxclients-in-apache-and-its-effect-on-tomcat-during-full-gc/&quot;&gt;MaxClients in Apache and its effect on Tomcat during Full GC&lt;/a&gt;&amp;nbsp;we have explained the importance of&amp;nbsp;&lt;code&gt;MaxClients&lt;/code&gt;&amp;nbsp;parameter in Apache that significantly affects the overall system performance when GC occurs.&lt;/p&gt;
&lt;p&gt;In this fifth article I will explain about the principles of Java application performance tuning. Specifically, I will explain what is required in order to tune the performance of Java application, the steps you need to perform to identify whether your application needs tuning. I will also explain the problems you may encounter during performance tuning. The article will be finalized with the recommendations you need to follow to make better decisions when tuning Java applications.&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Not every application requires tuning. If an application performs as well as expected, you don&apos;t need to exert additional efforts to enhance its performance. However, it would be difficult to expect an application would reach its target performance as soon as it finishes debugging. This is when tuning is required. Regardless of the implementation language, tuning an application requires high expertise and concentration. Also, you may not use the same method for tuning a certain application to tune another application. This is because each application has its unique action and a different type of resource usage. For this reason, tuning an application requires more basic knowledge compared to the knowledge required to write an application. For example, you need knowledge on virtual machines, operating systems and computer architectures. When you focus on an application domain based on such knowledge, you can successfully tune an application.&lt;/p&gt;
&lt;p&gt;Sometimes Java application tuning requires only changing JVM options, such as &lt;a href=&quot;/blog/dev-platform/how-to-tune-java-garbage-collection/&quot; target=&quot;_self&quot;&gt;Garbage Collector&lt;/a&gt;, but sometimes it requires changing the application source code. Whichever method you choose, you need to monitor the process of executing the Java application first. For this reason, the issues this article will deal with are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;How can I monitor a Java application?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;What JVM options should I give?&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;How can I know if modifying source codes is required or not?&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Knowledge Required to Tune the Performance of Java Applications&lt;/h2&gt;
&lt;p&gt;Java applications operate inside Java Virtual Machine (JVM). Therefore, to tune a Java application, you need to understand the JVM operation process. I have previously blogged about &lt;a href=&quot;/blog/dev-platform/understanding-jvm-internals/&quot; target=&quot;_self&quot;&gt;Understanding JVM Internals&lt;/a&gt;&amp;nbsp;where you can find&amp;nbsp;great insights about JVM.&lt;/p&gt;
&lt;p&gt;The knowledge regarding the process of the operation of JVM in this article mainly refers to the knowledge of Garbage Collection (GC) and Hotspot. Although you may not be able to tune the performance of all kinds of Java applications only with the knowledge on GC or Hotspot, these two factors influence the performance of Java applications in most cases.&lt;/p&gt;
&lt;p&gt;It is noted that from the perspective of an operating system JVM is also an application process. To make an environment in which a JVM can operate well, you should understand how an OS allocates resources to processes. This means, to tune the performance of Java applications, you should have an understanding of OS or hardware as well as JVM itself.&lt;/p&gt;
&lt;p&gt;Another aspect is that knowledge of Java language domain is also important. It is also important to understand lock or concurrency and to be familiar with class loading or object creation.&lt;/p&gt;
&lt;p&gt;When you carry out Java application performance tuning, you should approach it by integrating all this knowledge.&lt;/p&gt;
&lt;h2&gt;The Process of Java Application Performance Tuning&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;Figure 1 shows a flow chart from the book &amp;lt;Java Performance&amp;gt; co-authored by Charlie Hunt and Binu John. This chart shows the process of Java application performance tuning.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/432/576/process-tuning-performance-java-applications.png&quot; alt=&quot;process-tuning-performance-java-applications.png&quot; title=&quot;process-tuning-performance-java-applications.png&quot; class=&quot;iePngFix&quot; width=&quot;470&quot; height=&quot;781&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1: The Process of Tuning the Performance of Java Applications.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The above process is not a one-time process. You may need to repeat it until the tuning is completed. This also applies to determining an expected performance value. In the process of tuning, sometimes you should lower the expected performance value, and sometimes raise it.&lt;/p&gt;
&lt;h3&gt;JVM distribution model&lt;/h3&gt;
&lt;p&gt;A &lt;b&gt;JVM distribution model&lt;/b&gt; is related with making a decision on whether to operate Java applications on a single JVM or to operate them on multiple JVMs. You can decide it according to its availability, responsiveness and maintainability. When operating JVM on multiple servers, you can also decide whether to run multiple JVMs on a single server or to run a single JVM per server. For example, for each server, you can decide whether to run a single JVM using a heap of 8 GB, or to use four JVMs each using a heap of 2 GB. Of course, you can decide the number of JVMs running on a single server depending on the number of cores and the characteristics of the application. When comparing the two settings in terms of responsiveness, it might be more advantageous to use a heap of 2 GB rather than 8 GB for the same application, for it takes shorter to perform a full garbage collection when using a heap of 2 GB. If you use a heap of 8 GB, however, you can reduce the frequency of full GCs. You can also improve responsiveness by increasing the hit rate if the application uses internal cache. Therefore, you can choose a suitable distribution model by taking into account the characteristics of the application and the method to overcome the disadvantage of the model you chose for some advantages.&lt;/p&gt;
&lt;h3&gt;JVM architecture&lt;/h3&gt;
&lt;p&gt;Selecting a JVM means whether to use a &lt;b&gt;32-bit JVM&lt;/b&gt; or a &lt;b&gt;64-bit JVM&lt;/b&gt;. Under the same conditions, you had better choose a 32-bit JVM. This is because a 32-bit JVM performs better than a 64-bit JVM. However, the maximum logical heap size of a 32-bit JVM is 4 GB. (However, actual allocatable size for both 32-bit OS and 64-bit OS is 2-3 GB.) It is appropriate to use a 64-bit JVM when a heap size larger than this is required.&lt;/p&gt;
&lt;table style=&quot;margin: 0 auto;&quot;&gt;
&lt;caption&gt;&lt;b&gt;Table 1: Performance Comparison (&lt;/b&gt;&lt;a href=&quot;http://www.readwriteweb.com/hack/2011/06/cpp-go-java-scala-performance-benchmark.php&quot; target=&quot;_self&quot;&gt;source&lt;/a&gt;&lt;b&gt;).&lt;/b&gt;&lt;/caption&gt; &lt;thead&gt; 
&lt;tr&gt;
&lt;th&gt;Benchmark&lt;/th&gt;&lt;th&gt;Time (sec)&lt;/th&gt;&lt;th&gt;Factor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C++ Opt&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;23&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;1.0x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C++ Dbg&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;197&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;8.6x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java 64-bit&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;134&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;5.8x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java 32-bit&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;290&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;12.6x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java 32-bit GC*&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;106&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;4.6x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java 32-bit SPEC GC*&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;89&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;3.7x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scala&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;82&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;3.6x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scala low-level*&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;67&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;2.9x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scala low-level GC*&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;58&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;2.5x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go 6g&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;161&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;7.0x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go Pro*&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;126&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;5.5x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The next step is to run the application and to measure its performance. This process includes tuning GC, changing OS settings and modifying codes. For these tasks, you can use a system monitoring tool or a profiling tool.&lt;/p&gt;
&lt;p&gt;It should be noted that tuning for responsiveness and tuning for throughput could be different approaches. Responsiveness will be reduced if &lt;a href=&quot;/blog/dev-platform/understanding-java-garbage-collection/&quot; target=&quot;_self&quot;&gt;stop-the-world&lt;/a&gt; occurs from time to time, for example, for a full garbage collection despite a large amount of throughput per unit time. You also need to consider that a trade-off could occur.&amp;nbsp;Such trade-off could occur not only between responsiveness and throughput. You may need to use more CPU resources to reduce memory usage or put up with reduction in responsiveness or throughput. As opposite cases could likewise occur, you need to approach it according to the priority.&lt;/p&gt;
&lt;p&gt;The flow chart of &lt;b&gt;Figure 1&lt;/b&gt;&amp;nbsp;above shows the performance tuning approach for almost all kinds of Java applications, including Swing applications. However, this chart is somewhat unsuitable for writing a server application for Internet service as our company&amp;nbsp;&lt;a href=&quot;/blog/tags/NHN/&quot; target=&quot;_self&quot;&gt;NHN&lt;/a&gt; does. The flow chart in &lt;b&gt;Figure 2&lt;/b&gt;&amp;nbsp;below is a simpler procedure designed based on &lt;b&gt;Figure 1&lt;/b&gt; to be more suitable for NHN.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/432/576/recommended-procedure-tuning-nhn-java-applications.png&quot; alt=&quot;recommended-procedure-tuning-nhn-java-applications.png&quot; title=&quot;recommended-procedure-tuning-nhn-java-applications.png&quot; class=&quot;iePngFix&quot; width=&quot;304&quot; height=&quot;530&quot; style=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 2: A Recommended Procedure for Tuning NHN&apos;s Java Applications.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Select JVM&lt;/b&gt;&amp;nbsp;in the above flow chart means using a 32-bit JVM as much as possible except when you need to use a 64-bit JVM to maintain cache of several GB.&lt;/p&gt;
&lt;p&gt;Now, based on the flow chart in &lt;b&gt;Figure 2&lt;/b&gt;, you will learn about things to do to execute each of the steps.q&lt;/p&gt;
&lt;h3&gt;JVM Options&lt;/h3&gt;
&lt;p&gt;I will explain how to specify suitable JVM options mainly for a web application server. Despite not being applied to every case, the &lt;b&gt;best GC algorithm&lt;/b&gt;, especially for web server applications, is the &lt;a href=&quot;/blog/dev-platform/understanding-java-garbage-collection/&quot; target=&quot;_self&quot;&gt;Concurrent Mark Sweep GC&lt;/a&gt;. This is because what matters is &lt;b&gt;low latency&lt;/b&gt;. Of course, when using the Concurrent Mark Sweep, sometimes a very long stop-the-world phenomenon could take place due to fractions. Nevertheless, this problem is likely to be resolved by adjusting the new area size or the fraction ratio.&lt;/p&gt;
&lt;p&gt;Specifying the &lt;b&gt;new area size&lt;/b&gt; is as important as specifying the &lt;b&gt;entire heap size&lt;/b&gt;. You had better specify the ratio of the new area size to the entire heap size by using &lt;code&gt;&amp;ndash;XX:NewRatio&lt;/code&gt; or specify the desired new area size by using the &lt;code&gt;&amp;ndash;XX:NewSize&lt;/code&gt; option. Specifying a new area size is important because most objects cannot survive long. In web applications, most objects, except cache data, are generated when &lt;code&gt;HttpResponse&lt;/code&gt; to &lt;code&gt;HttpRequest&lt;/code&gt; is created. This time hardly exceeds a second. This means the life of objects does not exceed a second, either. If the new area size is not large, it should be moved to the old area to make space for newly created objects. The cost for GC for the old area is much bigger than that for the new area; therefore, it is good to set the size of the new area sufficiently.&lt;/p&gt;
&lt;p&gt;If the new area size exceeds a certain level, however, responsiveness will be reduced. This is because the garbage collection for the new area is basically to copy data from one survivor area to another survivor area. Also, the stop-the-world phenomenon will occur even when performing GC for the new area as well as the old area. If the new area becomes bigger, the survivor area size will increase, and thus the size of the data to copy will increase as well. Given such characteristics, it is good to set a suitable new area size by referring to the &lt;code&gt;NewRatio&lt;/code&gt; of HotSpot JVM by OS.&lt;/p&gt;
&lt;table style=&quot;margin: 0 auto;&quot;&gt;
&lt;caption&gt;&lt;b&gt;Table 2: NewRatio by OS and option.&lt;/b&gt;&lt;/caption&gt; &lt;thead&gt; 
&lt;tr&gt;
&lt;th&gt;OS and option&lt;/th&gt;&lt;th&gt;Default -XX:NewRatio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sparc -server&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sparc -client&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;x86 -server&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;x86 -client&lt;/td&gt;
&lt;td style=&quot;text-align: right;&quot;&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If the&amp;nbsp;&lt;code&gt;NewRatio&lt;/code&gt;&amp;nbsp;is specified, &lt;code&gt;1/(NewRatio +1)&lt;/code&gt; of the entire heap size becomes the new area size. You will find the&amp;nbsp;&lt;code&gt;NewRatio&lt;/code&gt;&amp;nbsp;of &lt;b&gt;Sparc -server&lt;/b&gt; is very small. This is because the Sparc system was used for more high-end use than x86 when default values were specified. Now it is common to use the x86 server and its performance has also been improved. Thus it is better to specify 2 or 3, which is the value similar to that of the &lt;b&gt;Sparc -server&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;You can also specify&amp;nbsp;&lt;code&gt;NewSize&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;MaxNewSize&lt;/code&gt;&amp;nbsp;instead of&amp;nbsp;&lt;code&gt;NewRatio&lt;/code&gt;. The new area is created as much as the value specified for&amp;nbsp;&lt;code&gt;NewSize&lt;/code&gt;&amp;nbsp;and the size increments as much as the value specified for&amp;nbsp;&lt;code&gt;MaxNewSize&lt;/code&gt;. The Eden or Survivor area also increases according to the (specified or default) ratio. As you specify the same size for&amp;nbsp;&lt;code&gt;-Xs&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;-Xmx&lt;/code&gt;, it is a very good choice to specify the same size for&amp;nbsp;&lt;code&gt;MaxSize&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;MaxNewSize&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you have specified both&amp;nbsp;&lt;code&gt;NewRatio&lt;/code&gt;&amp;nbsp;and&amp;nbsp;&lt;code&gt;NewSize&lt;/code&gt;, you should use the bigger one. Therefore, when a heap has been created, you can express the initial New area size as follows:&lt;/p&gt;
&lt;pre class=&quot;brush:java&quot;  title=&quot;&quot;&gt;min(MaxNewSize, max(NewSize, heap/(NewRatio+1)))&lt;/pre&gt;
&lt;p&gt;However, it is impossible to determine the appropriate entire heap size and New area size in a single attempt. Based on my experience running Web server applications at NHN, I recommend to run Java applications with the following JVM options. After monitoring the performance of the application with these options, you can use a more suitable GC algorithm or options.&lt;/p&gt;
&lt;table style=&quot;margin: 0 auto;&quot;&gt;
&lt;caption&gt;&lt;b&gt;Table 3: Recommended JVM options.&lt;/b&gt;&lt;/caption&gt; &lt;thead&gt; 
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;&lt;th&gt;Option&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Operation mode&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-sever&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entire heap size&lt;/td&gt;
&lt;td&gt;Specify the same value for &lt;code&gt;-Xms&lt;/code&gt; and &lt;code&gt;-Xmx&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td rowspan=&quot;2&quot;&gt;New area size&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-XX:NewRatio&lt;/code&gt;: value of 2 to 4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-XX:NewSize=?&lt;/code&gt; &lt;code&gt;&amp;ndash;XX:MaxNewSize=?&lt;/code&gt;. Also good to specify &lt;code&gt;NewSize&lt;/code&gt; instead of &lt;code&gt;NewRatio&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perm size&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-XX:PermSize=256 m&lt;/code&gt; &lt;code&gt;-XX:MaxPermSize=256 m&lt;/code&gt;. Specify the value to an extent not to cause any trouble in the operation because it does not affect the performance.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GC log&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-Xloggc:$CATALINA_BASE/logs/gc.log&lt;/code&gt; &lt;code&gt;-XX:+PrintGCDetails&lt;/code&gt; &lt;code&gt;-XX:+PrintGCDateStamps&lt;/code&gt;. Leaving a GC log does not particularly affect the performance of Java applications. You are recommended to leave a GC log as much as possible.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GC algorithm&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-XX:+UseParNewGC&lt;/code&gt; &lt;code&gt;-XX:+CMSParallelRemarkEnabled&lt;/code&gt; &lt;code&gt;-XX:+UseConcMarkSweepGC&lt;/code&gt; &lt;code&gt;-XX:CMSInitiatingOccupancyFraction=75&lt;/code&gt;.This is only a generally recommendable configuration. Other choices could be better depending on the characteristics of the application.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creating a heap dump when an OOM error occurs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-XX:+HeapDumpOnOutOfMemoryError&lt;/code&gt; &lt;code&gt;-XX:HeapDumpPath=$CATALINA_BASE/logs&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Actions after an OOM occurs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-XX:OnOutOfMemoryError=$CATALINA_HOME/bin/stop.sh&lt;/code&gt;&amp;nbsp;or&amp;nbsp;&lt;code&gt;-XX:OnOutOfMemoryError=$CATALINA_HOME/bin/restart.sh&lt;/code&gt;. After leaving a heap dump, take a proper operation according to a management policy.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Measuring the Performance of Applications&lt;/h2&gt;
&lt;p&gt;The information to acquire to grasp the performance of an application is as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;TPS (OPS):&lt;/b&gt; The information required to understand the performance of an application conceptually.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Request Per Second (RPS):&lt;/b&gt; Strictly speaking, RPS is different from responsiveness, but you can understand it as responsiveness. Through RPS, you can check the time it takes for the user to see the result.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RPS Standard Deviation:&lt;/b&gt; It is necessary to induce even RPS if possible. If a deviation occurs, you need to check GC tuning or interworking systems. &amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To obtain a more accurate performance result, you should measure it after warming up the application sufficiently. This is because byte code is expected to be compiled by HotSpot JIT. In general, you can measure actual performance values after applying load to a certain feature for at least 10 minutes by using &lt;a href=&quot;http://www.nhnopensource.org/ngrinder/&quot; target=&quot;_self&quot;&gt;nGrinder&lt;/a&gt; load testing tool.&lt;/p&gt;
&lt;h2&gt;Tuning in Earnest&lt;/h2&gt;
&lt;p&gt;You don&apos;t need to tune the performance of an application if the result of the execution of nGrinder meets the expectation. If the performance does not meet the expectation, you need to carry out tuning to resolve problems. Now you will see the approach by case.&lt;/p&gt;
&lt;h3&gt;In the event the Stop-the-World takes long&lt;/h3&gt;
&lt;p&gt;Long &lt;b&gt;stop-the-world&lt;/b&gt; time could result from inappropriate GC options or incorrect implementation. You can decide the cause according to the result of a profiler or a heap dump. This means you can judge the cause after checking the type and number of objects of a heap. If you find many unnecessary objects, you had better modify source codes. If you find no particular problem in the process of creating objects, you had better simply change GC options.&lt;/p&gt;
&lt;p&gt;To adjust GC options appropriately, you need to have GC log secured for a sufficient period of time. You need to understand in which situation the stop-the-world takes a long time. For more information on the selection of appropriate GC options, read my colleague&apos;s blog about&amp;nbsp;&lt;a href=&quot;/blog/dev-platform/how-to-monitor-java-garbage-collection/&quot;&gt;How to Monitor Java Garbage Collection&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;In the event CPU usage rate is low&lt;/h3&gt;
&lt;p&gt;When blocking time occurs, both TPS and CPU usage rate will decrease. This might result from the problem of interworking systems or concurrency. To analyze this, you can use an analysis on the result of thread dump or a profiler. For more information on thread dump analysis, read&amp;nbsp;&lt;a href=&quot;/blog/dev-platform/how-to-analyze-java-thread-dumps/&quot;&gt;How to Analyze Java Thread Dumps&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can conduct a very accurate lock analysis by using a commercial profiler. In most cases, however, you can obtain a satisfactory result with only the CPU analyzer in &lt;b&gt;jvisualvm&lt;/b&gt;.&lt;/p&gt;
&lt;h3&gt;In the event CPU usage rate is high&lt;/h3&gt;
&lt;p&gt;If TPS is low but CPU usage rate is high, this is likely to result from inefficient implementation. In this case, you should find out the location of bottlenecks by using a profiler. You can analyze this by using &lt;b&gt;jvisuavm&lt;/b&gt;, &lt;b&gt;TPTP&lt;/b&gt; of Eclipse or &lt;b&gt;JProbe&lt;/b&gt;.&lt;/p&gt;
&lt;h2&gt;Approach for Tuning&lt;/h2&gt;
&lt;p&gt;You are advised to use the following approach to tune applications.&lt;/p&gt;
&lt;p&gt;First, you should check whether performance tuning is necessary. The process of performance measuring is not easy work. You are also not guaranteed to obtain a satisfactory result all the time. Therefore, if the application already meets its target performance, you don&apos;t need to invest additionally in performance.&lt;/p&gt;
&lt;p&gt;The problem lies in only a single place. All you have to do is to fix it. The &lt;a href=&quot;http://en.wikipedia.org/wiki/Pareto_principle&quot;&gt;Pareto principle&lt;/a&gt; applies to performance tuning as well. This does not mean to emphasize that the low performance of a certain feature results necessarily from a single problem. Rather, this emphasizes that we should focus on one factor that has the biggest influence on the performance when approaching performance tuning. Thus, you could handle another problem after fixing the most important one. You are advised to try to fix just one problem at a time.&lt;/p&gt;
&lt;p&gt;You should consider the &lt;a href=&quot;http://en.wikipedia.org/wiki/Balloon_effect&quot;&gt;balloon effect&lt;/a&gt;. You should decide what to give up to get something. You can improve responsiveness by applying cache but if the cache size increases, the time it takes to carry out a full GC will increase as well. In general, if you want a small amount of memory usage, throughput or responsiveness could be deteriorated. Thus, you need to consider what is most important and what is less important.&lt;/p&gt;
&lt;p&gt;So far, you have read the method for Java application performance tuning. To introduce a concrete procedure for performance measurement, I had to omit some details. Nevertheless, I think this could satisfy most of the cases for tuning Java web server applications.&lt;/p&gt;
&lt;p&gt;Good luck with performance tuning!&lt;/p&gt;
&lt;p&gt;By&amp;nbsp;&lt;a href=&quot;/?mid=textyle&amp;amp;act=dispMemberInfo&amp;amp;member_srl=290454&amp;amp;vid=blog&amp;amp;tab=blogs&quot;&gt;Se Hoon Park&lt;/a&gt;, Senior Software Engineer at Web Platform Development Lab, NHN Corporation.&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="Java"/>
            <category term="Garbage Collection"/>
            <category term="performance"/>
            <category term="JVM"/>
            <category term="NHN"/>
            <category term="tuning"/>
            <category term="analysis"/>
            <category term="monitoring"/>
            
   </entry>
   <entry>
      <title>All about Two-Phase Locking and a little bit MVCC</title>
      <id>http://www.cubrid.org/blog/507566</id>
      <published>2012-12-10T23:18:29-08:00</published>
      <updated>2013-02-05T17:24:43-08:00</updated>
      <link rel="alternate" type="text/html" href="http://www.cubrid.org/blog/507566"/>
      <link rel="replies" type="text/html" href="http://www.cubrid.org/blog/507566#comment"/>
      <author>
         <name>Park Kieun</name>
               </author>
            <content type="html">&lt;div class=&quot;xe_content&quot;&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;In this blog I will describe the concurrency control methods implemented in database management systems, and&amp;nbsp;the differences between them.&amp;nbsp;I will also explain about what locking technique is used in&amp;nbsp;&lt;a href=&quot;http://www.cubrid.org&quot; target=&quot;_self&quot;&gt;CUBRID RDBMS&lt;/a&gt;, about locking modes and their compatibility, and finally, the deadlocks and the solution for them.&lt;/p&gt;

&lt;h2&gt;Overview&lt;/h2&gt;

&lt;p&gt;When multiple transactions, which change the data,&amp;nbsp;are executed&amp;nbsp;simultaneously,&amp;nbsp;it is required to control the order of processing these transactions to satisfy the &lt;a href=&quot;http://en.wikipedia.org/wiki/ACID&quot; target=&quot;_self&quot;&gt;ACID&lt;/a&gt; (Atomicity, Consistency, Integrity, Durability) property of the database. &lt;i&gt;Executing multiple transactions simultaneously should&amp;nbsp;lead to the same result as executing each transaction independently&lt;/i&gt;, in other words, one transaction should not be affected by another transaction.&lt;/p&gt;

&lt;p&gt;If different data is changed for each transaction, no interference between transactions is made, so there is no issue. However, if the same data is simultaneously changed by multiple transactions, the order of processing each transaction should be controlled.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;Types of Concurrency Control&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;For example, the &lt;b&gt;T1 transaction&lt;/b&gt; changes the &lt;b&gt;A record&lt;/b&gt; from &lt;i&gt;1&lt;/i&gt; to &lt;i&gt;2&lt;/i&gt; and then changes the &lt;b&gt;B record&lt;/b&gt;, the &lt;b&gt;T2 transaction&lt;/b&gt; can simultaneously change the &lt;b&gt;A record&lt;/b&gt;, too. Let&apos;s assume that the &lt;b&gt;T2 transaction&lt;/b&gt; changes the &lt;b&gt;A record&lt;/b&gt; from &lt;i&gt;2&lt;/i&gt; to &lt;i&gt;4&lt;/i&gt; by adding &lt;b&gt;+2&lt;/b&gt;. If two transactions are successfully terminated, there is no issue. But it is important that all transactions can be rolled back. If the &lt;b&gt;T1 transaction&lt;/b&gt; is rolled back, the value of the &lt;b&gt;A record&lt;/b&gt; should be returned to &lt;i&gt;1&lt;/i&gt;, i.e. the value &lt;i&gt;before&lt;/i&gt; the &lt;b&gt;T1 transaction&lt;/b&gt; was executed. This is to satisfy the ACID property of the database. However, the &lt;b&gt;T2 transaction&lt;/b&gt; has already changed the &lt;b&gt;A record&lt;/b&gt; value to &lt;i&gt;3&lt;/i&gt;. So, it is impossible to return the &lt;b&gt;A record&lt;/b&gt; to &lt;i&gt;1&lt;/i&gt; regardless of the situation. In this case, there can be two options.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Two-phase_locking&quot; target=&quot;_self&quot;&gt;Two-phase locking (2PL)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The first one is when the&amp;nbsp;&lt;b&gt;T2 transaction&lt;/b&gt;&amp;nbsp;tries to change the&amp;nbsp;&lt;b&gt;A record&lt;/b&gt;, it knows that the&amp;nbsp;&lt;b&gt;T1 transaction&lt;/b&gt;&amp;nbsp;has already changed the&amp;nbsp;&lt;b&gt;A record&lt;/b&gt;&amp;nbsp;and waits until the&amp;nbsp;&lt;b&gt;T1 transaction&lt;/b&gt;&amp;nbsp;is completed because the&amp;nbsp;&lt;b&gt;T2 transaction&lt;/b&gt;&amp;nbsp;cannot know whether the&amp;nbsp;&lt;b&gt;T1 transaction&lt;/b&gt;&amp;nbsp;will be committed or rolled back. This method is called &lt;b&gt;Two-phase locking (2PL)&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Multiversion_concurrency_control&quot; target=&quot;_self&quot;&gt;Multi-version concurrency control (MVCC)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The other one is to allow each of them, &lt;b&gt;T1&lt;/b&gt; and &lt;b&gt;T2 transactions&lt;/b&gt;, to have their own changed versions. Even when the &lt;b&gt;T1 transaction&lt;/b&gt; has changed the &lt;b&gt;A record&lt;/b&gt; from &lt;i&gt;1&lt;/i&gt; to &lt;i&gt;2&lt;/i&gt;, the &lt;b&gt;T1 transaction&lt;/b&gt; leaves the original value &lt;i&gt;1&lt;/i&gt; as it is and writes that the&amp;nbsp;&lt;b&gt;&lt;i&gt;T1 transaction version&lt;/i&gt;&lt;/b&gt;&amp;nbsp;of the &lt;b&gt;A record&lt;/b&gt; is &lt;b&gt;2&lt;/b&gt;. Then, the following &lt;b&gt;T2 transaction&lt;/b&gt; changes the &lt;b&gt;A record&lt;/b&gt; from &lt;i&gt;1&lt;/i&gt; to &lt;i&gt;3&lt;/i&gt;, &lt;b&gt;not&lt;/b&gt; from &lt;i&gt;2&lt;/i&gt; to &lt;i&gt;4&lt;/i&gt;, and writes that the&amp;nbsp;&lt;i&gt;&lt;b&gt;T2 transaction version&lt;/b&gt;&lt;/i&gt;&amp;nbsp;of the &lt;b&gt;A record&lt;/b&gt; is &lt;b&gt;3&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;When the &lt;b&gt;T1 transaction&lt;/b&gt; is rolled back, it does not matter if the&amp;nbsp;&lt;b&gt;2&lt;/b&gt;,&amp;nbsp;&lt;b&gt;&lt;i&gt;the&amp;nbsp;T1 transaction version&lt;/i&gt;&lt;/b&gt;, is not applied to the &lt;b&gt;A record&lt;/b&gt;. After that, if the &lt;b&gt;T2 transaction&lt;/b&gt; is committed, the &lt;b&gt;3&lt;/b&gt;, &lt;b&gt;&lt;i&gt;the&amp;nbsp;T2 transaction version&lt;/i&gt;&lt;/b&gt;, will be applied to the &lt;b&gt;A record&lt;/b&gt;. If the &lt;b&gt;T1 transaction&lt;/b&gt; is committed prior to the &lt;b&gt;T2 transaction&lt;/b&gt;, the &lt;b&gt;A record&lt;/b&gt; is changed to 2, and then to 3 at the time of committing the &lt;b&gt;T2 transaction&lt;/b&gt;. The final database status is identical to the status of executing each transaction independently, without any impact on other transactions. Therefore, it satisfies the ACID property. This method is called &lt;b&gt;Multi-version concurrency control (MVCC)&lt;/b&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CUBRID has implemented 2PL method as well as DB2 and SQL Server, while Oracle, InnoDB and PostgreSQL have implemented&amp;nbsp;MVCC.&lt;/p&gt;

&lt;h2&gt;Two-phase locking in CUBRID&lt;/h2&gt;&lt;p&gt;The 2PL adopted by CUBRID uses locks to ensure the consistency between transactions that change the identical data. As the &quot;lock&quot; literally means,&amp;nbsp;&lt;b&gt;the locking is executed through two phases&lt;/b&gt;:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;expanding phase (acquiring)&lt;/li&gt;
&lt;li&gt;shrinking phase (releasing)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;

&lt;p&gt;More accurately, all transactions should acquire lock for the data to be accessed and the acquired locks are released only when the transaction is terminated. After a transaction has acquired the lock for a certain data (regardless of the lock type, &lt;code&gt;S_LOCK&lt;/code&gt; for read, stands for &lt;i&gt;Shared Lock&lt;/i&gt;, or &lt;code&gt;X_LOCK&lt;/code&gt; for write, stands for &lt;i&gt;Exclusive Lock&lt;/i&gt;), when another transaction tries to acquire a new lock for the data, the new lock is allowed or pended depending on the&amp;nbsp;&lt;a href=&quot;/transaction_and_lock&quot; target=&quot;_self&quot;&gt;lock compatibility rule&lt;/a&gt;.&amp;nbsp;Therefore, success or failure of the prior transaction does not have impact on the following transactions, so the data consistency is maintained.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;Lock Manager in CUBRID&lt;/h2&gt;

&lt;p&gt;Thus, the &lt;b&gt;key point of 2PL&lt;/b&gt;, adopted by CUBRID, is that &lt;b&gt;the lock must be processed through two phases&lt;/b&gt;:&amp;nbsp;&lt;i&gt;expanding phase&lt;/i&gt; and &lt;i&gt;shrinking phase&lt;/i&gt;. Then, &lt;b&gt;[Figure 1]&lt;/b&gt;&amp;nbsp;&lt;i&gt;release all locks, acquired while executing a transaction, only after the transaction ends (commit or rollback)&lt;/i&gt;.&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/566/507/two-phase-lock.png&quot; alt=&quot;two-phase-lock.png&quot; title=&quot;two-phase-lock.png&quot; class=&quot;iePngFix&quot; width=&quot;323&quot; height=&quot;216&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 1: Two-Phase Locking.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;2PL concurrency control method naturally controls access to the identical data from transactions by making all transactions observe the 2PL protocol. The following &lt;b&gt;Figure 2&lt;/b&gt; below shows an example of three transactions using 2PL: &lt;b&gt;Transaction 1&lt;/b&gt; executes &lt;b&gt;B=B+A&lt;/b&gt; operation, &lt;b&gt;Transaction 2&lt;/b&gt; executes &lt;b&gt;C=A+B&lt;/b&gt; operation, and &lt;b&gt;Transaction 3&lt;/b&gt; executes &lt;b&gt;Print C&lt;/b&gt; operation. Since all three transactions are accessing the data A, B and C, the concurrency control is required. In this case, each transaction is executed according to the 2PL protocol so that there is no data conflict.&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/566/507/concurrency-control-using-2PL.png&quot; alt=&quot;concurrency-control-using-2PL.png&quot; title=&quot;concurrency-control-using-2PL.png&quot; class=&quot;iePngFix&quot; width=&quot;486&quot; height=&quot;642&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 2: Concurrency Control by using 2PL.&lt;/b&gt;&lt;/p&gt;

&lt;h3&gt;Lock modes&lt;/h3&gt;&lt;p&gt;To understand the concurrency control of multiple transactions more deeply, let&apos;s discuss about&amp;nbsp;&lt;a href=&quot;/manual/90/en/Lock%20Mode%20Types%20And%20Compatibility&quot; target=&quot;_self&quot;&gt;lock modes&lt;/a&gt;, &lt;b&gt;lock conversion&lt;/b&gt; and &lt;a href=&quot;/manual/90/en/Transaction%20Isolation%20Level-Overview&quot; target=&quot;_self&quot;&gt;transaction isolation level&lt;/a&gt;. In the above figure, you can see that &lt;code&gt;S-lock&lt;/code&gt;, &lt;i&gt;Shared Lock&lt;/i&gt;, for &lt;b&gt;A&lt;/b&gt; was&amp;nbsp;first&amp;nbsp;acquired by &lt;b&gt;Transaction 1&lt;/b&gt;, but it is also&amp;nbsp;acquired by&amp;nbsp;&lt;b&gt;Transaction 2&lt;/b&gt;, too. On the contrary, the transaction which requested &lt;code&gt;X-lock&lt;/code&gt; is blocked until &lt;code&gt;S-lock&lt;/code&gt; is released. In this matter, a &lt;a href=&quot;/manual/90/en/Lock%20Mode%20Types%20And%20Compatibility&quot; target=&quot;_self&quot;&gt;variety of lock modes&lt;/a&gt; are used to minimize conflicts by lockers. Major types of locks utilized in DBMSs are.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Shared (S) Lock&lt;/b&gt;: Used for read operation. It is generally set on the target record when &lt;code&gt;SELECT&lt;/code&gt; statement is executed. It blocks a transaction from changing data which was already read by other transactions.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Exclusive (X) Lock&lt;/b&gt;: Used for write-operations such as &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;. It blocks one data from being changed by multiple transactions.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Update (U) Lock&lt;/b&gt;: Used to define that the target resource will be changed. It is used to minimize deadlock which may occur when multiple transactions are executing both read and write.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Intent Shared (IS) Lock&lt;/b&gt;: Set on the upper resource (e.g. tables) to set the &lt;code&gt;S-lock&lt;/code&gt; on some lower resources (e.g. records or pages). It is to prevent other transactions from setting &lt;code&gt;X-lock&lt;/code&gt; on the upper resource. Intent lock will soon be described.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Intent Exclusive (IX) Lock&lt;/b&gt;: Set on the upper resource to set &lt;code&gt;X-lock&lt;/code&gt; on some lower resources.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Shared with Intent Exclusive (SIX) Lock&lt;/b&gt;: Set on the upper resource to set &lt;code&gt;S-lock&lt;/code&gt; and &lt;code&gt;X-lock&lt;/code&gt; on some lower resources.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h4&gt;Lock mode compatibility&lt;/h4&gt;&lt;p&gt;Among the lock modes above, &lt;b&gt;intent locks&lt;/b&gt; are used to &lt;i&gt;improve the transaction concurrency&lt;/i&gt; and to &lt;i&gt;prevent deadlock&lt;/i&gt; between the upper resources and the lower resources. For example, when &lt;b&gt;Transaction A&lt;/b&gt; tries to read &lt;b&gt;Record R&lt;/b&gt; on &lt;b&gt;Table T&lt;/b&gt;, it sets &lt;code&gt;IS_LOCK&lt;/code&gt; on &lt;b&gt;Table T&lt;/b&gt; before setting &lt;code&gt;S_LOCK&lt;/code&gt; on &lt;b&gt;Record R&lt;/b&gt;. Then, &lt;b&gt;Transaction B&lt;/b&gt; is prevented from setting &lt;code&gt;X_LOCK&lt;/code&gt; on &lt;b&gt;Table T&lt;/b&gt; to change the structure of &lt;b&gt;Table T&lt;/b&gt;. If &lt;b&gt;Transaction A&lt;/b&gt; has not set &lt;code&gt;IS_LOCK&lt;/code&gt; on &lt;b&gt;Table T&lt;/b&gt;, &lt;b&gt;Transaction B&lt;/b&gt; would change the structure of &lt;b&gt;Table T&lt;/b&gt;. Then, &lt;b&gt;Transaction A&lt;/b&gt; would perform a wrong read operation. This way&amp;nbsp;&lt;b&gt;Transaction B&lt;/b&gt; has no need to check all records in &lt;b&gt;Table T&lt;/b&gt; to check whether there is any lock set by other transactions for setting &lt;code&gt;X_LOCK&lt;/code&gt; on &lt;b&gt;Table T&lt;/b&gt;. The following lock mode compatibility table will clearly show the effect of intent locks:&lt;/p&gt;

&lt;table style=&quot;margin:0 auto&quot;&gt;
  &lt;caption&gt;&lt;b&gt;Table 1: The lock mode compatibility table of CUBRID.&lt;/b&gt;&lt;/caption&gt;
 &lt;thead&gt;
  &lt;tr&gt;
    &lt;th colspan=&quot;2&quot; rowspan=&quot;2&quot;&gt;&lt;/th&gt;
    &lt;th colspan=&quot;9&quot;&gt;Current Lock Mode&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;NULL&lt;/th&gt;
    &lt;th&gt;IS&lt;/th&gt;
    &lt;th&gt;NS&lt;/th&gt;
    &lt;th&gt;S&lt;/th&gt;
    &lt;th&gt;IX&lt;/th&gt;
    &lt;th&gt;SIX&lt;/th&gt;
    &lt;th&gt;U&lt;/th&gt;
    &lt;th&gt;NX&lt;/th&gt;
    &lt;th&gt;X&lt;/th&gt;
  &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
  &lt;tr&gt;
    &lt;th rowspan=&quot;9&quot;&gt;Newly-requested Lock Mode&lt;/th&gt;
    &lt;th&gt;NULL&lt;/th&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;IS&lt;/th&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;N/A&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;N/A&lt;/td&gt;
    &lt;td&gt;N/A&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;NS&lt;/th&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;N/A&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td&gt;N/A&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;S&lt;/th&gt;
    &lt;td&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;IX&lt;/th&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td&gt;N/A&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;SIX&lt;/th&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td&gt;N/A&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;U&lt;/th&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;NX&lt;/th&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;N/A&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;X&lt;/th&gt;
    &lt;td class=&quot;&quot;&gt;True&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td class=&quot;&quot;&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
    &lt;td&gt;False&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;From the lock mode compatibility table, you can see that &lt;code&gt;X_LOCK&lt;/code&gt; cannot be set on a table if &lt;code&gt;IS_LOCK&lt;/code&gt; is set on the table. And only &lt;code&gt;IS_LOCK&lt;/code&gt; can be compatible with &lt;code&gt;SIX_LOCK&lt;/code&gt;. This means that &lt;code&gt;SIX_LOCK&lt;/code&gt; intends to set &lt;code&gt;S_LOCK&lt;/code&gt; and &lt;code&gt;X_LOCK&lt;/code&gt; on the record and it will not allow any lock but &lt;code&gt;IS_LOCK&lt;/code&gt; for &lt;code&gt;S_LOCK&lt;/code&gt; on other non-conflicting records. From the table, you can see that &lt;code&gt;IX_LOCK&lt;/code&gt; and &lt;code&gt;IX_LOCK&lt;/code&gt; can be compatible with each other. &lt;code&gt;IX_LOCK&lt;/code&gt; intends to set &lt;code&gt;X_LOCK&lt;/code&gt; for some records. So, the compatibility is available. If there are two transactions that try to change an identical record, &lt;code&gt;IX_LOCK&lt;/code&gt; for the table is allowed. However, there is no problem in concurrency control since only the transaction that has acquired &lt;code&gt;X_LOCK&lt;/code&gt; for the record first can change the record (&lt;code&gt;X_LOCK&lt;/code&gt; and &lt;code&gt;X_LOCK&lt;/code&gt; are not compatible).&lt;/p&gt;

&lt;p&gt;The lock mode compatibility table is expressed as a global variable &lt;code&gt;lock_Comp[][]&lt;/code&gt; in the &lt;i&gt;&lt;b&gt;lock_table.c&lt;/b&gt;&lt;/i&gt; file in &lt;a href=&quot;/wiki_tutorials/entry/cubrid-source-code&quot; target=&quot;_self&quot;&gt;CUBRID source code&lt;/a&gt;. Among CUBRID sources, most codes related to lock modes are implemented in &lt;i&gt;&lt;b&gt;lock_manager.c&lt;/b&gt;&lt;/i&gt; file. To set lock on a data object, the &lt;code&gt;lock_object()&lt;/code&gt; function is used which receives three parameters:&amp;nbsp;the &lt;b&gt;OID of an object&lt;/b&gt; where the lock mode will be set, &lt;b&gt;the OID of the class&lt;/b&gt; where the object belongs, and &lt;b&gt;the desired lock mode&lt;/b&gt;. In the source code of the function, you can see that the function is executed in several ways based on the &lt;b&gt;target of the lock mode&lt;/b&gt;, the &lt;b&gt;lock mode for an instance object&lt;/b&gt; or &lt;b&gt;for a class object&lt;/b&gt;.&lt;/p&gt;

&lt;blockquote class=&quot;q4&quot;&gt;&lt;p&gt;&lt;b&gt;Take note of this&lt;/b&gt;: in CUBRID, a class object is also an object. Keep it in mind that a class object has an &lt;a href=&quot;/questions/235437&quot; target=&quot;_self&quot;&gt;OID&lt;/a&gt; and all class objects are the instances of a root class, so it uses ROOTOID, the OID of the root object, as its class OID.&lt;/p&gt;

&lt;/blockquote&gt;

&lt;p&gt;From the code, you can see that the required intent lock is set on a class object when a lock mode is required for an instance object. And there is &lt;b&gt;a concept of lock waiting time&lt;/b&gt; in the lock mode request. To retrieve the lock timeout value set on the current transaction, the &lt;code&gt;logtb_find_wait_secs()&lt;/code&gt; function is called. CUBRID supports the &lt;code&gt;SET TRANSACTION LOCK TIMEOUT&lt;/code&gt; SQL command and the &lt;code&gt;setLockTimeout()&lt;/code&gt; method in JDBC. The command is to specify the &lt;b&gt;lock timeout&lt;/b&gt; of the current transaction. Lock waiting time means the time for a transaction, which has made a request for lock mode, to wait when a lock mode is set on an object by a transaction and the requested lock is not compatible with the already-set lock mode. As you have seen before, the 2PL concurrency control method does not allow lock from other transactions until the existing lock is released. For the following two reasons, lock timeout should be set by a transaction:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When a user does not want to wait too long because of the lock mode.&lt;/li&gt;
&lt;li&gt;To lower the frequency of deadlock.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;Deadlocks&lt;/h3&gt;

&lt;p&gt;A deadlock occurs when two or more transactions request resources locked by each of them, so all transactions cannot be progressed. &lt;b&gt;Figure 8&lt;/b&gt; below shows an example of a deadlock.&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;img src=&quot;http://www.cubrid.org/files/attach/images/220547/566/507/transaction_deadlock.png&quot; alt=&quot;transaction_deadlock.png&quot; title=&quot;transaction_deadlock.png&quot; class=&quot;iePngFix&quot; width=&quot;700&quot; height=&quot;658&quot; style=&quot;&quot; /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;b&gt;Figure 2: Transaction Deadlock.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;First, &lt;b&gt;Transaction 1&lt;/b&gt;&amp;nbsp;executes&amp;nbsp;&lt;code style=&quot;line-height: normal; &quot;&gt;UPDATE participant SET gold=10 WHERE host_year=2004 AND nation_code=’KOR’&lt;/code&gt;&amp;nbsp;statement and sets&amp;nbsp;&lt;code style=&quot;line-height: normal; &quot;&gt;X_LOCK&lt;/code&gt;&amp;nbsp;on the &lt;code&gt;‘KOR’&lt;/code&gt; record.&amp;nbsp;&lt;b style=&quot;line-height: normal; &quot;&gt;Transaction 2&lt;/b&gt;&amp;nbsp;sets&amp;nbsp;&lt;code style=&quot;line-height: normal; &quot;&gt;X_LOCK&lt;/code&gt;&amp;nbsp;on the&amp;nbsp;&lt;code style=&quot;line-height: normal; &quot;&gt;‘JPN’&lt;/code&gt;&amp;nbsp;record.&amp;nbsp;&lt;b style=&quot;line-height: normal; &quot;&gt;Transaction 3&lt;/b&gt;&amp;nbsp;sets&amp;nbsp;&lt;code style=&quot;line-height: normal; &quot;&gt;X_LOCK&lt;/code&gt;&amp;nbsp;on the&amp;nbsp;&lt;code style=&quot;line-height: normal; &quot;&gt;‘CHN’&lt;/code&gt;&amp;nbsp;record.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;After that,&amp;nbsp;&lt;b&gt;Transaction 1&lt;/b&gt;&amp;nbsp;requests&amp;nbsp;&lt;code&gt;X_LOCK&lt;/code&gt;&amp;nbsp;on the&amp;nbsp;&lt;code&gt;‘JPN’&lt;/code&gt;&amp;nbsp;record for executing&amp;nbsp;&lt;code&gt;UPDATE&lt;/code&gt;&amp;nbsp;for that record. However, the&amp;nbsp;&lt;code&gt;‘JPN’&lt;/code&gt;&amp;nbsp;record is already locked with&amp;nbsp;&lt;code&gt;X_LOCK&lt;/code&gt;&amp;nbsp;by&amp;nbsp;&lt;b&gt;Transaction 2&lt;/b&gt;. So,&amp;nbsp;&lt;b&gt;Transaction 1&lt;/b&gt;&amp;nbsp;should wait until&amp;nbsp;&lt;b&gt;Transaction 2&lt;/b&gt;&amp;nbsp;ends. Based on the 2PL protocol, the&amp;nbsp;&lt;code&gt;X_LOCK&lt;/code&gt;&amp;nbsp;is released when the transaction ends.&amp;nbsp;&lt;b&gt;Transaction 2&lt;/b&gt;&amp;nbsp;requests&amp;nbsp;&lt;code&gt;X_LOCK&lt;/code&gt;&amp;nbsp;on the&amp;nbsp;&lt;code&gt;‘CHN’&lt;/code&gt;record and waits for&amp;nbsp;&lt;b&gt;Transaction 3&lt;/b&gt;. Finally,&amp;nbsp;&lt;b&gt;Transaction 3&lt;/b&gt;&amp;nbsp;waits for&amp;nbsp;&lt;b&gt;Transaction 1&lt;/b&gt;&amp;nbsp;to acquire the&amp;nbsp;&lt;code&gt;&apos;KOR&apos;&lt;/code&gt;&amp;nbsp;record of&amp;nbsp;&lt;b&gt;Transaction 1&lt;/b&gt;&amp;nbsp;as it has&amp;nbsp;&lt;code&gt;X_LOCK&lt;/code&gt;&amp;nbsp;on the&amp;nbsp;&lt;code&gt;‘CHN’&lt;/code&gt;&amp;nbsp;record. As a result,&lt;b&gt;Transaction 1&lt;/b&gt;&amp;nbsp;waits for&amp;nbsp;&lt;b&gt;Transaction 2&lt;/b&gt;&amp;nbsp;to end,&amp;nbsp;&lt;b&gt;Transaction 2&lt;/b&gt;&amp;nbsp;waits for&amp;nbsp;&lt;b&gt;Transaction 3&lt;/b&gt;&amp;nbsp;to end, and&amp;nbsp;&lt;b&gt;Transaction 3&lt;/b&gt;&amp;nbsp;waits for&amp;nbsp;&lt;b&gt;Transaction 1&lt;/b&gt;&amp;nbsp;to end. So, no transaction can be progressed. This is called a&amp;nbsp;&lt;b&gt;deadlock&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Most DBMSs which use the 2PL method,&amp;nbsp;including CUBRID, use the &lt;b&gt;deadlock detection method&lt;/b&gt; to solve the deadlock problem. It periodically checks whether the cycle illustrated in the above figure occurs by drawing a &lt;b&gt;Lock Wait Graph&lt;/b&gt; for the transactions being executed.&lt;/p&gt;

&lt;p&gt;In CUBRID, the thread for detecting deadlock checks the &lt;b&gt;Lock Wait Graph&lt;/b&gt; every second. When a deadlock is detected, one transaction among the transactions is randomly selected and aborted by force. This is called &lt;b&gt;unilateral abort&lt;/b&gt;. When a transaction is selected as a victim to be sacrificed to solve the deadlock and unilaterally aborted, the corresponding SQL statement returns an error code. The error message is &quot;&lt;b&gt;The transaction has timed out due to deadlock while waiting for &lt;code&gt;X_LOCK&lt;/code&gt; for an object. It waited until User 2 ended.&lt;/b&gt;” When an error is returned and the application aborts the transaction, the locks of the transaction are released and other transactions can be continuously processed.&lt;/p&gt;

&lt;p&gt;To see how the deadlock is detected, see the &lt;code&gt;lock_detect_local_deadlock()&lt;/code&gt; function in the source code. This function is called with the intervals (in seconds) specified by the &lt;code&gt;PRM_LK_RUN_DEADLOCK_INTERVAL&lt;/code&gt; variable (the &lt;code&gt;deadlock_detection_interval_in_secs&lt;/code&gt; parameter in&amp;nbsp;&lt;a href=&quot;/manual/90/en/cubrid.conf&quot; target=&quot;_self&quot;&gt;cubrid.conf&lt;/a&gt;&amp;nbsp;file) on the background thread which executes &lt;code&gt;thread_deadlock_detect_thread()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even if a deadlock does not occur, when the execution time of a transaction is too long, other transactions should wait for too long as well. For a certain application, it is wiser to give up rather than wait. In particular, when a web server has called DB tasks and the wait time is too long, all threads of the web server are used to process the DB, so they cannot be used to process external HTTP requests any more, causing service failures. Therefore, for a web application, the threads should be returned without waiting an unlimited amount of time for DB processing even if an error occurs. Two methods are used for that:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One is &lt;b&gt;lock timeout&lt;/b&gt; supported by CUBRID.&lt;/li&gt;
&lt;li&gt; The other is &lt;b&gt;query cancel&lt;/b&gt;. JDBC is defined with an API which can cancel the SQL statement being executed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The key data structure of the lock manager is defined in the &lt;b&gt;&lt;i&gt;lock_manager.c&lt;/i&gt;&lt;/b&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;pre class=&quot;brush:cpp&quot;  title=&quot;&quot;&gt;typedef struct lk_entry LK_ENTRY;
struct lk_entry
{
#if defined(SERVER_MODE)
  struct lk_res *res_head;      /* back to resource entry           */
  THREAD_ENTRY *thrd_entry;     /* thread entry pointer             */
  int tran_index;               /* transaction table index          */
  LOCK granted_mode;            /* granted lock mode                */
  LOCK blocked_mode;            /* blocked lock mode                */
  int count;                    /* number of lock requests          */
  struct lk_entry *next;        /* next entry                       */
  struct lk_entry *tran_next;   /* list of locks that trans. holds  */
  struct lk_entry *class_entry; /* ptr. to class lk_entry           */
  LK_ACQUISITION_HISTORY *history;      /* lock acquisition history         */
  LK_ACQUISITION_HISTORY *recent;       /* last node of history list        */
  int ngranules;                /* number of finer granules         */
  int mlk_count;                /* number of instant lock requests  */
  unsigned char scanid_bitset[1];       /* PRM_LK_MAX_SCANID_BIT/8];       */
#else                           /* not SERVER_MODE */
  int dummy;
#endif                          /* not SERVER_MODE */
};

typedef struct lk_res LK_RES;
struct lk_res
{
  MUTEX_T res_mutex;            /* resource mutex */
  LOCK_RESOURCE_TYPE type;      /* type of resource: class,instance */
  OID oid;
  OID class_oid;
  LOCK total_holders_mode;      /* total mode of the holders */
  LOCK total_waiters_mode;      /* total mode of the waiters */
  LK_ENTRY *holder;             /* lock holder list */
  LK_ENTRY *waiter;             /* lock waiter list */
  LK_ENTRY *non2pl;             /* non2pl list */
  LK_RES *hash_next;            /* for hash chain */
};&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;From the file, the &lt;code&gt;lk_Gl&lt;/code&gt; global variable of &lt;code&gt;LK_GLOBAL_DATA&lt;/code&gt; type is the core. The &lt;code&gt;LK_ENTRY&lt;/code&gt; structure stands for the lock itself. For example, when the &lt;b&gt;Transaction T1&lt;/b&gt; has requested a lock, one &lt;code&gt;LK_ENTRY&lt;/code&gt; is created. &lt;code&gt;LK_RES&lt;/code&gt; is a structure that shows to which resource the lock belongs. In CUBRID, all resources are objects (instance objects and class objects), so they are shaped as OIDs. In the &lt;code&gt;LK_RES&lt;/code&gt; structure, you can see the list of holders with &lt;code&gt;LK_ENTRY&lt;/code&gt; type and the list of waiters. The list of holders is a list of transactions that hold the lock for the resource now. For example, when &lt;b&gt;Transaction T1&lt;/b&gt; and &lt;b&gt;Transaction T2&lt;/b&gt; have acquired &lt;code&gt;S_LOCK&lt;/code&gt; for the data record with OID1, &lt;code&gt;LK_ENTRY&lt;/code&gt; that corresponds to the &lt;code&gt;S_LOCK&lt;/code&gt; of &lt;b&gt;T1&lt;/b&gt; and &lt;b&gt;T2&lt;/b&gt; will be registered in the list of holders. When &lt;b&gt;Transaction T3&lt;/b&gt; requests &lt;code&gt;X_LOCK&lt;/code&gt; on the OID1 record, &lt;b&gt;T3&lt;/b&gt; should wait because of the existing &lt;code&gt;S_LOCK&lt;/code&gt;. So, the &lt;code&gt;LK_ENTRY&lt;/code&gt; corresponding to &lt;code&gt;X_LOCK&lt;/code&gt; of T3 will be registered to the list of waiters. Which lock is held by which transaction is maintained in the &lt;code&gt;tran_lock_table&lt;/code&gt; variable which has the &lt;code&gt;LK_TRAN_LOCK&lt;/code&gt; structure as a table.&lt;/p&gt;

&lt;p&gt;The &lt;b&gt;Wait For Graph&lt;/b&gt; for detecting a deadlock is expressed as &lt;code&gt;TWFG_node&lt;/code&gt; and &lt;code&gt;TWFG_edge&lt;/code&gt; of the &lt;code&gt;LK_WFG_NODE&lt;/code&gt; structure and the &lt;code&gt;LK_WFG_EDGE&lt;/code&gt; structure. The &lt;code&gt;lock_detect_local_deadlock()&lt;/code&gt; function creates a &lt;b&gt;Wait For Graph&lt;/b&gt; and detects whether there is a cycle on the graph. When a cycle is detected, the &lt;code&gt;lock_select_deadlock_victim()&lt;/code&gt; function selects a victim transaction to be sacrificed for solving the deadlock. For reference, transactions are continuously executed while a &lt;b&gt;Wait For Graph&lt;/b&gt; is drawn up and checked, the information of the ended transaction is removed from the graph. The victim transaction is selected based on the following criteria:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a transaction is not a holder, it cannot be a victim.&lt;/li&gt;
&lt;li&gt;When a transaction is in the commit phase or the rollback phase, it cannot be selected as a victim.&lt;/li&gt;
&lt;li&gt;Select a transaction of which lock timeout is not set to -1 (unlimited waiting) first.&lt;/li&gt;
&lt;li&gt;Select the latest transaction rather than the older one. (The transaction ID is an incremental number. A transaction with smaller transaction number is the older one.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;This concludes the talk about Two-Phase Locking in CUBRID. I briefly covered the types of concurrency control, the difference between 2PL and MVCC, about what locking technique is used in CUBRID RDBMS, about locking modes and their compatibility, and finally, the deadlocks and the solution for them.&lt;/p&gt;

&lt;p&gt;In this article I have mentioned about OID (Object Identifiers) which are used to identify instance objects as well as class objects. In the next article I will continue this talk and explain what Object, Class, and OID are.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/div&gt;</content>
                  <category term="CUBRID Internals"/>
            <category term="Locking"/>
            <category term="2PL MVCC"/>
            <category term="Two-Phase Locking"/>
            <category term="Multi-Version Concurrency Control"/>
            <category term="table lock"/>
            <category term="OID"/>
            
   </entry>
</feed> 
