+ All Categories
Home > Documents > IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan...

IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan...

Date post: 24-Mar-2020
Category:
Upload: others
View: 0 times
Download: 0 times
Share this document with a friend
15
Transcript
Page 1: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia
Page 2: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

ISSN 1979-2484 (Print) ISSN 2460-7010 (Online)

Editor in ChiefFergyanto E. Gunawan

Associate EditorsSatryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Ngoc Thank Nguyen, Wroclaw University of Technology, Wroclaw, PolandHiroomi Homma, Toyohashi University of Technology, Japan

Yasuhiro Kanto, Ibaraki University, Japan

Executive Editors Arta Moro Sundjaja

Noerlina

Language Editors and Setters Karen PhangDina Nurfitria

HolilAtmawati

SecretariatHaryo Sutanto

Eka Yanti Pangputri

Aims and ScopeJournal of Communication and Information Technology (CommIT) focuses on various issues spanning: software engineering, mobile technology and applications, robotics, database system, information engineering, artificial intelligent, interactive multimedia, computer networking, information system audit, accounting information system, information technology investment, information system development methodology, strategic information system (business intelligence, decision support system, executive information system, enterprise system, knowledge management), e-learning, and e-business (e-health, e-commerce, e-supply chain management, e-customer relationship management, e-marketing, and e-government). The journal is published in affiliation with the Research and Technology Transfer Office (RTTO), Bina Nusantara University, Jl. Kebon Jeruk Raya no. 27, Jakarta 11530, Indonesia.

PublicationsCommIT Journal (ISSN 1979-2484) is published binually by the Research and Technology Transfer Office (RTTO) Bina Nusantara University at Kampus Anggrek, Jl. Kebon Jeruk Raya No. 27, Kemanggisan/Palmerah, Jakarta Barat 11530, telp. (021) 5327630, ext. 1708, e-Mail: [email protected]. Home page: http://journal.binus.ac.id/index.php/commit

Vol. 10 No.1 May 2016

Page 3: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

ISSN 1979-2484 (Print) ISSN 2460-7010 (Online)

Contents

Josef Bernadi; SuharjitoExecutive Information System Modelling to Monitor Indonesian Criminal Rate 1-7

Hansel Bagus Tritama; Riswan Efendi TariganThe Effect of Social Media to the Brand Awareness of A Product of A Company 9-14

Oscar KarnalimImproving Scalability of Java Archive Search Engine through Recursion Conversion and Multithreading 15-26

Ghouraf Djamel EddinePower System Stabilizer Design Based on A Particle Swarm Optimization Multiobjective Function Implemented Under Graphical Interface 27-33

Harry DhikaDevelopment of Model for Providing Feasible Scholarship 35-39

Andri Wijaya; Abba Suganda GirsangThe Use of Data Mining for Prediction of Customer Loyalty 41-47

Vol. 10 No.1 May 2016

Page 4: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

CommIT (Communication & Information Technology) 10(1), 15–26, 2016

IMPROVING SCALABILITY OF JAVAARCHIVE SEARCH ENGINE THROUGH

RECURSION CONVERSION ANDMULTITHREADING

Oscar KarnalimProgram of Information Technology, Faculty of Information Technology,

Maranatha Christian University, Bandung 40164, IndonesiaEmail: [email protected]

Abstract—Based on the fact that bytecode always existson Java archive, a bytecode based Java archive searchengine had been developed [1, 2]. Although the system isquite effective, it still lacks of scalability because manymodules applying recursive calls and the system onlyutilizes one core (single thread). In this research, Javaarchive search engine architecture is redesigned in orderto improve its scalability. All recursions are convertedinto iterative forms although most of these modulesare logically recursive and quite difficult to convert(e.g., Tarjan’s strongly connected component algorithm).Recursion conversion can be conducted by following itsrespective recursive pattern. Each recursion is brokendown to four parts (before and after actions of currentand its children) and converted to iteration with the helpof caller reference. This conversion mechanism improvesscalability by avoiding stack overflow error caused bymethod calls. System scalability is also improved byapplying multithreading mechanism which successfullycut off its processing time. Shorter processing time mayenable system to handle larger data. Multithreading isapplied on major parts which are indexer, vector spacemodel (VSM) retriever, low-rank vector space model(LRVSM) retriever, and semantic relatedness calculator(semantic relatedness calculator also involves multipro-cess). The correctness of both recursion conversion andmultithread design are proved by the fact that allimplementation yield similar result.Keywords: Scalability; Recursion Conversion; Multi-threading; Java Archive Search Engine; Multiprocess.

I. INTRODUCTION

Scalability is a prominent factor in a search enginedevelopment since the size of index data the searchengine may grow rapidly [3]. Many techniques are ap-plied to handle data growth such as algorithm optimiza-tion, preprocessing, multithreading, and parallelism.

Received: March 22, 2016; received in revised form: March 28,2016; accepted: March 30, 2016; available online: April 4, 2016.

Based on the fact that bytecode always exists onJava archive, a bytecode based Java archive searchengine had been developed [1]. The system utilizesbytecode on Java archive as its primary informationsource and extracts many textual information on classfiles as document terms through reverse engineeringmechanism (e.g., class name, field name, method name,control flow weighted string literals in method content,and method calls). Its retrieval model is also embeddedwith relatedness in order to improve its recall [2].Although the system works well, it still lacks ofscalability since many modules are applying recursivecalls and the system is single threaded.

Since recursion generates many function calls andeach function call is pushed on stack to keep the trackof the program flow [4], recursive calls may yield stackoverflow error in Java environment. Stack overflowerror occurs when memory stored in JVM stack islarger than its size [5]. This error can be avoided byconverting all recursive algorithms to its iterative form.However, some algorithms are logically recursive andinconvenient enough to design it on iterative manner(e.g., Tarjan algorithm for detecting strongly connectedcomponents on graph [6]). Although logically recur-sive algorithms are exceptional cases where recursiveapproach is more beneficial than iterative approach insoftware development [7], these algorithms are stillneeded to be converted in order to avoid stack overflowerror.

As hardware technologies advances, many regularcomputers are backed up with multi core processorswhich enable operating system to complete many taskat a time using multithreading [8]. Liu & Wang [9]applied multithreading on their ensemble learning in

Page 5: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.order to filter spam in Short Message Services (SMS).Their multithread design runs faster than single threaddesign which strengthens the proof that multithreadmay reduce processing time. This mechanism mayalso be utilized to reduce time latency in many searchengine tasks such as indexing and retrieving docu-ments [10–12].

In this research, a bytecode based java archivesearch engine is designed in more scalable way whichinvolve recursion conversion and multithreading. Threemain recursive algorithms which are converted to itsiterative form are loop encapsulation, recursive methodelimination, and method expansion. These algorithmsare needed at indexing phase in order to extract methodcontents. The search engine architecture is also re-designed as multithread search engine to diminish itsprocessing time.

II. METHODS

A. Recursion Conversion

It is known that all algorithms can be implementedrecursively or iteratively [13]. Some algorithms aremore convenient to be implemented with iterativeapproach whereas the others are more convenient to bedesigned as recursive one. Many nave and straightfor-ward algorithms such as sequential searching, sorting,and string processing are easier to be implementediteratively. However, some permutation and combina-torial problems are easier to solve recursively (e.g.,map coloring, insertion on binary tree, and traversingall nodes in graph).

Recursive algorithms converted in this research arelogically recursive. Loop encapsulation is designedsimilar to Depth First Search (DFS) pattern and uti-lizes Tarjans Strongly Connected Component (SCC)algorithm for loop detection. Recursive method elimi-nation also utilizes similar Tarjan’s algorithm to detectrecursive methods although they do not share thesame data type. Therefore, object oriented techniquecalled Generics is applied in order to enable Tarjan’sSCC algorithm takes various data types on its pro-cess without explicit typecasting. Method expansion isdesigned in recursive dynamic programming mannerwhich never re-expand already-expanded method to cutoff its processing time. Since stack overflow error is thebiggest issue in recursive implementation, especiallyon large scale recursion [4, 5]. Therefore, all recursiveimplementation in this research will be converted asiterative one to improve the program scalability.

For clarity at conversion phase, some recursive partsof algorithm in both implementation are marked withdifferent color which details can be seen in Table I.

Abbrevations are also given for each description tosimplify the illustration.

B. Loop Encapsulation

Loop encapsulation encapsulates loops based onMiecznikowski’s algorithm [1, 14]. Loop encapsula-tion example can be seen in Fig. 1. This moduletakes control flow graph as its argument and utilizesMiecznikowski’s to detect loop candidates. All nodeswhich is a member of certain loop are wrapped andmerged as one loop node. Loop node is a wrapperwhich consists of loop member nodes and inheritsits successors / predecessors. This loop replacementmechanism is conducted repeatedly from inner-mostloops until no more loop exists.

Recursive implementation of loop encapsulationmodule can be seen in Alg. 1. Control Flow Graph(CFG) is represented as array of Control Flow (CF)nodes which will be broke down as a bunch of sub-

TABLE IRECURSIVE PARTS COLOR DETAILS.

Color Description

Blue Current process before processing itschildren (B)

Red Current process after processing its chil-dren (A)

Green Current children’s process before recur-sion (CB)

Brown Current children’s process after recusion(CA)

2 5 8 R423930272421189

Initial Control Flow Graph

2 5 8 R423930272421189

Loop Detector Result

2 5 R423930272421

Inner Loop Encapsulation

A

B RC

Outer Loop Encapsulation

Fig. 1. Loop encapsulation example.

16

Page 6: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

graph based on Tarjan’s algorithm (getSCC function).Each subgraph which consists of more than one nodeis considered as loop candidates and its respectiveconditional node is removed. Removing conditionalnodes is required to detect inner loop on remainingnodes by executing similar mechanism recursively.

Converting loop encapsulation to iterative form isquite simple since this algorithm follows simple DFSpattern (without A and CA parts). Simple DFS patterncan be remodeled to iterative form with the help of astack and a while loop (which are used to keep trackof recursive calls). Iterative loop encapsulation can beseen in Alg. 2 where each recursive call is replaced bypushing its recursive argument on a stack. B and CBare translated as loop action whereas each element onstack is popped and processed until the stack is empty.

C. Recursive Method Elimination

Recursive method elimination removes all recursivemethods from method expansion candidates since allrecursion may yield endless method expansion (eachexpansion consists of additional recursive call). Thismodule takes method list as its argument, augmentsit as method graph, detects recursion candidates, andremoves them from method expansion candidates.Method graph is augmented from method calls whereeach method is converted to a node and a method call

Algorithm 1 Recursive Loop Encapsulation.

engine tasks such as indexing and retrieving documents [10, 11, 12].

In this research, a bytecode based java archive search engine is designed in more scalable way which involve recursion conversion and multithreading. Three main recursive algorithms which are converted to its iterative form are loop encapsulation, recursive method elimination, and method expansion. These algorithms are needed at indexing phase in order to extract method contents. The search engine architecture is also redesigned as multithread search engine to diminish its processing time. METHOD Recursion Conversion It is known that all algorithms can be implemented recursively or iteratively [13]. Some algorithms are more convenient to be implemented with iterative approach whereas the others are more convenient to be designed as recursive one. Many naïve and straightforward algorithms such as sequential searching, sorting, and string processing are easier to be implemented iteratively. However, some permutation and combinatorial problems are easier to solve recursively (e.g. map coloring, insertion on binary tree, and traversing all nodes in graph).

Recursive algorithms converted in this research are logically recursive. Loop encapsulation is designed similar to depth first search (DFS) pattern and utilizes Tarjan’s strongly connected component (SCC) algorithm for loop detection. Recursive method elimination also utilizes similar Tarjan’s algorithm to detect recursive methods although they do not share the same data type. Therefore, Object oriented technique called Generics is applied in order to enable Tarjan’s SCC algorithm takes various data types on its process without explicit typecasting. Method expansion is designed in recursive dynamic programming manner which never re-expand already-expanded method to cut off its processing time. Since stack overflow error is the biggest issue in recursive implementation, especially on large scale recursion [4, 5]. Therefore, all recursive implementation in this research will be converted as iterative one to improve the program scalability.

For clarity at conversion phase, Some recursive parts of algorithm in both implementation are marked with different color which details can be seen in Table 1. Abbrevations are also given for each descirption to simplify the illustration.

Loop Encapsulation Loop encapsulation encapsulates loops based on Miecznikowski’s algorithm [1, 14]. Loop encapsulation example can be seen in Fig. 1. This module takes control flow graph as its argument

and utilizes Miecznikowski’s to detect loop candidates. All nodes which is a member of certain loop are wrapped and merged as one loop node. Loop node is a wrapper which consists of loop member nodes and inherits its successors / predecessors. This loop replacement mechanism is conducted repeatedly from inner-most loops until no more loop exists.

Table 1: Recursive parts color details

Color Description Blue Current process before processing its

children (B) Red Current process after processing its

children (A) Green Current children’s process before

recursion (CB) Brown Current children’s process after

recursion (CA)

Fig 1: Loop encapsulation example

Recursive implementation of loop

encapsulation module can be seen in Fig. 2. Control flow graph (CFG) is represented as array of control flow (CF) nodes which will be broke down as a bunch of subgraph based on Tarjan’s algorithm (getSCC function). Each subgraph which consist of more than one nodes is considered as loop candidates and its respective conditional nodes are removed. Removing conditional nodes is required to detect inner loop on remaining nodes by execute similar mechanism recursively.

procedure encapsLoopR(nodeList :CF[]) | CF[][] sccList= getSCC(nodelist) | for each scc in sccList | | if(scc.length > 1) | | | encapsulate scc as loop node | | | detectLoopType(scc) | | | removeConditionalNodes(scc) | | | encapsulateLoopR(scc) | | end if | end for end procedure

Algorithm 2 Iterative Loop Encapsulation.

Fig 2: Recursive loop encapsulation Converting loop encapsulation to iterative

form is quite simple since this algorithm follows simple DFS pattern (without A and CA parts). Simple DFS pattern can be remodeled to iterative form with the help of a stack and a while loop (which are used to keep track of recursive calls). Iterative loop encapsulation can be seen in Fig. 3 where each recursive calls are replaced by pushing its recursive argument on a stack. B and CB are translated as loop action whereas each elements on stack are popped and processed until the stack is empty.

Fig 3: Iterative loop encapsulation

Recursive Method Elimination Recursive method elimination removes all recursive methods from method expansion candidates since all recursion may yield endless

method expansion (each expansion consists of additional recursive call). This module takes method list as its argument, augments it as method graph, detects recursion candidates, and removes them from method expansion candidates. Method graph is augmented from method calls where each method is converted to a node and a method call is converted as an edge from caller to called method. Since this module only apply recursion on its Tarjan’s SCC algorithm, This module will not be discussed further.

Tarjan’s SCC Algorithm Since loop encapsulation and recursive method elimination involve SCC detection on their graph respectively, Tarjan’s SCC algorithm is also converted to iterative form. Tarjan’s SCC algorithm applies Generic which enables this module to take various data types on its process without explicit typecasting. Generics is a Java feature which enable developer to use same class for many kind of data types without using explicit typecasting [15].

Tarjan’s SCC algorithm is logically recursive which is quite difficult to convert it as iterative algorithm. This algorithm also has all recursive algorithm parts which declared at Table 1 (B, A, CB, and CA). Tarjan’s recursive implementation can be seen in Fig. 4. This algorithm can be conducted by calling getSCC. Index and lowlink of each node are used to detect SCC wherein -1 stands for unprocessed nodes. Index variable in this algorithm is considered as global variable.

Fig 4: Recursive Tarjan’s SCC algorithm

function getSCC(nodeList:T[]) : T[][] | T[][] sccList; Stack s; int index = 0 | for each node in nodeList | | if(node.index = -1) | | | constructSCC(node, sccList, s, index, nodeList) | | end if | end for | return sccList end function procedure constructSCC(node : T, sccList : T[][], s : Stack, index : int, nodeList : T[]) | node.index = index; node.lowlink = index | stack.push(node); index = index + 1 | for each successor suc of nodein nodeList | | if(suc.index == -1) | | | constructSCC(suc, sccList, stack, index, nodeList) | | | node.lowlink = min(suc.lowlink, node.lowlink) | | else if(suc.onStack) | | | node.lowlink = min(suc.index, node.lowlink) | | end if | end for | if(node.index = node.lowLink) | | T[] scc; T n | | do{ | | | n = stack.pop(); | | | scc.add(n) | | }while(node != n) | | sccList.add(scc) | end if end procedure

procedure encapsLoopI(nodeList : CF[]) | Stack s | s.push(nodeList) | while(s is not empty) | | CF[] tmp = s.pop() | | CF[][] sccList = getSCC(tmp) | | for each scc in sccList | | | if(scc.length > 1) | | | | encapsulate scc as loop node | | | | detectLoopType(scc) | | | | removeConditionalNodes(scc) | | | | s.push(scc) | | | end if | | end for | end while end procedure

is converted as an edge from caller to called method.Since this module only apply recursion on its TarjansSCC algorithm, This module will not be discussedfurther.

D. Tarjan’s SCC Algorithm

Since loop encapsulation and recursive method elim-ination involve SCC detection on their graph respec-tively, Tarjan’s SCC algorithm is also converted toiterative form. Tarjan’s SCC algorithm applies Genericwhich enables this module to take various data typeson its process without explicit typecasting. Genericsis a Java feature which enables developer to use sameclass for many kind of data types without using explicittypecasting [15].

Tarjans SCC algorithm is logically recursive whichis quite difficult to convert it as iterative algorithm.This algorithm also has all recursive algorithm partswhich declared at Table I (B, A, CB, and CA). Tarjansrecursive implementation can be seen in Alg. 3. Thisalgorithm can be conducted by calling getSCC. Indexand lowlink of each node are used to detect SCCwherein −1 stands for unprocessed nodes. Indexvariable in this algorithm is considered as global vari-able.

Despite of its iterative conversion difficulty, this al-gorithm still can be converted by imitating its recursivepatterns with the help of caller reference. Tarjan’siterative implementation can be seen in Alg. 4. Thisimplementation follows some rules which are:

• Each data tuple is encapsulated as IterTuple whichhas an additional field called caller reference.Caller reference is used to keep track of its recur-sive pattern and to perform its “after recursion”part (A and CA).

• Procedure call of constructSCC is replacedby a loop which perform similar pattern asconstructSCC.

• Current process is stored in cur and each re-cursive call is replaced by assigning cur withits recursive process (which is similar to let thisprocess visit its child first).

• A and CA parts are conducted after all of itssuccessor are “recursively” processed. A part isconducted first before CA part since CA partconducted in this phase is its parent process’s CA(parent process is accessed using caller reference).

E. Method Expansion

Method expansion unwrap all method encapsula-tion by replacing all method calls with its respectivemethod contents until no more method call exists(which is quite similar to method inlining [16]). This

17

Page 7: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

Algorithm 3 Recursive Tarjan’s SCC Algorithm.

Fig 2: Recursive loop encapsulation Converting loop encapsulation to iterative

form is quite simple since this algorithm follows simple DFS pattern (without A and CA parts). Simple DFS pattern can be remodeled to iterative form with the help of a stack and a while loop (which are used to keep track of recursive calls). Iterative loop encapsulation can be seen in Fig. 3 where each recursive calls are replaced by pushing its recursive argument on a stack. B and CB are translated as loop action whereas each elements on stack are popped and processed until the stack is empty.

Fig 3: Iterative loop encapsulation

Recursive Method Elimination Recursive method elimination removes all recursive methods from method expansion candidates since all recursion may yield endless

method expansion (each expansion consists of additional recursive call). This module takes method list as its argument, augments it as method graph, detects recursion candidates, and removes them from method expansion candidates. Method graph is augmented from method calls where each method is converted to a node and a method call is converted as an edge from caller to called method. Since this module only apply recursion on its Tarjan’s SCC algorithm, This module will not be discussed further.

Tarjan’s SCC Algorithm Since loop encapsulation and recursive method elimination involve SCC detection on their graph respectively, Tarjan’s SCC algorithm is also converted to iterative form. Tarjan’s SCC algorithm applies Generic which enables this module to take various data types on its process without explicit typecasting. Generics is a Java feature which enable developer to use same class for many kind of data types without using explicit typecasting [15].

Tarjan’s SCC algorithm is logically recursive which is quite difficult to convert it as iterative algorithm. This algorithm also has all recursive algorithm parts which declared at Table 1 (B, A, CB, and CA). Tarjan’s recursive implementation can be seen in Fig. 4. This algorithm can be conducted by calling getSCC. Index and lowlink of each node are used to detect SCC wherein -1 stands for unprocessed nodes. Index variable in this algorithm is considered as global variable.

Fig 4: Recursive Tarjan’s SCC algorithm

function getSCC(nodeList:T[]) : T[][] | T[][] sccList; Stack s; int index = 0 | for each node in nodeList | | if(node.index = -1) | | | constructSCC(node, sccList, s, index, nodeList) | | end if | end for | return sccList end function procedure constructSCC(node : T, sccList : T[][], s : Stack, index : int, nodeList : T[]) | node.index = index; node.lowlink = index | stack.push(node); index = index + 1 | for each successor suc of nodein nodeList | | if(suc.index == -1) | | | constructSCC(suc, sccList, stack, index, nodeList) | | | node.lowlink = min(suc.lowlink, node.lowlink) | | else if(suc.onStack) | | | node.lowlink = min(suc.index, node.lowlink) | | end if | end for | if(node.index = node.lowLink) | | T[] scc; T n | | do{ | | | n = stack.pop(); | | | scc.add(n) | | }while(node != n) | | sccList.add(scc) | end if end procedure

procedure encapsLoopI(nodeList : CF[]) | Stack s | s.push(nodeList) | while(s is not empty) | | CF[] tmp = s.pop() | | CF[][] sccList = getSCC(tmp) | | for each scc in sccList | | | if(scc.length > 1) | | | | encapsulate scc as loop node | | | | detectLoopType(scc) | | | | removeConditionalNodes(scc) | | | | s.push(scc) | | | end if | | end for | end while end procedure

mechanism is applied to reweight terms since termsused in frequently called methods should have greaterweight based on its occurences. Each inserted methodcontent is also weighted by its prior method call weightin order to keep its relevancy to its caller method.Since recursive calls may yield unlimited loop duringexpansion phase, recursive methods are marked andonly expanded at N times (N is defined as a parameterat indexing phase).

Method expansion applies dynamic programming tospeed up its process. Each method is only expandedonce and all unexpanded method which is called inmethod content is expanded first. This module isinitially implemented with recursive approach becauseof its natural recursive logic. Recursive implementationof method expansion can be seen in Alg. 5 where itsiterative form can be seen in Alg. 6. Conversion ofthis module imitates Tarjans SCC algorithm conversionwhere each tuple is encapsulated as IterTuple with anadditional field caller reference. Although copying allterm in method with nID to mtt is considered both Aand CA parts, this instruction still can be converted byduplicating its instruction (The first one is for A partwhereas the second one is for CA part).

F. Multithread Design

It is obvious to state that single thread program inmulti core processor is not efficient enough since itonly utilizes one core. To utilize all cores, program

must apply multithreading mechanism which let pro-gram to do tasks at many different cores at the sametime. Therefore, program developed in this research isredesigned to multithread manner in order to cut offits processing time. Two major parts are redesignedwhich are indexer and retriever. Indexer part conversionis quite simple since its jobs can be split based ondocuments (Java archives). Retriever part involves tworetriever mechanism which are VSM and LRVSM.Unlike indexer part, this module requires some globalcalculation after multithreading to yield similar resultas sequential one. In addition, semantic relatednesscalculator between term pairs is also redesigned inmultithread manner since semantic relatedness is re-quired at EVSM retriever.

G. Multithread Indexer

Since document-partitioned indexes are more fre-quently used than term-partitioned indexes in mostsearch engines [17], multithread indexing developedin this research are based on document-partitionedindexes. Documents (Java archives) are split and in-dexed separately using many threads at the same time.Because document-partitioned indexes assures that allindexes are not tightly-coupled to each other, error-neous indexes only affect the indexed documents andthe re-index phase will not affect remaining indexes.Therefore, it may yields faster index error correction.

18

Page 8: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

Algorithm 4 Iterative Tarjan’s SCC Algorithm.

International Journal of Communication & Information Technology (CommIT) Vol x (yy), pp 31- Despite of its iterative conversion difficulty,

this algorithm still can be converted by imitating its recursive patterns with the help of caller reference. Tarjan’s iterative implementation can be seen in Fig. 5. This implementation follows some rules which are:

a. Each data tuple is encapsulated as IterTuple which has an additional field called caller reference. Caller reference is used to keep track of its recursive pattern and to perform its “after recursion” part (A and CA).

b. Procedure call of constructSCC is replaced by a loop which perform similar pattern as constructSCC.

c. Current process is stored in cur and each recursive call is replaced by assigning cur with its recursive process (which is similar to let this process visit its child first).

d. A andCA parts are conducted after all of its successor are “recursively” processed. A part is conducted first before CA part since CA part conducted in this phase is its parent process’s CA (parent process is accessed using caller reference).

Method Expansion Method expansion unwrap all method encapsulation by replacing all method calls with its respective method contents until no more method call exists (which is quite similar to method inlining [16]). This mechanism is applied to reweight terms since terms used in frequently called methods should have greater weight based on its occurences. Each inserted method content is also weighted by its prior method call weight in order to keep its relevancy to its caller method. Since recursive calls may yield unlimited loop during expansion phase, recursive methods are marked and only expanded at N times (N is defined as a parameter at indexing phase).

Fig 5: Iterative Tarjan’s SCC algorithm

function getSCC(nodeList : T[]): T[][] | T[][] scc | int index = 0 | Stack stack | for each node in nodeList | | if(node.index == -1) | | | IterTuple cur | | | cur.node = node; cur.caller = null | | | cur.node.index = index; cur.node.lowlink = index | | | stack.push(cur); index = index + 1 | | | while(true) | | | | if(cur.node has unprocessed successors which is nodeList member) | | | | | IterTuple next | | | | | next.node = cur.node.getNextUnprocessedNode(); next.caller = cur | | | | | if(nodeList.contains(next.node)) | | | | | | if(next.node.index == -1) | | | | | | | next.node.index = index; next.node.lowlink =index | | | | | | | stack.push(next); index = index + 1 | | | | | | | cur = next | | | | | | else if(next.node.onStack) | | | | | | | cur.node.lowlink = min(cur.node.lowlink, next.node.index) | | | | | |end if | | | | else | | | | | if(cur.node.index = cur.node.lowlink) | | | | | | T[] scc; IterTuple top | | | | | | do{ | | | | | | | top = stack.pop() | | | | | | | scc.add(top.node) | | | | | | }while(top.node.index != cur.node.index) | | | | | | sccList.add(scc) | | | | | end if | | | | | IterTuple caller = cur.caller | | | | | if(caller != null) | | | | | | caller.node.lowlink = min(caller.node.lowlink, cur.node.lowlink) | | | | | | cur = caller | | | | | else break | | | | | end if | | | |end if | | |end while | | end if | end for | return sccList end function

Documents are partitioned based on greedy load-balance mechanism which can be seen in Alg. 7.The number of initialized stacks is similar with thenumber of expected jobs wherein each document isplaced on the lowest document size stack at that time.This mechanism intends to distribute documents evenlyamong all jobs with greedy approach. Although greedyapproach does not always yield the best result, it mayyield fairly good distribution among all jobs at lineartime. Greedy approach is extremely faster than bruteforce approach which complexity is O(N!).

Multithread indexer design can be seen in Fig. 2. Alldocuments are listed and distributed based on greedyload-balance algorithm. Since each job yields an indexbased on its given documents, this mechanism willresult many indexes rather than one. These indexesneed not to be merged as one since split indexes mayyields faster index error correction with the help ofdistribution list. Distribution list is a comma separated

Document Enlistment

Job Distribution

. . .

Ind

ex1

Ind

exe

r 1

Ind

exe

r 2

Ind

exe

r 3

Ind

exe

r N

Ind

ex2

Ind

ex3

Ind

exN

Dis

trib

utio

n L

ist

Fig. 2. Multithread Indexer Design.

values file that contain document list for each job. Thisfile is also generated at indexing phase. Any weightingschemes conducted in previous sequential design aredelayed to retriever part based on these reasons:

• Storing raw indexes is more scalable than pro-cessed one since various weighting schemes may

19

Page 9: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

Algorithm 5 Recursive Method Expansion Algorithm.

International Journal of Communication & Information Technology (CommIT) Vol x (yy), pp 31-

Method expansion applies dynamic programming to speed up its process. Each method is only expanded once and all unexpanded method which is called in method content is expanded first. This module is initially implemented with recursive approach because of its natural recursive logic. Recursive implementation of method expansion can be seen in Fig. 6 where its iterative form can be seen in Fig. 7. Conversion of this module imitates Tarjan’s SCC algorithm conversion where each tuple is encapsulated as IterTuple with an additional field caller reference. Although copying all term in method with nID to mtt is considered both A and CA parts, this instruction still can be converted by duplicating its instruction (The first one is for A part whereas the second one is for CA part).

Multithread Design It is obvious to state that single thread program in multi core processor is not efficient enough since it only utilize one core. To utilize all cores, program must apply multithreading mechanism which let program to do tasks at many different cores at the same time. Therefore, program developed in this research is redesigned to multithread manner in order to cut off its processing time. Two major parts are redesigned which are indexer and retriever. Indexer part conversion is quite simple since its jobs can be split based on documents (Java archives). Retriever part involves two retriever mechanism which are VSM and LRVSM. Unlike indexer part, this module

require some global calculation after multithreading to yield similar result as sequential one. In addition, semantic relatedness calculator between term pairs is also redesigned in multithread manner since semantic relatedness is required at EVSM retriever.

Multithread Indexer Since document-partitioned indexes are more frequently used than term-partitioned indexes in most search engines [17], multithread indexing developed in this research are based on document-partitioned indexes. Documents (Java archives) are split and indexed separately using many threads at the same time. Because document-partitioned indexes assures that all indexes are not tightly-coupled to each other, errorneous indexes only affect its indexed documents and re-index phase will not affect remaining indexes. Therefore, it may yields faster index error correction.

Documents are partitioned based on greedy load-balance mechanism which can be seen in Fig. 8. The number of initialized stacks is similar with the number of expected jobs wherein each document is placed on the lowest document size stack at that time. This mechanism intends to distribute documents evenly among all jobs with greedy approach. Although greedy approach does not always yield the best result, it may yield fairly good distribution among all jobs at linear time. Greedy approach is extremely faster than brute force approach which complexity is O(N!).

Fig 6: Recursive method expansion algorithm

function expand(beforeList : Data) : Data | Data afterList | for each method with id curID in beforeList | | methodExpansion(curID, beforeList, afterList) | return afterList end function procedure methodExpansion(curID : MethodID, beforeList : Data, afterList : Data) | if(afterList does not contain method with curID) | | ExpandedMethod mtt | | ScoreTuple[] sList = get score tuple list of method with curID from beforeList | | for each ScoreTuple st in sList | | | if(st is string literal) | | | | mtt.add(st) | | | else // st is method call | | | | MethodID nID = st.getMethodID() | | | | if(beforeList contains method with nID) // need to be expanded | | | | | if(afterList does not contain method with nID) // not expanded yet | | | | | | methodExpansion(curID, beforeList, afterList) | | | | | end if | | | | | copy all term in method with nID to mtt// also included as CA part | | | | end if | | | end if | | end for | | afterList.add(mtt) | end if end procedure

Algorithm 6 Iterative Method Expansion Algorithm.

Fig 7: Iterative method expansion algorithm

Fig 8: Greedy load-balance algorithm Multithread indexer design can be seen in

Fig. 9. All documents are listed and distributed based on greedy load-balance algorithm. Since each job yields an index based on its given documents, this mechanism will result many indexes rather than one. These indexes need not to be merged as one since split indexes may yields faster index error correction with the help of distribution list. Distribution list is a comma separated values file that contain document list for each job. This file is also generated at indexing phase.

Any weighting schemes conducted in previous sequential design are delayed to retriever part based on these reasons :

a. Storing raw indexes is more scalable than processed one since various weighting

schemes may be applied without re-indexing.

b. Index error correction may be simplified since it only focus on errorneous indexes and its respective documents.

c. Many additional indexes can be embedded during retrieval phase without modifying preexisting indexes.

Fig 9: Multithread indexer design

Multithread Retriever In this research, two retrieval models are redersigned in multithread manner. These retrieval

functionsplitJob(path : String, n : int) | Stack[] jobs = new Stack[n] | for eachfile finpath | | if(f is Java archive) | | | minIdx = get lowest sJobs index | | | jobs[minIdx].add(f) | |end if | end for end function

function expand(beforeList : Data) : Data | Data afterList | for each method with id curID in beforeList | | methodExpansion(curID, beforeList, afterList) | return afterList end function procedure methodExpansion(curID : MethodID, beforeList : Data, afterList : Data) | if(afterList does not contain method with curID) | | IterTuple cur | | cur.id = curID; cur.caller = null | | cur.sList = get score tuple list of method with cur.id from beforeList | | while(true) | | | if(cur.sList has unprocessed ScoreTuple) | | | | ScoreTuple st = cur.sList.getNextUnprocessedScoreTuple() | | | | if(st is string literal) | | | | | cur.mtt.add(st) | | | | else// st is method call | | | | | MethodID nID = st.getMethodID() | | | | | if(beforeList contains method with nID) // need to be expanded | | | | | | if(afterList does not contain method with nID) // notexpanded yet | | | | | | | IterTuple next | | | | | | | next.id = nID; next.caller = cur | | | | | | | next.sList = get score tuple list of method with next.id from beforeList | | | | | | | cur = next | | | | | | else | | | | | | | copy all term in method with nID to cur.mtt | | | | | | endif | | | | | endif | | | | end if | | | else | | | | afterList.add(cur.mtt) | | | | if(cur.caller != null) | | | | | insert all term in method with cur.id to cur.caller.mtt at its respective pos | | | | else break | | | | end if | | | end if | | end while | end if end procedure

20

Page 10: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

Algorithm 7 Greedy Load-Balance Algorithm.

Fig 7: Iterative method expansion algorithm

Fig 8: Greedy load-balance algorithm Multithread indexer design can be seen in

Fig. 9. All documents are listed and distributed based on greedy load-balance algorithm. Since each job yields an index based on its given documents, this mechanism will result many indexes rather than one. These indexes need not to be merged as one since split indexes may yields faster index error correction with the help of distribution list. Distribution list is a comma separated values file that contain document list for each job. This file is also generated at indexing phase.

Any weighting schemes conducted in previous sequential design are delayed to retriever part based on these reasons :

a. Storing raw indexes is more scalable than processed one since various weighting

schemes may be applied without re-indexing.

b. Index error correction may be simplified since it only focus on errorneous indexes and its respective documents.

c. Many additional indexes can be embedded during retrieval phase without modifying preexisting indexes.

Fig 9: Multithread indexer design

Multithread Retriever In this research, two retrieval models are redersigned in multithread manner. These retrieval

functionsplitJob(path : String, n : int) | Stack[] jobs = new Stack[n] | for eachfile finpath | | if(f is Java archive) | | | minIdx = get lowest sJobs index | | | jobs[minIdx].add(f) | |end if | end for end function

function expand(beforeList : Data) : Data | Data afterList | for each method with id curID in beforeList | | methodExpansion(curID, beforeList, afterList) | return afterList end function procedure methodExpansion(curID : MethodID, beforeList : Data, afterList : Data) | if(afterList does not contain method with curID) | | IterTuple cur | | cur.id = curID; cur.caller = null | | cur.sList = get score tuple list of method with cur.id from beforeList | | while(true) | | | if(cur.sList has unprocessed ScoreTuple) | | | | ScoreTuple st = cur.sList.getNextUnprocessedScoreTuple() | | | | if(st is string literal) | | | | | cur.mtt.add(st) | | | | else// st is method call | | | | | MethodID nID = st.getMethodID() | | | | | if(beforeList contains method with nID) // need to be expanded | | | | | | if(afterList does not contain method with nID) // notexpanded yet | | | | | | | IterTuple next | | | | | | | next.id = nID; next.caller = cur | | | | | | | next.sList = get score tuple list of method with next.id from beforeList | | | | | | | cur = next | | | | | | else | | | | | | | copy all term in method with nID to cur.mtt | | | | | | endif | | | | | endif | | | | end if | | | else | | | | afterList.add(cur.mtt) | | | | if(cur.caller != null) | | | | | insert all term in method with cur.id to cur.caller.mtt at its respective pos | | | | else break | | | | end if | | | end if | | end while | end if end procedure

be applied without re-indexing.• Index error correction may be simplified since

it only focuses on errorneous indexes and itsrespective documents.

• Many additional indexes can be embedded dur-ing retrieval phase without modifying preexistingindexes.

H. Multithread Retriever

In this research, two retrieval models are reder-signed in multithread manner. These retrieval modelare standard and low-rank vector space model. Low-rank VSM (LRVSM) is extended VSM that utilizessemantic relatedness in order to improve its recall.VSM is selected since this model is a benchmarkof many other retrieval models whereas LRVSM isthe most effective extended VSM found in previousresearch [2, 3]. Both retrievers takes directory pathwhich consists of all indexed files as its input and buildin-memory retrieval models.

I. Multithread VSM

On VSM retriever, multithreading is conducted atreading indexes and retrieving documents. Both tasksassume each index as one job and each job is handledby one retriever (N indexes = N jobs = N retriever).Multithread VSM index reader can be seen in Fig. 3.Each index is listed and read separately in differentjobs. After all indexes are read, their respective termsare weighted using tf-idf scoring and stored in separateretrievers. Multithread VSM document retriever canbe seen in Fig. 4. Since each retriever is responsiblefor an index, the number of jobs is equivalent to thenumber of indexes. Each retriever retrieves its relevantdocuments based on query input and merges it to globalresult.

J. Multithread LRVSM

Multithread LRVSM works quite similar with mul-tithread VSM except LRVSM involves pre-calculatedsemantic relatedness. Since semantic relatedness be-tween terms is stored in binary file, index reader shouldload that file and document retriever should involve it

model are standard and low-rank vector space model. Low-rank VSM (LRVSM) is extended VSM that utilizes semantic relatedness in order to improve its recall. VSM is selected since this model is a benchmark of many other retrieval models whereas LRVSM is the most effective extended VSM found in previous research [2, 3]. Both retrievers takes directory path which consists of all indexed files as its input and build in-memory retrieval models.

Multithread VSM

On VSM retriever, Multithreading is conducted at reading indexes and retrieving documents. Both tasks assume each index as one job and each job is handled by one retriever (N indexes = N jobs = N retriever). Multithread VSM index reader can be seen in Fig. 10. Each index are listed and read separately in different jobs. After all indexes are read, its respective terms are weighted using tf-idf scoring and stored in separate retrievers. Multithread VSM document retriever can be seen in Fig. 11. Since each retriever is responsible for an index, the number of jobs is equivalent to the number of indexes. Each retriever retrieves its relevant documents based on query input and merges it to global result.

Fig 10: Multithread VSM index reader

Multithread LRVSM Multithread LRVSM works quite similar

with multithread VSM except LRVSM involves pre-calculated semantic relatedness. Since semantic relatedness between terms is stored in binary file, index reader should load that file and document retriever should involves it on its retrieval mechanism. Multithread LRVSM index reader can be seen in Fig. 12. This module enlists all indexes and relatedness file in order to load it on memory. Following VSM index reader design, each file is considered as one job and all index terms are weighted using tf-idf scoring before stored in

memory. Multithread LRVSM document retriever can be seen in Fig. 13. Relatedness data are stored in array and shared among all retrievers. This mechanism is thread-safe since only read action permitted on shared data.

. . .

Ret

rieve

r 1

Ret

rieve

r 2

Ret

rieve

r 3

Ret

rieve

r N

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

Result Merger

Index Store

Query Processing

Fig 11: Multithread VSM document retriever

Index and Relatedness Enlistment

. . .

Inde

x R

eade

r 1

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

TF-IDF Scoring

Index And Relatedness Store

Retriever Builder

Inde

x R

eade

r 2

Inde

x R

eade

r 3

Inde

x R

eade

r N

Rel

ated

ness

1

Rel

ated

ness

2

Rel

ated

ness

3

Rel

ated

ness

N

. . .

. . .

Rel

ated

ness

R

eade

r 1

Rel

ated

ness

R

eade

r 2

Rel

ated

ness

R

eade

r 3

Rel

ated

ness

R

eade

r N

Fig 12: Multithread LRVSM index reader

Multithread and Multiprocess Semantic Relatedness Calculator

Since semantic relatedness between terms is pre-computed and takes a long time, this module is also redesigned by involving multithread and multiprocess which can be seen in Fig. 14. This module takes all indexes as its input, generates distinct terms, and calculates semantic relatedness on separate processes. Separate processes is implemented by executing many standalone executable files. Processes are chosen instead of threads because:

a. Many third-party semantic relatedness libraries involve synchronized and static methods which may yield bottlenecks if implemented only in separate threads (e.g.

Fig. 3. Multithread VSM Index Reader.

model are standard and low-rank vector space model. Low-rank VSM (LRVSM) is extended VSM that utilizes semantic relatedness in order to improve its recall. VSM is selected since this model is a benchmark of many other retrieval models whereas LRVSM is the most effective extended VSM found in previous research [2, 3]. Both retrievers takes directory path which consists of all indexed files as its input and build in-memory retrieval models.

Multithread VSM

On VSM retriever, Multithreading is conducted at reading indexes and retrieving documents. Both tasks assume each index as one job and each job is handled by one retriever (N indexes = N jobs = N retriever). Multithread VSM index reader can be seen in Fig. 10. Each index are listed and read separately in different jobs. After all indexes are read, its respective terms are weighted using tf-idf scoring and stored in separate retrievers. Multithread VSM document retriever can be seen in Fig. 11. Since each retriever is responsible for an index, the number of jobs is equivalent to the number of indexes. Each retriever retrieves its relevant documents based on query input and merges it to global result.

Fig 10: Multithread VSM index reader

Multithread LRVSM Multithread LRVSM works quite similar

with multithread VSM except LRVSM involves pre-calculated semantic relatedness. Since semantic relatedness between terms is stored in binary file, index reader should load that file and document retriever should involves it on its retrieval mechanism. Multithread LRVSM index reader can be seen in Fig. 12. This module enlists all indexes and relatedness file in order to load it on memory. Following VSM index reader design, each file is considered as one job and all index terms are weighted using tf-idf scoring before stored in

memory. Multithread LRVSM document retriever can be seen in Fig. 13. Relatedness data are stored in array and shared among all retrievers. This mechanism is thread-safe since only read action permitted on shared data.

. . .

Ret

rieve

r 1

Ret

rieve

r 2

Ret

rieve

r 3

Ret

rieve

r N

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

Result Merger

Index Store

Query Processing

Fig 11: Multithread VSM document retriever

Index and Relatedness Enlistment

. . .

Inde

x R

eade

r 1

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

TF-IDF Scoring

Index And Relatedness Store

Retriever Builder

Inde

x R

eade

r 2

Inde

x R

eade

r 3

Inde

x R

eade

r N

Rel

ated

ness

1

Rel

ated

ness

2

Rel

ated

ness

3

Rel

ated

ness

N

. . .

. . .

Rel

ated

ness

R

eade

r 1

Rel

ated

ness

R

eade

r 2

Rel

ated

ness

R

eade

r 3

Rel

ated

ness

R

eade

r N

Fig 12: Multithread LRVSM index reader

Multithread and Multiprocess Semantic Relatedness Calculator

Since semantic relatedness between terms is pre-computed and takes a long time, this module is also redesigned by involving multithread and multiprocess which can be seen in Fig. 14. This module takes all indexes as its input, generates distinct terms, and calculates semantic relatedness on separate processes. Separate processes is implemented by executing many standalone executable files. Processes are chosen instead of threads because:

a. Many third-party semantic relatedness libraries involve synchronized and static methods which may yield bottlenecks if implemented only in separate threads (e.g.

Fig. 4. Multithread VSM Document Retriever.

on its retrieval mechanism. Multithread LRVSM indexreader can be seen in Fig. 5. This module enlists allindexes and relatedness file in order to load it onmemory. Following VSM index reader design, eachfile is considered as one job and all index terms areweighted using tf-idf scoring before stored in memory.Multithread LRVSM document retriever can be seen inFig. 6. Relatedness data are stored in array and sharedamong all retrievers. This mechanism is thread-safesince only read action permitted on shared data.

K. Multithread and Multiprocess Semantic Related-ness Calculator

Since semantic relatedness between terms is pre-computed and takes a long time, this module is alsoredesigned by involving multithread and multiprocess

21

Page 11: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

which can be seen in Fig. 7. This module takesall indexes as its input, generates distinct terms, andcalculates semantic relatedness on separate processes.Separate processes is implemented by executing manystandalone executable files. Processes are chosen in-stead of threads because:

• Many third-party semantic relatedness librariesinvolve synchronized and static methods whichmay yield bottlenecks if implemented only in sep-arate threads (e.g., Ws4J: WordNet Similarity forJava [18]). Multithread design with bottlenecksmay yield longer processing time than the naiveone (single-thread) since multithreading needs ad-ditional time to split and merge jobs.

• Standalone executable files may be built in manyprogramming language other than Java as long asit follows its input and output template.

model are standard and low-rank vector space model. Low-rank VSM (LRVSM) is extended VSM that utilizes semantic relatedness in order to improve its recall. VSM is selected since this model is a benchmark of many other retrieval models whereas LRVSM is the most effective extended VSM found in previous research [2, 3]. Both retrievers takes directory path which consists of all indexed files as its input and build in-memory retrieval models.

Multithread VSM

On VSM retriever, Multithreading is conducted at reading indexes and retrieving documents. Both tasks assume each index as one job and each job is handled by one retriever (N indexes = N jobs = N retriever). Multithread VSM index reader can be seen in Fig. 10. Each index are listed and read separately in different jobs. After all indexes are read, its respective terms are weighted using tf-idf scoring and stored in separate retrievers. Multithread VSM document retriever can be seen in Fig. 11. Since each retriever is responsible for an index, the number of jobs is equivalent to the number of indexes. Each retriever retrieves its relevant documents based on query input and merges it to global result.

Fig 10: Multithread VSM index reader

Multithread LRVSM Multithread LRVSM works quite similar

with multithread VSM except LRVSM involves pre-calculated semantic relatedness. Since semantic relatedness between terms is stored in binary file, index reader should load that file and document retriever should involves it on its retrieval mechanism. Multithread LRVSM index reader can be seen in Fig. 12. This module enlists all indexes and relatedness file in order to load it on memory. Following VSM index reader design, each file is considered as one job and all index terms are weighted using tf-idf scoring before stored in

memory. Multithread LRVSM document retriever can be seen in Fig. 13. Relatedness data are stored in array and shared among all retrievers. This mechanism is thread-safe since only read action permitted on shared data.

. . .

Ret

rieve

r 1

Ret

rieve

r 2

Ret

rieve

r 3

Ret

rieve

r N

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

Result Merger

Index Store

Query Processing

Fig 11: Multithread VSM document retriever

Index and Relatedness Enlistment

. . .

Inde

x R

eade

r 1

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

TF-IDF Scoring

Index And Relatedness Store

Retriever Builder

Inde

x R

eade

r 2

Inde

x R

eade

r 3

Inde

x R

eade

r N

Rel

ated

ness

1

Rel

ated

ness

2

Rel

ated

ness

3

Rel

ated

ness

N

. . .

. . .

Rel

ated

ness

R

eade

r 1

Rel

ated

ness

R

eade

r 2

Rel

ated

ness

R

eade

r 3

Rel

ated

ness

R

eade

r N

Fig 12: Multithread LRVSM index reader

Multithread and Multiprocess Semantic Relatedness Calculator

Since semantic relatedness between terms is pre-computed and takes a long time, this module is also redesigned by involving multithread and multiprocess which can be seen in Fig. 14. This module takes all indexes as its input, generates distinct terms, and calculates semantic relatedness on separate processes. Separate processes is implemented by executing many standalone executable files. Processes are chosen instead of threads because:

a. Many third-party semantic relatedness libraries involve synchronized and static methods which may yield bottlenecks if implemented only in separate threads (e.g.

Fig. 5. Multithread LRVSM Index Reader.

Ws4J: WordNet Similarity for Java [18]). Multithread design with bottlenecks may yield longer processing time than the naive one (single-thread) since multithreading needs additional time to split and merge jobs.

b. Standalone executable files may be built in many programming language other than Java as long as it follows its input and output template.

c. Semantic relatedness calculator may be freely designed by its developer. Internal saving mechanism may also be added as additional feature since calculating semantic relatedness takes a long time (calculating semantic relatedness of 40.978 distinct terms in previous research using single thread takes about five days).

. . .

Ret

rieve

r 1

Ret

rieve

r 2

Ret

rieve

r 3

Ret

rieve

r N

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

Result Merger

Index and Relatedness Store

Query Processing

Rel

ated

ness

1

Rel

ated

ness

2

Rel

ated

ness

3

Rel

ated

ness

N

. . .

Relatedness Merger

Fig 13: Multithread LRVSM document retriever

Standalone executable file built for this

module must follow input and output template. It takes 6 input arguments which are source file (CSV file which consists all distinct terms), lower and upper bound of first and second job, and target file. The program should take all distinct term from source file, calculate semantic relatedness between terms on given job, and store it to target file in binary format of hash map. Target hash map use double as its value and string as its key. Key represent concatenated term pair separated by vertical bar ("|") whereas its value represent term pair relatedness.

Since distinct terms are stored in array and each term i is only paired with remaining terms with larger index than i, semantic relatedness calculation at the end of array should be faster than the beginning part. To distribute term calculation tasks evenly, each process (executable file) is given two jobs. First one is from the beginning of an

array and the second one is from the end of an array. Distinct terms are split to 2*N jobs and each process i is assigned to job i and N-i where N represent the number of processes.

Index Enlistment

. . .

Rea

der

1

Rea

der

2

Rea

der

3

Rea

der

N

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

Distinct Term Generator

Rel

ated

ness

C

alcu

lato

r 1

Rel

ated

ness

C

alcu

lato

r 2

Rel

ated

ness

C

alcu

lato

r 3

. . .

Rel

ated

ness

C

alcu

lato

r N

Rel

ated

ness

1

Rel

ated

ness

2

Rel

ated

ness

3

Rel

ated

ness

N

Fig 14: Multithread semantic relatedness calculator

RESULTS AND DISCUSSION Efficiency and effectiveness are two major

measurements which are commonly used to determine the feasibility of a research. Since this research focuses on module conversion in order to improve its scalability, efficiency is measured based on processing time and scalable design whereas effectiveness is measured on converted modules correctness. Evaluation conducted in this research uses default dataset from [1] as a benchmark. For clarity in each table, blue mark represents the best result whereas red mark represents the worst result for each factor.

Evaluating Recursion Conversion

To evaluate recursion conversion, some schemes are augmented which are shown in Table 2. Each type consists of three symbols which represent module implementation (I = Iteration and R = Recursion). Its symbol order is equivalent to module order shown in Table 2 columns. RRR and III schemes are the benchmarks of this evaluation since RRR represent recursive approach in all modules and III represent iterative approach in all modules. Type IRR, RIR, and RRI are used to measure conversion impact of certain module.

Indexing time of each schemes on default dataset can be seen in Table 3. Since processing time is operating system dependent, each scheme is measured five times using the same dataset and its

Fig. 6. Multithread LRVSM Document Retriever.

• Semantic relatedness calculator may be freelydesigned by its developer. Internal saving mech-anism may also be added as additional featuresince calculating semantic relatedness takes a longtime (calculating semantic relatedness of 40.978distinct terms in previous research using singlethread takes about five days).

Standalone executable file built for this module mustfollow input and output template. It takes six input ar-guments which are source file (CSV file which consistsall distinct terms), lower and upper bound of first andsecond job, and target file. The program should takeall distinct term from source file, calculate semanticrelatedness between terms on given job, and store it totarget file in binary format of hash map. Target hashmap uses double as its value and string as its key.The key represents concatenated term pair separatedby vertical bar (“|”) whereas its value represents termpair relatedness.

Since distinct terms are stored in array and eachterm i is only paired with remaining terms with largerindex than i, semantic relatedness calculation at the endof array should be faster than the beginning part. Todistribute term calculation tasks evenly, each process(executable file) is given two jobs. First one is fromthe beginning of an array and the second one is fromthe end of an array. Distinct terms are split to 2 ×Njobs and each process i is assigned to job i and N − i

Ws4J: WordNet Similarity for Java [18]). Multithread design with bottlenecks may yield longer processing time than the naive one (single-thread) since multithreading needs additional time to split and merge jobs.

b. Standalone executable files may be built in many programming language other than Java as long as it follows its input and output template.

c. Semantic relatedness calculator may be freely designed by its developer. Internal saving mechanism may also be added as additional feature since calculating semantic relatedness takes a long time (calculating semantic relatedness of 40.978 distinct terms in previous research using single thread takes about five days).

. . .

Ret

rieve

r 1

Ret

rieve

r 2

Ret

rieve

r 3

Ret

rieve

r N

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

Result Merger

Index and Relatedness Store

Query Processing

Rel

ated

ness

1

Rel

ated

ness

2

Rel

ated

ness

3

Rel

ated

ness

N

. . .

Relatedness Merger

Fig 13: Multithread LRVSM document retriever

Standalone executable file built for this

module must follow input and output template. It takes 6 input arguments which are source file (CSV file which consists all distinct terms), lower and upper bound of first and second job, and target file. The program should take all distinct term from source file, calculate semantic relatedness between terms on given job, and store it to target file in binary format of hash map. Target hash map use double as its value and string as its key. Key represent concatenated term pair separated by vertical bar ("|") whereas its value represent term pair relatedness.

Since distinct terms are stored in array and each term i is only paired with remaining terms with larger index than i, semantic relatedness calculation at the end of array should be faster than the beginning part. To distribute term calculation tasks evenly, each process (executable file) is given two jobs. First one is from the beginning of an

array and the second one is from the end of an array. Distinct terms are split to 2*N jobs and each process i is assigned to job i and N-i where N represent the number of processes.

Index Enlistment

. . .

Rea

der

1

Rea

der

2

Rea

der

3

Rea

der

N

Inde

x1

Inde

x2

Inde

x3

Inde

xN. . .

Distinct Term Generator

Rel

ated

ness

C

alcu

lato

r 1

Rel

ated

ness

C

alcu

lato

r 2

Rel

ated

ness

C

alcu

lato

r 3

. . .

Rel

ated

ness

C

alcu

lato

r N

Rel

ated

ness

1

Rel

ated

ness

2

Rel

ated

ness

3

Rel

ated

ness

N

Fig 14: Multithread semantic relatedness calculator

RESULTS AND DISCUSSION Efficiency and effectiveness are two major

measurements which are commonly used to determine the feasibility of a research. Since this research focuses on module conversion in order to improve its scalability, efficiency is measured based on processing time and scalable design whereas effectiveness is measured on converted modules correctness. Evaluation conducted in this research uses default dataset from [1] as a benchmark. For clarity in each table, blue mark represents the best result whereas red mark represents the worst result for each factor.

Evaluating Recursion Conversion

To evaluate recursion conversion, some schemes are augmented which are shown in Table 2. Each type consists of three symbols which represent module implementation (I = Iteration and R = Recursion). Its symbol order is equivalent to module order shown in Table 2 columns. RRR and III schemes are the benchmarks of this evaluation since RRR represent recursive approach in all modules and III represent iterative approach in all modules. Type IRR, RIR, and RRI are used to measure conversion impact of certain module.

Indexing time of each schemes on default dataset can be seen in Table 3. Since processing time is operating system dependent, each scheme is measured five times using the same dataset and its

Fig. 7. Multithread Semantic Relatedness Calculator.

22

Page 12: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

where N represent the number of processes.

III. RESULTS AND DISCUSSION

Efficiency and effectiveness are two major measure-ments which are commonly used to determine thefeasibility of a research. Since this research focuses onmodule conversion in order to improve its scalability,efficiency is measured based on processing time andscalable design whereas effectiveness is measured onconverted modules correctness. Evaluation conductedin this research uses default dataset from Ref. [1]as a benchmark. For clarity in each table, blue markrepresents the best result whereas red mark representsthe worst result for each factor.

A. Evaluating Recursion Conversion

To evaluate recursion conversion, some schemesare augmented which are shown in Table II. Eachtype consists of three symbols which represent moduleimplementation (I = Iteration and R = Recursion). Itssymbol order is equivalent to module order shownin Table II columns. RRR and III schemes are thebenchmarks of this evaluation since RRR representrecursive approach in all modules and III representiterative approach in all modules. Type IRR, RIR, andRRI are used to measure conversion impact of certainmodule.

Indexing time of each schemes on default dataset canbe seen in Table III. Since processing time is operatingsystem dependent, each scheme is measured five timesusing the same dataset and its average result is assignedas its result to reduce its dependency bias.

As seen in Table III, each scheme that involvesiterative implementation takes more processing timerather than RRR scheme. Following recursive logic initerative approach may yield longer processing timesince it requires many additional objects on its process(e.g. IterTuple in Iterative Tarjans SCC algortihm).

TABLE IIRECURSION CONVERSION EVALUATION SCHEMES.

Type Module

LoopEncapsu-lation

RecursiveMethodElimination

MethodExpander

RRR Rec Rec RecIRR Iter Rec RecRIR Rec Iter RecRRI Rec Rec IterIII Iter Iter Iter

Although its processing time is less efficient, it is morescalable than recursive approach. Stack overflow errorrarely appears on iterative approach since the numberof function call is greatly reduced. RRR scheme ondefault dataset generates a stack overflow error whenrun on JRE 1.8 whereas it runs well on JRE 1.7.This is caused by many update in JRE 1.8 whichdetects some processes in this program as endlessrecursion (although it is not). Iterative form is also abetter approach than recursive form since the numberof recursive calls conducted on dataset is uncertain.III scheme takes the longest indexing time since allmodules are implemented iteratively.

Recursion conversion correctness is measured bycomparing the result of iterative and recursive ap-proaches. Its correctness is proved when both imple-mentation yield similar results on various dataset. Inthis evaluation, 11 dataset are tested where the firstdataset is default dataset in Ref. [1] and the rest aresub dataset split from default dataset. Sub dataset areresulted by splitting default dataset to 10 parts evenly.Since these modules are indexer part, result comparisonis conducted based on indexes generated by bothimplementation. As a result, both implementation yieldsimilar results on all schemes.

B. Evaluating Multithread Design

Multithread indexer, VSM, EVSM, and semantic re-latedness calculator are measured in term of efficiencyand effectiveness. These evaluation are conducted inWindows 7 Ultimate 32-bit with 4 GB RAM, andIntel(IR) CoreTM i7-3770 CPU @ 3.40 GHz and3.90 GHz as its processor. Each evaluated moduleexcepts semantic relatedness calculator is tested byvarious number of jobs which are 1, N,N × 2, N ×5, N × 10, N × 20, N × 40, and 552. N is the numberof physical cores −1, which is 3 in this evaluation en-vironment whereas 552 is the number of Java archivesindexed in our dataset. To reduce its dependency bias,each evaluation scheme is measured five times usingthe same dataset and its average result is assigned asits result.

TABLE IIIINDEXING TIME OF RECURSION CONVERSION SCHEMES.

Type Indexing Time (s)

RRR 417.297IRR 423.964RIR 436.958RRI 429.307III 433.995

23

Page 13: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

C. Evaluating Multithread Indexer

The quantitative efficiency measurement of multi-thread indexer can be seen in Table IV. The bestindexing time is gained at N = 3 since all physicalcores are utilized (4 cores, 1 core is used for mainthread and the rest are used for side threads). N = 1takes the longest indexing time since it only utilizes1 side thread (which is quite similar to sequentialprocess). Index size is increased proportionally withthe number of jobs since each job generates an indexfile and each index has its own header file.

Since the contents of generated indexes for eachscheme are equivalent with the contents of indexgenerated in previous research, multithread design onthis module is proved correct. Time reduction in mul-tithread indexer also proves that multithreading mayimprove scalability since it enables this system toprocess larger dataset.

D. Evaluating Multithread VSM and LRVSM

Multithread VSM and LRVSM are measured withsimilar factors since both of them are retriever mod-ules. Measured retriever’s efficiency factors are indexload time and average query latency whereas effective-ness is only measured based on its correctness.

The time efficiency measurement of multithreadVSM and LRVSM can be seen in Tables V and VI.Since LRVSM evaluation is assumed to take related-ness file as a single file, both results yield similarconclusions which are:

• Index load time runs fastest at N = 3 since allphysical cores are utilized. The number of jobs isproportional to index load time since job transferin thread takes time. N = 1 takes longer timethan N=3 since it only utilizes one thread insteadof three.

TABLE IVTIME AND MEMORY EFFICIENCY OF MULTITHREAD INDEXING.

NEfficiency Measurement

Indexing Time (s) Index Size (MB)

1 326.851 4,8943 153.913 5,2136 164.822 5,559

15 169.354 5,86030 172.387 6,52560 174.642 6,973

120 180.711 7,623552 240.053 9,142

• Average query latency is affected by the numberof index partitioning. Retrieving a term fromone big chunk of index takes longer time thanretrieving it from many small chunks since largeindex may yield more complicated structure thanthe small one. Small indexes are also easier to becached in memory. But too many small indexesmay yield longer processing time since it needs toiterate through these indexes. As seen in Table VI,average query latency at N = 552 takes longertime than N = 120 although it has more indexeswith smaller size.

Conversion correctness are proven by the fact thatboth retriever yields similar result with its respectivesequential form for all queries from default dataset(1860 queries). Multithread VSM and LRVSM is alsomore scalable since shorter processing time may enablesystem to handle larger data.

TABLE VTIME EFFICIENCY OF MULTITHREAD VSM.

NEfficiency Measurement

Indexing Time (s) Ave. Query Latency (s)

1 1.749 0.4623 0.831 0.0996 0.926 0.045

15 0.961 0.02430 1.118 0.01160 1.310 0.007

120 1.572 0.007552 2.558 0.024

TABLE VITIME EFFICIENCY OF MULTITHREAD LRVSM.

NEfficiency Measurement

Indexing Time (s) Ave. Query Latency (s)

1 56.041 0.0913 55.563 0.0476 55.759 0.046

15 56.603 0.04330 57.128 0.04260 57.287 0.041

120 57.884 0.039552 59.208 0.152

24

Page 14: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

TABLE VIISEMANTIC RELATEDNESS EVALUATION DATASET.

Java Archive DistinctTerms

Related TermPairs

javassist-2.5.1.jar 646 22.770lucene-1.2.jar 553 15.434jxl-2.4.2.jar 1.102 63.415

TABLE VIIIPROCESSING TIME OF SEMANTIC RELATEDNESS

CALCULATOR (S).

Java Archive Single ThreadDesign

MultithreadDesign

javassist-2.5.1.jar 2.237,249 1.355,221lucene-1.2.jar 1.457,311 828,732jxl-2.4.2.jar 5.249,131 3.372,989

E. Evaluating Multithread Semantic Relatedness Cal-culator

Since semantic relatedness calculator requires stan-dalone executable files for completing its task, a Java-based standalone executable file (JAR) is build forthis research. This program follows algorithm templategiven by multithread semantic relatedness calculator.Since calculating semantic relatedness is time con-suming, multithread design of this module is onlytested to three Java archives instead of entire defaultdataset. These Java archives characteristics can be seenin Table VII.

Processing time of multithread and single-threaddesign of semantic relatedness calculator can be seenin Table VIII. Each scheme is evaluated five timesand its average result is considered as that schemeresult. Evaluation is conducted by split distinct termsto three jobs and utilize Lin’s semantic relatednessalgorithm described in Ref. [19]. As seen in Table VIII,multithread design is more scalable since it takes lesstime than single-thread by utilizing all physical cores.This design also yields the same result as single-threaddesign which proves its correctness.

IV. CONCLUSIONS

Based on evaluation in this research, scalability ofJava archive search engine can be improved throughrecursion conversion and multithreading. Recursionconversion improves scalability by avoiding stack over-flow error whereas multithreading improves scalabilityby reducing its execution time (which enables systemto process larger dataset).

Recursion conversion conducted in this research in-volves three main recursive modules which are loop en-capsulation, recursive method elimination, and methodexpansion. Although these modules are inconvenientenough to be redesigned as iterative one, it still can beconverted by following its recursive pattern with thehelp of caller reference. Recursive pattern in iterativeimplementation takes more time than its recursiveform since these modules are logically recursive andrequire many additional objects during its execution.The correctness of recursion conversion described isalso proved by the fact that both implementation yieldsimilar result.

Multithread design has been successfully imple-mented in Java archive search engine which involvesindexer, VSM retriever, LRVSM retriever, and seman-tic relatedness calculator. This mechanism cuts off itsrespective processing time since it utilizes all physicalcores. Index partitioning may yield faster retrievalmodel although too many small indexes may also yieldlonger processing time. All multithread modules arealso proved correct by black box testing its results.

REFERENCES

[1] O. Karnalim and R. Mandala, “Java archivessearch engine using byte code as informa-tion source,” in Data and Software Engineering(ICODSE), 2014 International Conference on.IEEE, 2014, pp. 1–6.

[2] O. Karnalim, “Extended vector space model withsemantic relatedness on java archive search en-gine,” Jurnal Teknik Informatika dan Sistem In-formasi, vol. 1, no. 2, 2015.

[3] W. B. Croft, D. Metzler, and T. Strohman,Search engines: Information retrieval in practice.Addison-Wesley Reading, 2010, vol. 283.

[4] D. Grune, K. Van Reeuwijk, H. E. Bal, C. J.Jacobs, and K. Langendoen, Modern compilerdesign. Springer Science & Business Media,2012.

[5] T. Lindholm, F. Yellin, G. Bracha, and A. Buck-ley, The Java virtual machine specification. Pear-son Education, 2014.

[6] R. Tarjan, “Depth-first search and linear graphalgorithms,” SIAM journal on computing, vol. 1,no. 2, pp. 146–160, 1972.

[7] M. Carrano and T. Henry, Data Abstraction &Problem Solving with C++: Walls and Mirrors,6th ed. Prentice Hall, 2012.

[8] A. S. Tanenbaum, Modern Operating Systems,4th ed. Prentice Hall, 2014.

25

Page 15: IMPROVING SCALABILITY OF JAVA ARCHIVE SEARCH ENGINE ... 2016-05... · Fergyanto E. Gunawan Associate Editors Satryo Soemantri Brodjonegoro, Institut Teknologi Bandung, Bandung, Indonesia

Cite this article as: O. Karnalim, “Improving Scalability of Java Archive Search Engine Through RecursionConversion and Multithreading”, CommIT (Communication & Information Technology) Journal 10(1), 15–26,2016.

[9] W. Liu and T. Wang, “Index-based online textclassification for sms spam filtering,” Journal ofComputers, vol. 5, no. 6, pp. 844–851, 2010.

[10] W. Premchaiswadi and A. Tungkatsathan, “On-line content-based image retrieval system usingjoint querying and relevance feedback scheme,”WSEAS Transactions on Computers, vol. 9, no. 5,pp. 465–474, 2010.

[11] C. Bonacic, C. Garcia, M. Marin, M. Prieto,F. Tirado, and C. Vicente, “Improving search en-gines performance on multithreading processors,”in High Performance Computing for Computa-tional Science-VECPAR 2008. Springer, 2008,pp. 201–213.

[12] C. Bonacic and M. Marin, “Simulation study ofmulti-threading in web search engine processors,”in String Processing and Information Retrieval.Springer, 2013, pp. 37–48.

[13] V. Skylarov, I. Skilarova, and B. Pimentel, “Fpga-based implementation and comparison of re-cursive and iterative algorithms,” in Field Pro-grammable Logic and Applications, 2005. Inter-national Conference on. IEEE, 2005, pp. 235–

240.[14] J. Miecznikowski and L. Hendren, “Decompil-

ing java using staged encapsulation,” in ReverseEngineering, 2001. Proceedings. Eighth WorkingConference on. IEEE, 2001, pp. 368–374.

[15] M. Naftalin and P. Wadler, Java generics andcollections. ” O’Reilly Media, Inc.”, 2006.

[16] C. Kustanto and I. Liem, “Automatic source codeplagiarism detection,” in Software Engineering,Artificial Intelligences, Networking and Paral-lel/Distributed Computing, 2009. SNPD’09. 10thACIS International Conference on. IEEE, 2009,pp. 481–486.

[17] C. D. Manning, P. Raghavan, H. Schutze et al.,Introduction to information retrieval. Cambridgeuniversity press Cambridge, 2008, vol. 1, no. 1.

[18] H. Shima. (2015) Ws4j : Wordnet similarity forjava. Accessed on November 24, 2015. [Online].Available: https://code.google.com/p/ws4j/

[19] D. Lin, “An information-theoretic definition ofsimilarity.” in ICML, vol. 98, 1998, pp. 296–304.

26


Recommended