text:
StartUpHire is the place to find Senior JavaScript Engineer jobs. Review the list of Senior JavaScript Engineer career opportunities to the left. These Senior JavaScript Engineer jobs represent some of the most rewarding careers available.
You can refine your job search for Senior JavaScript Engineer career opportunities by adding a job title, company name, or keyword to the search box above … or click the "Advanced Search" link for more options.
Don't see the employment opportunity you're looking for? Check back soon for more Senior JavaScript Engineer jobs, or sign up for an email alert (link below) to receive periodic updates on new Senior JavaScript Engineer jobs.
Integral Ad Science is looking a Senior JavaScript Engineer to help build the future of online advertising technology. We're a team of about 90 engineers working on a platform that handles hundreds of thousands of transactions per second -- our JavaS9/18/2016 Austin, TX Save This Job
Integral Ad Science is looking a Senior JavaScript Engineer to help build the future of online advertising technology. We're a team of about 90 engineers working on a platform that handles hundreds of thousands of transactions per second -- our JavaS9/3/2016 San Francisco, CA Save This Job
Sprout Socialâs web applications and user experience revolve around JavaScript. Weâre looking for an experienced JavaScript engineer to join our team of talented engineers.9/29/2016 Chicago, IL Save This Job
We're looking for a tech-savvy, self-starting, flexible Senior SQA Engineer/SDET who has a passion for working with state-of-the-art technology to help us deliver high quality software that will allow creating next-generation social robots.9/11/2016 Boston, MA Save This Job
Troy, NY Full Time EUX Experienced Position: Senior Software Engineer Team: End User Experience Tech Stack: JavaScript, HTML, CSS As an engineer you seek to solve problems and stir innovation. Apprenda provides an environment uniquely designed to put you on the brink8/28/2016 Troy, NY Save This Job
Engineering Menlo Park, CA, United States Ayasdi uses a pioneering approach to automatically discover insights from complex data. Founded in 2008 after a decade of research at Stanford, DARPA, and NSF, Ayasdi uses Topological Data Analysis (TDA) to unify best-of-breed machine9/6/2016 Menlo Park, CA Save This Job
Technology ? Irvine, California Senior Software Engineer: Design, maintain, and deliver application software solutions in accordance with the client?s strategic objective using Microsoft C#, ASP.Net, and MS SQL Server. Manage all stages of the software development life cycle9/14/2016 Irvine, CA Save This Job
You are here Home / Senior QA Engineer / Software Engineer Testing (Full time; Lehi, UT) Location: Lehi, UT Type: Full-time Experience: 5+ years Functions: Senior QA Engineer / Software Engineer Testing Industries: Computer Software Posted: Ongoing Job overview Lingotek8/30/2016 Lehi, UT Save This Job
Job Summary: Work with a dynamic team of engineers and architects to build enterprise solutions using the very latest PaaS technologies. The Senior Salesforce Engineer needs to be capable of working alone or within a team atmosphere to convert functional and architectural8/7/2016 Portsmouth, NH Save This Job
San Francisco, CA Company Summary: Blurb is a book-making platform and creative community that enables individuals to create, publish, share and sell high-quality photo books, trade books, and magazines in both print and digital formats. Blurb is accessible to consumers9/16/2016 San Francisco, CA Save This Job
Zendesk is looking for a Senior Software Engineer to join our Shared Services team! The Shared Services group consists of a small team of engineers building infrastructure used across the Zendesk product suite. Our primary languages are Ruby, Scala and JavaScript. You will8/10/2016 San Francisco, CA Save This Job
Location Burlington, MA Senior Software Engineer The Senior Software Engineer as an individual contributor in our collaborative team is responsible for the development, integration, testing and deployment of our products. The Senior Software Engineer will be based in our8/9/2016 Burlington, MA Save This Job
New York City MongoDB is looking for a Senior UI Engineer to help build the best database management system. Cloud Manager is the freely available, cloud-based web application for deploying, monitoring, and backing up MongoDB clusters of any size and configuration. It currently8/8/2016 New York, NY Save This Job
Technology - Indianapolis, IN - Full Time Senior Software Engineer Location: Chicago, IL OR Indianapolis, IN OR Naples, FL Department: Development Team Type: Full Time Min. Experience: Mid-Level Job Description: Geofeedia has a unique opening for a Senior Software Engineer who8/7/2016 Indianapolis, IN Save This Job
at Weebly San Francisco, CA Weebly is looking for a Senior Backend Engineer to work with a focused team to deliver a high quality experience to users of Weebly's industry-leading mobile apps. Our mobile apps have been featured by Apple and Google, and Weebly has been identified8/6/2016 San Francisco, CA Save This Job
Position Summary Zettaset Inc. is seeking a Senior QA Engineer to join the QA team. The QA Engineer develops software test plans, designs and develops white and black box QA tests, and automates QA tests where appropriate. The position works closely with Engineering to develop8/1/2016 Mountain View, CA Save This Job
Engineering San Jose, CA, United States Senior UI Engineer Seeking a professional challenge where your impact will be immediately felt and appreciated? We at MapR have built the industry best Hadoop for managing petabytes of data, running on thousands of nodes, and accessed8/28/2016 San Jose, CA Save This Job
Engineering Foster City, California Apply Description Conviva?s real-time big data platform enables content publishers and service providers to achieve a TV-quality viewing experience despite the unpredictability of a complex and fragile Internet and device ecosystem. Fueled by9/15/2016 Foster City, CA Save This Job
APPLY FOR THIS POSITION SEND TO A FRIEND Department:Apps Location:Fort Myers, Florida # of openings:1 Description DEPARTMENT OVERVIEW The Apps channel of Adknowledge specializes in developing, monetizing, and promoting free applications to millions of users every month. Our9/1/2016 Fort Myers, FL Save This Job
Chandler, AZ About the Job Nexant is currently seeking a Senior Software Engineer for our Chandler, AZ office. Duties and Responsibilities Design and develop software solutions for Nexant?s Grid Management division, providing software solutions for the relief of electric9/1/2016 Chandler, AZ Save This Job

subset: commoncrawl


text:
How interesting! Danube , shot from the other side:)) Greetings from Rousse! Valentina
Te agrego a mis Fotógrafos favoritos.. Me encantan todas tus fotos. Saludos. Maite
Thank you very much, you are very generous, because I saw that your picture is very, very good!
Very nice shot, dear Crina, beautiful view, very beautiful picture!!!
Like and favorite :-)
Best wishes,
Beautiful shot of the sunset crina.stanciu.
COMPLIMENTS. Regards from Italy. Roberto
Photo taken in Giurgiu, Romania


text: Vox Pop : Pets and Vets with Dr. Ron Scharf : 4/25/12 ShareTwitter Facebook Google+ Email Its Pets and Vets on this edition of Vox Pop with Dr. Ron Scharf of the Animal Hospital of Niskayuna, New York. WAMC's Ray Graf hosts. Related Program: Vox PopTags: pets and vetsdr. ron scharfcatsdogsanimalsView the discussion thread.


text:
Commemorate 22 years of the Americans with Disabilities Act with a day-long celebration. Unveiling of wheel chair used by disability rights activist Justin Dart, Jr. while flanking President George H.W. Bush at the signing of the Americans with Disabilities Act in 1990, photography exhibition, interactive booths, Disability Pride March, reception.
Also enjoy free admission to the National Constitution Center today.
Participate in the Disability Pride March starting at the National Constitution Center and ending at the Liberty Bell.
9:30am: Doors open, booths, tables, discussion
11am-12noon: Unveiling ceremony for Justin Dart Jr.'s wheelchair at the National Constitution Center (525 Arch St.)
12noon-2pm: Speakers, performers & joint photo exhibition by documentary photographers Tom Olin & Harvey Finkle at the National Constitution Center
2pm-3:30pm: Disability Pride March on Independence Mall
3:30pm-5:30pm: Reception at Liberty Resources (714 Market St., Atrium Lobby)
PA - Philadelphia
No registration needed
All Ages/Families
We make every effort to ensure the accuracy of this information. However, you should always call ahead to confirm dates, times, location, and other information.


text:
The Los Angeles Times reported that despite Israel's current economic growth spurt, an Israeli economist is prophesying doom because of the large number of men in Israel who are on the government dole. Around 20 percent of men between 35 and 54 are not working.
Edmund Sanders reported from Jerusalem:
Officially, Israel's unemployment rate is about 8%. But that doesn't include Israeli citizens who are not trying to find work, either because they feel disenfranchised, such as many Arab Israelis, or because they've chosen a life of state-subsidized religious study, such as many ultra-Orthodox Jews.
Nearly 27% of Arab men and 65% of ultra-Orthodox Jews don't work, government figures show. The non-employment rate for ultra-Orthodox men has tripled since 1970, Ben-David said.
"We support a lifestyle of nonworking that is pretty unparalleled in the Western world," said Ben-David, who is also a Tel Aviv University professor. "On the one hand, we have this state-of-the-art part of the economy. Then there is the rest of the country that is like a huge drag."
What worries Ben-David most is that the nonproductive part of Israel's population, which survives largely on welfare, is also the fastest growing.
Click here to read the full story.
View our privacy policy and terms of service.


text:
Ray Hudson lived in the Aleutian Islands for nearly thirty years. He currently lives in Middlebury, Vermont.
Paul R. Ehrlich
Hope on Earth
A Conversation
Get it for free!
About E-books
Bodleian Library, University of Oxford, featured publisher
University of Chicago Press: 1427 E. 60th Street Chicago, IL 60637 USA | Voice: 773.702.7700 | Fax: 773.702.9756
Privacy Policies
Site Map
Chicago Manual of Style
Scientific Style and Format
University of Chicago


text:
Via per Canicattini, 28 -, Siracusa 96100 Syracuse (Syracuse)
Case Damma is a lovely holiday farm beatifully sited in a rural district, a few minutes from Siracusa. A fascinanting country house in the peaceful quietness of a large green park, rich in a beautiful variety of luxuriant Sicilian vegetation. The site is an ideal resort for a short stay, wedding receptions, meetings and nice parties for every occasion.
We offer full board or half board accommodation and typical Sicilian food. There is the opportunity of a shuttle bus, hiring a car, a boat or a bicycle or attending a cookerycourse. Beside you may also awail of a swimming pool for your children, amusing visits to the cattleshed and to a near dairy farm.
The holiday farm Case Damma is situated in a pleasant spot among lemon and arange trees. It is a classic Sicilian farm whose story goes back to the XV century; elements of old architectural country style can be admired.
The buildings are situated all around the main court where you can find the "palmento" (wine pressing) where now the dining room is situated, the oven the country houses and the store house. The residential lodging is situated in a higher position above the court. All around there is beautiful garden typical of the old noble Sicilian country villa.
The rooms (double or triple bedded) are situated in rural buildings completely renovated and equipped with all modern conforts. Additional beds may be added in the rooms. Your meals will be homely cooked and rich in traditional taste of old Sicilian recepes. All the ingrediends are produced in the farm.
Come and stay with us: you will enjoy an unfergottable holiday. Our holiday farm is situated in an engjoyble position near the most beautiful sea resorts of our zone – Fontane bianche, Marina di Noto, Riserva faunistica di Vendicari – not far from the most suggestive archaeological sites – Necropoli di Pantalica, Cavagrande del Cassibile, Megara Iblea ecc. and the hilly woody areas when you can go far a ride.
Inform the agriturismo of any animals at the time of booking.
Owners will be held responsible for damage to property and persons.
We had a great time at Case Damma. The place is very nice with a beautiful pool. The community engages with other residents restoration allows enriching encounters.
(Translated with Google Translate)
A wonderful place to be nearby Seracusa. Relaxing atmosphere, friendly family and delicious food. Nice pool and garden. We can recommend it! Heinz and Marly
(Translated with Google Translate)
We went to this wonderful place Sunday, May 17, 2015 a fantastic place where the food is a taste and qualità'unica. Congratulations !!
(Translated with Google Translate)
The telephone number is:
+39.0931.717405 +39.3358086513 +39.3472536720
The fax is:


text:
This event has expired. This may be a recurring event, so please check the calendar in the future for updated occurrences.
Eau Claire Marathon
Eau Claire
A Race for everyone!!! 26.2 mile Marathon, 13.1 mile Half Marathon, 26.2 mile 4 person relay and 5K Run/Walk Check us out online or Follow us on Facebook


text:
Amana 5.0 cu. ft. Gas Range - White
$346.68 - $450.77
1 year parts and labor
Find Out More »
Amana® 5.0 cu. ft. Gas Range Oven - Efficient and Convenient Cooking The versatile cooktop on this Amana® 5.0 cu. ft. gas range features multiple burner options that provide precise control at all temperatures, so you can prepare food while using the right amount of energy with the right burner. The smooth surface of this stove is now even easier to clean with the raised edges of the SpillSaver™ upswept cooktop. And with features like the extra-large oven window, it will be even easier to keep a close eye on that fillet of sole with capers that you are preparing for dinner.
- The multiple burner options on this versatile gas cooktop provide precise control at all temperatures, so you can prepare food while using the right amount of energy with the right burner
- The 5.0 cu. ft. of capacity within this oven allows you to cook multiple dishes at once, so you can handle everything from daily meals to large family dinners with ease
- This adjustable self-cleaning oven lets you select the right amount of cleaning for light or heavy soils
- Extra-large oven window lets you keep a close eye on your food, without opening the oven door
- The included LP gas conversion kit enables conversion of your natural gas range for use with propane gas
Specifications & Dimensions
Product Documentation
Owner's Manual - English (Warranty)
Installation Guide
Product Warranty - English
More Like This
View Product
View Product
View Product
View Product


text:
what are system wide locations in linux?
is there only one such location? can it be changed?
Printable View
what are system wide locations in linux?
is there only one such location? can it be changed?
Hi and welcome
there are multiple type of file.
Binaries, configfiles, logfiles, etc
Each do have well defined system wide locations, and some additionally do have user local ones.
You didnt specify, which type you need. So for a comprehensive overview, look here:
Filesystem Hierarchy Standard
actually i was trying to install java on ubuntu 12.10 from this link
there is a note about root access on the page.....can you explain me what its saying?
root is a privileged user.
This account has control over all the aspects of a system, not just file access.
As you are using ubuntu, this guide is more appropiate
so where should i install java so that "java -version" will work?
Just follow the documentation I linked.
sudo update-alternatives --config java
this gives no alternatives.
Depending upon the variety of java you are installing, it can be installed into /etc/alternatives (openjdk) or /usr/java (sun/oracle java). If you installed sun/oracle java, then the last version you installed will have a link as /usr/java/latest, and /usr/bin/java will have been configured to point to the bin/java executable under that. You can have multiple versions of java installed, but only one will be the default. Personally, I very much dislike the alternatives way of doing things, but have to deal with it given we do a LOT of java programming where I work. Thankfully, most of my work is in C++... :-)


text:
FRITCH - The Fritch Police Department has a new chief and soon will have new office space.
Terry Cox, a lieutenant with the department, will move up to the chief's spot effective immediately, said Ric Walton, Fritch city manager.
"All things being equal, considering his experience and the fact he knows the town, he knows the structure and it's a structure that works well for him," Walton said.
Cox, a six-year veteran at the Fritch Police Department, succeeds Trevlyn Pitner, who left last month to work as Pampa's police chief. Cox worked as the interim chief while the city looked for a permanent replacement.
"I think it's great," Cox said of moving into the police chief's position. "Our former chief (Pitner) left us in excellent shape."
The city did a statewide search through the Texas Municipal League and got nine resumes from New York to Arizona, Walton said. Some of the city's minimum requirements for the job narrowed the field, he said.
Requirements for the position included administrative experience, certified peace officer documentation and some college and law enforcement.
Cox said he has been in law enforcement for 20 years, starting at the Pampa Police Department and then the Gray County Sheriff's Office. He plans to work on grants through the Panhandle Regional Planning Commission to upgrade the department's radio system and hire a new patrolman.
© 2016. All Rights Reserved. | Contact Us


text:
To the Editor.—
In a recent issue (229:763, 1974), Shaffer describes a series of cases characterized by anesthesia, analgesia, nystagmus, dizziness, diplopia, visual distortions, and psychosis. These findings were attributed to ketamine, a derivative of phencyclidine. Phencyclidine is a major component of street drug preparations.1 In one series, phencyclidine was detected in 184 of 237 street drug samples.2 In liquid form, phencyclidine is sprayed on marihuana, parsley, oregano, or other plant leaves and sold as "angel dust." As a powder, it is marketed as phencyclidine or "peace pills."3 It is frequently sold as LSD, mescaline, psilocybin, cocaine, 3, 4 - methylenedioxyamphetamine (MDA), tetrahydrocannabinol, and other more "attractive" drugs. Or it may be mixed with these agents.2,3Both ketamine and phencyclidine are sympathomimetic anesthetics.4 However, phencyclidine is a much more potent hallucinogen.4-6The abuse of these compounds is a massive and generally unrecognized problem. Recently, 41
Some tools below are only available to our subscribers or users with an online account.
Download citation file:
Customize your page view by dragging & repositioning the boxes below.
More Listings atJAMACareerCenter.com >
Enter your username and email address. We'll send you a link to reset your password.
Enter your username and email address. We'll send instructions on how to reset your password to the email address we have on record.
Need assistance?
Athens and Shibboleth are access management services that provide single sign-on to protected resources. They replace the multiple user names and passwords necessary to access subscription-based content with a single user name and password that can be entered once per session. It operates independently of a user's location or IP address. If your institution uses Athens or Shibboleth authentication, please contact your site administrator to receive your user name and password.


text:
Sudu Upadhyay and Chuck Rounsaville talk all the latest in Ole Miss spring football and more
OM Spirit Top Stories
Ole Miss Commitment Progress ReportHow did the Ole Miss commitments fare in their contest last week? Read inside.
OM Spirit10:21 AM
Podcast: Answering Ole Miss Mailbag QuestionsIn this edition of the Ole Miss Spirit Podcast, Ben Garrett and Sudu Upadhyay answer listener questions, including the latest on the NCAA investigation, Memphis and more.
OM Spirit9:12 AM
Offensive Line Starting to ClickEven though he's just a sophomore, Ole Miss Right Tackle/Center Sean Rawlings - along with fellow sophs Javon Patterson and Jordan Sims - are some of the leaders in the offensive…
OM SpiritYesterday at 10:00 PM
Friday Focus: Ole Miss vs. Memphis#16 Ole Miss takes on Memphis on Saturday at Vaught-Hemingway Stadium. Kickoff is set for 6 p.m. CT on ESPN 2.
OM SpiritYesterday at 4:29 PM
Mississippi Ties for 4-Star DT Noah EllisNoah Ellis out of Highlands Ranch, Colo., is well into his senior season. The 6-foot-4, 325-pound defensive tackle knows that he'll have make a decision where he's going to spend…
OM SpiritYesterday at 11:44 AM


text:
Speech-Language Pathology, M.S.Ed
The Council on Academic Accreditation in Audiology and Speech-Language Pathology (CAA) of the American Speech-Language-Hearing Association Accredited
Enrollment in all teacher education programs follows the guidelines for "Admission to Teacher Education Programs" found in the catalog. Applicants who do not yet meet all admissions criteria should consult with the department.
Programs must be planned under advisement and approved by the director of the graduate studies and the department chair. Students are expected to complete academic and clinical education requirements to qualify for the Certificate of Clinical Competence (CCC) in speech-language pathology issued by the American Speech-Language-Hearing Association (ASHA) and New York State licensure in speech-language pathology. Additional coursework may be required for teacher certification. Students must complete a minimum of three semesters of supervised practica in the Speech-Language-Hearing Clinic prior to placement at off-campus practica. Only students in good standing are permitted to enroll in SLP 505 Graduate Practicum in an Educational Setting and SLP 611 Externship in Communication Disorders. Students must meet with their academic adviser before initial registration to plan a program that will ensure completion of ASHA certification, New York State licensure, and New York State teacher certification requirements.
The master's in education (M.S.Ed.) program in speech-language pathology at SUNY Buffalo State has been placed on probation by the Council on Academic Accreditation in Audiology and Speech-Language Pathology (CAA) of the American Speech-Language-Hearing Association, 2200 Research Boulevard #310, Rockville, Maryland 20850, 800-498-2071 or 301-296-5700. A program on probation is not currently in full compliance with the accreditation standards. Programs on probation remain accredited but must demonstrate compliance with the standards within one year. The CAA's Accreditation Action Report is available online on CAA's webpage for recent accreditation decisions (http://www.asha.org/Academic/accreditation/caaDecisions/).
The master's in education (M.S.Ed.) degree program in speech-language is also registered with the New York State Education Department, 89 Washington Avenue, Albany, New York 12234 http://www.nysed.gov/contact-NYSED, for licensure in speech-language pathology (http://www.op.nysed.gov/prof/slpa) and for the initial/professional teaching certificate (Teacher of Speech and Language Disabilities; Teacher Certification, 518-474-3901).
Curriculum is currently under revision. Contact Department Chair for details.
208 Ketchum Hall
1300 Elmwood Ave
Buffalo, NY 14222
Phone: (716) 878-4412
Fax: (716) 878-5711
1. A bachelor's degree from an accredited college or university with a minimum cumulative GPA of 3.0 (4.0 scale).
2. A minimum of 25 credit hours of undergraduate coursework in speech-language pathology that includes courses related to the normal development of speech, language, and hearing processes; courses related to disordered speech, language, and hearing; and courses related to the speech and hearing sciences. For ASHA and NCATE certification, the following courses are also required. If they were not taken at the undergraduate level, they will be added to the graduate program:
3 credits in a biological science
3 credits in the physical sciences
3 credits in math (can be MAT 311)
3 credits in the social and behavioral sciences
SPF 202 Child Development and Education
SPF 302 Educational Psychology: Elementary Education
EXE 100 Nature and Needs of Individuals with Special Needs
3. Three letters of recommendation that attest to the applicant's potential as a graduate student. For students with an undergraduate major in speech-language pathology or communication sciences and disorders, two of the letters must come from faculty in the major. For students from other majors, two of the letters must come from faculty in the major.
4. Graduate Record Examination (GRE) scores. All three scores will be evaluated.
5. A written personal statement reflecting reasons for choosing this discipline.
Application Deadline: Applicants must apply by February 1 for summer or fall admission. No applications are accepted for spring admission.
Application Procedures: The Speech-Language Pathology Department is currently participating in the Communication and Sciences Centralized Application Service (CSDCAS). To apply to the graduate program in speech-language pathology students must submit application to the SUNY Buffalo State Graduate School and apply online using the CSDCAS application.
Required Courses* 38 cr
SLP 501 Clinical Methods (2)
SLP 511 Neural Processes of Communication
SLP 516 Diagnostic Principles and Procedures (2)
SLP 518 Extended Applications in Communication Sciences and Disorders (1)
SLP 541 Language Disorders: Birth to Age 5
SLP 580 Research Methods in Speech-Language Pathology (2)
SLP 605 Contemporary Issues in Clinical Interactions: Families and Culture (2)
SLP 606 Fluency Disorders and Cleft Palate (3)
SLP 607 Dysphagia Across the Life Span (2)
SLP 608 Neuromotor Speech Disorders Across the Life Span (2)
SLP 609 Disorders of Voice (2)
SLP 610 Evaluation and Treatment of Phonological Disorders
SLP 621 Augmentative and Alternative Communication (2)
SLP 622 Language Disorders of School-Aged Individuals
SLP 623 Acquired Language Disorders
SLP 625 Advanced Topics and Issues in Communication Sciences and Disorders*
Practicum* 19 cr
SLP 505 Graduate Practicum in an Educational Setting (6)
SLP 515 Clinical Practicum (7; 1-3 cr per semester)
SLP 611 Externship in Communication Disorders (6)
Master's Project or Master's Thesis* 3-6 cr
Select one option:
SLP 690 Master's Project
SLP 695 Master's Thesis (3-6)
Comprehensive Examination 0 cr
*Students who elect to take the comprehension examination must enroll in SLP 625.
Total Required Credit Hours 57-60 cr
* Selected under advisement
All courses are 3 credit hours unless otherwise indicated.


text:
From the IBM WebSphere Developer Technical Journal.
This article provides general guidance for creating well performing custom code for IBM WebSphere Portal. Custom code does not only refer to portlets (although they are the most common programming model for portals), but also includes code for WebSphere Portal themes and skins. Since these are implemented using the same basic technologies used for portlets, many performance considerations are applicable in the same way.
Regarding portlets, this article focuses on standardized portlets following the Java™ Portlet Specification, JSR 168, and the corresponding implementation in WebSphere Portal. The basis for this article is WebSphere Portal V5.1 or higher, although most guidelines and recommendations presented here will apply regardless of the version of WebSphere Portal you are running.
This article will explain how to set up and exploit the deployment parameters of a portlet application to optimize portal and portlet performance, since this is the last step in creating custom portal code. In contrast, general tuning of WebSphere Portal (that is, administrative actions that are performed after custom code has already been created and deployed) will not be covered here. Another document is available that covers WebSphere Portal performance tuning. That document combined with this one will provide an excellent resource on portals and performance.
This article is intended for programmers, designers, and architects involved in building custom portal applications and want to improve their understanding of potential performance issues with regard to custom code.
WebSphere Portal environment overview
IBM WebSphere Portal is built upon the IBM WebSphere Application Server product. As a result, the programming environment for custom portal code is threefold, with important corresponding implications:
WebSphere Portal and all its components are Java-based programs.
Thus, in general, best practices with regard to programming high-performance Java code should be followed.
WebSphere Portal is a J2EE application running on top of an application server platform.
J2EE embraces multi-threading; J2EE containers typically take a thread-per-request approach to handle the request burden. Any implementation or performance considerations inherent with using this mechanism should likewise be taken into account.
WebSphere Portal provides APIs to expand portal functionality.
Many tasks can be programmed in many different ways. Differences that affect performance should be addressed as a priority.
The next sections introduce some general performance considerations for different parts of the portal programming environment.
Clearly, this section is not intended as a complete treatment of Java performance. Instead, we present here the items we have found most useful when dealing with WebSphere Portal development, and suggest some resources that can help provide an indepth understanding of Java performance (see Resources).
Basic Java performance
In this section, we will cover some general performance items that will apply to most Java programs. Although these recommendations may not yield order of magnitude performance improvements, they can make you aware of the importance of low-level program execution performance while in the development phase.
- Use java.lang.StringBuffers instead of java.lang.String instances when the modification of strings is required.
String objects in Java are immutable, whereas StringBuffer objects are mutable. Whenever text is to be appended to or deleted from a String, a new object is created under the covers and the old object is discarded. Hence we prefer this:
StringBuffer sb = new StringBuffer("Hello "); sb.append(var).append(" World");
over this string concatenation:
String s = "Hello" + var + " World";
You can sometimes further improve performance by setting the initial capacity of a StringBuffer; the class is designed to automatically grow when it can no longer hold all its data. However, there is a performance penalty here, since a StringBuffer must work to transparently increase its size and shift the data around. For example, if a StringBuffer is used as a collecting parameter (meaning that more and more data is added to it), you should compute the appropriate buffer size before instantiating it so that it never needs to grow in size.
- Avoid costly I/O operations in server-side programs.
Execution of at least this thread is blocked during the I/O operation; if other threads also must wait for the disk, then system response times will easily and rapidly increase. Unless logging is being performed (for example, of exceptions or site access information), WebSphere Portal does not cause any disk access on its own. We will discuss I/O more later.
- Minimize the number and length of synchronized code blocks.
The synchronized keyword lets only one thread enter a code block at a time. The longer a synchronized code block requires for execution, the longer other threads wait to enter that block. We will discuss synchronization more later.
- Avoid expensive calculations and method calls.
For example, retrieving the current time information using System.currentTimeMillis() is rather expensive. If you need time information in your code, verify whether you need the exact time in every case, or (for example) if accuracy to the nearest second would be sufficient. If you have many get-time calls in your code path, but millisecond-accuracy is not mandatory, an alternative could be to determine the time at the beginning of a request and simply reuse this information throughout the request.
- Restrict your use of exceptions.
In general, exceptions in Java should be used to indicate a faulty situation. Do not use exceptions to indicate the success of an operation, especially because creating the exception stack traces is a time-consuming effort for the JVM, and because the traces can be very deep in a WebSphere Portal system.
- Take care when using the Java Reflection API.
This API adds powerful options to dynamic code execution, but also imposes severe performance penalties in terms of method execution times in exchange for this flexibility. In general, try to avoid the use of the Java Reflection API in portal code. However, if it is necessary to have reflection calls, try to have them in init methods so that they are not executed during every request.
Memory consumption and garbage creation
While memory often is not a predominant performance issue for Java client software, it is a major concern for J2EE applications, mainly because enterprise applications are typically accessed by many users at the same time. For an application server to be efficient, the available resources, including memory, CPU and bandwidth, are shared among the clients' requests. There are three major memory issues we want to mention:
- Keep the amount of temporary objects to a minimum.
That means, try to reuse objects as often as possible, and do not create new object instances too often. The more objects that are created, the more frequently the JVM garbage collector has to reclaim memory and, at least partially, interrupt request handling at that time. Creating many objects also tends to increase heap fragmentation, which leads to even more garbage collection cycles. For example, do not create objects prematurely:
String logData = "Parameter 1: " + param1; if (logger.isLogging(DEBUG)) { logger.log(logData); }
In this example, logData should only be created after evaluating the condition. Caching and pooling can be helpful techniques to reduce temporary object creation. To identify the parts of your code that contribute most to memory allocation issues, see Tools.
- Keep your permanent memory footprint low.
Do not read too much information into memory; rather, use caches to hold important information. Sometimes it is possible to change the data type for a piece of information. Date information, for example, can be held within a java.util.Date object or in a long variable. Objects typically are larger and somewhat slower to process than primitive data types. It might depend on the surrounding APIs and data structures which data type is preferred. In general, a higher memory footprint leads to higher garbage collection rates and additional pause times during request processing.
- Check your application for memory leaks.
When leaks occur, they typically occur within Java collection classes. For example, you have a java.util.Map and, under certain conditions, data is added to the map but never removed from it. Memory leaks lead to more and more consumption of memory that is reserved by the Java heap, and the garbage collector will be able to free up less memory over time. Thus, garbage collection will occur more frequently, and, finally, the portal system will become unresponsive. To complicate matters, memory leaks are often uncovered by long-running tests only, but there are tools around that can assist you with this analysis (see Tools).
Code design for performance and scalability
There is much to remember when designing and developing code for scalability. Three things of particular importance are: Caching, pooling, and information pre-fetch:
- Caches store already computed results.
For example, you can retrieve information from a backend system, but rather than copy every possible object from the store to memory, just load small pieces and put them into a cache. This way, the information is available for later reference, possibly in another request, or even for another user.
Caches almost always take the form of object maps with an upper size limit. A cache also has to have a way of knowing when something is unlikely to be asked for again so that it can be removed from the cache when appropriate. Such evictions are typically determined by a "time-to-live" (TTL) or "least-recently-used" (LRU) algorithm. Furthermore, the client using a cache cannot be confident that it will successfully retrieve an object from the cache; it must check for its existence, and then create the object if it is not found:
Mail mail = myCache.get("myMail"); if (mail == null) { mail = readMailInformation(); myCache.put("myMail", mail) ; } ...
(In some cases application-specific caches can be designed in such a way that they lookup the required data from some data source that is transparent to the client.)
- Object pools are used to restrict the number of instances of a certain class.
Often, a request requires an instance of a certain class, but this object does not (and should not) need to be recreated in every request. This is especially true in cases where object creation and initialization are expensive. Rather than accepting the performance hit, clients can request objects from a pool and then return them to the pool after finishing their use case.
PooledObject po = myPool.get(); ... // use the PooledObject ... myPool.put(po);
- A simple form of pool is to canonicalize an object.
This means that all different instances of an object are created during the program initialization phase and reused and referenced later on. The class java.lang.Boolean provides an example of an object that is canonicalized. There need to exist only two different Boolean objects, preferably accessible as constants. The same can be done with other objects with fixed sets of read-only internal state.
- Do not fetch more data as you currently want to process.
For example, in your portlet you could provide a list of e-mails; the portlet displays the subject, date, sender, and other important information. When the user selects a particular e-mail, the body of the e-mail displays. The body is not needed before the specific item was selected from the portlet, so retrieving it any earlier would be a waste of execution time and memory resources. This pattern applies to many situations. The general rule is to only compute and retrieve those pieces of information that have direct significance for the current request and response.
IBM WebSphere Application Server is the J2EE implementation upon which WebSphere Portal is built. Many of the performance considerations in the subsequent section apply due to the J2EE runtime context. The following sections describe performance items that are only applicable to IBM WebSphere Application Server. The items listed below are described here at a high level, and will be explained in more detail later in this article. For a more general discussion see Resources.
J2EE standard
The J2EE standard specification contains a number of items with performance implications:
init methods, available for many J2EE resources -- and also for portlets -- should be used to pre-calculate everything that will be used later on and that will not change. For example, JNDI lookups for common resources such as a data source should be performed only once at initialization time. Also, reading data from certain read-only files should be done just once during initialization of a portlet. You can scan your portlet service methods for any code that is executed in the same manner on every request and move it to the init method to reduce the run time cost for the service methods.
EJB components and sessions are important and powerful concepts within J2EE, but either of these can have severe performance implications if not used wisely. For example, applications should not put too much data into sessions to reduce the memory footprint of the server and to make session persistence easier and faster. Regarding EJB components, you should become familiar with the different persistence types associated with remote and local invocation, and so on. Some features available for EJBs come with a high performance penalty.
WebSphere Application Server
WebSphere Application Server products provide features to assist developers and architects in designing high-performance systems. (See the Information Centers for WebSphere Application Server and WebSphere Business Integration Server Foundation in Resources.
- As mentioned earlier, database connections are expensive to create. As defined in the J2EE standard, application servers can provide a pooling facility so the connections do not need to be recreated with every incoming request. WebSphere Application Server provides such a pooling facility together with some additional performance helpers, like a statement cache for frequently executed SQL statements. However, failing to return the connection immediately after completing the database interaction results in making the connection unavailable to other requests for significant periods of time. Using the WebSphere Application Server administrative console, you can control connection pools as properties of data sources to a JDBC database, and can define, for example, a minimum and maximum number of connections for the pool. (See the WebSphere Application Server Information Center for more information.)
For example, database connections are expensive to create. In this case, it is possible to make use of JDBC connection pooling and leverage the prepared statement cache as provided by WebSphere Application Server:
. . . public class IDontCare extends GenericPortlet { private javax.sql.DataSource ds; public void init() throws javax.portlet.PortletException { try { Hashtable env = new Hashtable(); env.put( Context.INITIAL_CONTEXT_FACTORY, "com.ibm.ejs.ns.jndi.CNInitialContextFactory" ); Context ctx = new InitialContext( env ); ds = (javax.sql.DataSource)ctx.lookup( "jdbc/MYSHOES" ); ctx.close(); } catch (Exception any) { // handle exceptions here . . . } } . . . public void processAction ( ActionRequest request, ActionResponse response ) throws PortletException, IOException { . . . try { Connection con = null; ResultSet rs = null; PreparedStatement pStmt = null; con = ds.getConnection ( dbuser, dbpasswd ); pStmt = con.prepareStatement( "select * from myscheme.size_of_shoes"); rs = pStmt.executeQuery(); . . . // release the resource when it is no longer used if (pStmt != null) pStmt.close(); if (con != null) con.close(); } catch (Exception any) { // handle exception here . . . } } }
WebSphere Application Server also supports the general concept of object pools, with each pool consisting of a pool manager providing access to pools for different class types. Such pools can be queried for an instance of the class type, as given in the previous example about pools. See the WebSphere Business Integrator Server Foundation Information Center for more information.
WebSphere Application Server also provides a "general purpose" cache. In the admin console, you can define cache instances that your applications can use to store, retrieve, and share data. Unlike the default shared dynamic cache, which is used by the portal to cache objects, a cache instance is only accessible to those applications that know its JNDI name. The DistributedMap interface is the programming interface that your applications work with, enabling the application to get and put objects into the cache instance, as well as invalidate them. See the WebSphere Business Integrator Server Foundation Information Center for more information.
If portlets make use of a caching implementation, they should look up or instantiate a cache instance in their initialization phase and keep a reference to that cache so that cache entries have a lifetime that is potentially longer than a single request. While processing the action and the render phase of a portlet, entries can be put into and retrieved from a cache. The portlet implementation needs to make sure that there is proper backend access and cache update handling if the cache does not return the data when queried with a certain key. Also, be aware that scoping of keys into the cache (for example, per user session) might be required for proper function of the intended design. A cache is typically a self-managed unit that can evict or invalidate entries dependent on the cache implementation. Note that, for the same reason, a cache is not suitable to communicate information back and forth between several pieces of code. A cache should also maintain a reasonable upper size limit to avoid memory over-utilization in custom code.
Portal APIs
WebSphere Portal supports two different portlet APIs:
- IBM Portlet API, which extends servlets.
- JSR 168 Portlet API, which is defined by the Java Community Process (JCP).
In this article, we focus on the JSR 168 Portlet API.
WebSphere Portal provides a variety of interfaces for integrating your portlets into the WebSphere Portal environment. As such, portlets should be carefully designed to take advantage of portal features. Be sure to apply best practices (such as those listed in Resources) so that your application of WebSphere Portal APIs is appropriate.
Common implementation considerations
In this section, we look at performance topics that are relevant for theme and skin programming, as well as portlet development.
JavaServer Pages (JSPs) are one of the cornerstones of portlet programming. In most portlets, using Model View Controller (MVC) terminology, JSPs function as the view component. JSPs are composed of a mixtures of HTML (or other markup languages) and Java code; their processing output is also a markup language, in most cases HTML. In its purest form, JSPs do not contain any Java code, but only custom tags that are called to perform non-HTML operations. (Conversely, it is also possible to have virtually no HTML content in a JSP file.)
- Upon the very first access to a JSP file, the file is parsed and translated into a regular Java servlet source file, which is then compiled into byte code. Hence, the very first request to a JSP is typically slow due to the two subsequent conversions (from JSP to Java source to byte code), but then it works like any other servlet for all future requests.
This is different from another approach for generating HTML content: XML and XSLT. In this case, upon every request the XML has to be parsed and style sheet transformations have to be applied. Only a good approach of caching the results and not re-running the transformations upon every request can save the performance here. Hence, from a performance point of view, JSP should be preferred over XML/XSLT. Furthermore, the portal infrastructure is optimized around JSPs, enabling easy expansion into other markups, languages, and browser support.
Application servers execute JSPs similarly to how they execute regular servlets. Nonetheless, servlets resulting from JSP compilation contain generated code, which is, in general, less optimized for performance than handcrafted code. If performance is very important for a certain JSP and you cannot achieve your goals with generated code, consider writing the markup into the output stream by yourself.
Java code fragments in JSPs are called scriptlets. Since JSPs are converted to Java source code anyway, there is no real performance penalty associated with using scriptlets. Some optimizations in the latest version of WebSphere Application Server apply to JSP files in cases where a JSP file does not contain any scriptlets. In general, you should not put scriptlet code into your JSPs, and instead use tags for those tasks.
JSPs can include other JSPs. That means that a single JSP does not have to answer the complete request; you can split the response into multiple JSPs and include others from a parent JSP. There are two different forms of inclusion, static and dynamic:
Static JSP includes are resolved at compile time. The JSP compiler includes the referenced file instead of the include statement. This option is generally very fast and adds no run time overhead at all.
<%@ include file="include2.jsp" %>
Dynamic JSP includes are resolved at run time, which is not an inexpensive undertaking. Resolving the correct JSP to which to dispatch is quite expensive in terms of garbage creation and execution time. For example (inside a JSP):
<jsp:include page="include2.jsp" flush="true" %>
Dynamic inclusion in JSPs is similar to using javax.servlet.RequestDispatcher when including other files from servlet code. Therefore, wherever possible, you should use static includes. Dynamic includes offer the highest flexibility, but come with a significant performance overhead if used too often.
EJB usage
Enterprise JavaBeans (EJB) define a component-based architecture for building scalable, transactional, distributed, and multi-user business applications. EJB components are designed to encapsulate the business logic while hiding all complexity behind the bean and built-in EJB container services.
The support for the variety of functions frequently required by enterprise applications does not come for free, as there is a certain amount of performance overhead that needs to be taken into account when using EJBs.
A portlet can obtain EJB references through JNDI lookups, which tend to be expensive with regard to performance. For example, if a portlet does not cache the reference to the EJB home interface somewhere, then every logical call to the EJB requires two remote calls: one to the naming service, and one to the actual object. To rectify this situation, use caching techniques to reduce or eliminate repeated lookups of EJB home references.
EJB components expose remote and local interfaces. EJBs that are location-independent use a remote interface. Method parameters and return values are serialized over RMI-IIOP and returned by value. Remote methods must be designed to satisfy data needs according to the usage pattern of the API. Use a granularity of methods and data types in the API that fits well with the use cases of the interface to minimize serialization costs.
Minimize the number of remote calls to reduce the overhead imposed by remote calls in your code path. Use session beans acting as remote facades to wrap complex interactions and to reduce remote calls between portlets and domain objects. A portlet accessing a remote entity bean directly usually results in several remote method calls. If you use entity beans in this context, avoid giving them a remote interface. Instead, session beans acting as facades can access entity beans via their local interfaces, gather data from them, and then return this information to the calling application.
The concept of local interfaces works when the calling client (such as a session facade) shares the same container as the called EJB. The use of local interfaces reduces inter-process communication costs by eliminating the overhead of a distributed object protocol. Local calls do not go through the communication layer and any objects can be passed by reference.
Transaction management supported by the EJB container can also affect performance. After developing an EJB, the programmer must set deployment descriptors that define characteristics, such as transaction support and isolation levels for the EJB. Set the transaction type to NotSupported if no transaction is required.
The transaction isolation level is the degree to which the underlying database exposes changed but uncommitted data to other transactions. For the best performance, use a liberal isolation level. Letting uncommitted data be seen by other transactions, however, can result in unexpected side effects, such as clashing updates and inconsistent reads. For instructions how to set isolation levels see the WebSphere Application Server V5.1.x Information Center.
See the IBM white paper WebSphere Application Server Development Best Practices for Performance and Scalability and the IBM Redbook IBM WebSphere V5.1 Performance, Scalability, and High Availability WebSphere Handbook Series for additional recommendations, as well as the justification for each recommendation.
Markup size
Markup size refers to the number of bytes to be transferred from the portal server to the client for a completely rendered portal page. From a portal server point of view, the most important part is the size of the HTML page containing the resulting markup. Other files, like stylesheets, images, or JavaScript, must be transferred to the client as well. Since the static files are typically stored outside the portal system on HTTP servers or proxy caches, we will concentrate here on the "real" HTML markup size.
Why do we bother at all about markup size? Within company intranets, there are probably lesser issues with network bandwidth, but if users are connected via modem or other low-bandwidth network connections, lengthy download times for large HTML responses can be very annoying.
Here is a short calculation. Let's assume that a server or cluster is processing up to 100 requests per second. The average HTML page size should be 100 KB, which may seem like a lot, but can easily be reached if you have a complex theme and several portlets on the page. For the server, this means that it has to put about 10 MB/sec on the wire (100 KB * 100 pages/sec). This is about the maximum traffic a 100 MB network can handle. (You cannot expect an Ethernet to support 100% of its potential capacity of 100 MB/sec and the inbound traffic is typically not negligible. For users connected to the portal via 56K modem, the download time for one page would be in the area of 15 seconds!)
How large is too large? This is difficult to answer in general. However, more than 100 KB per HTML page is probably too much. Also, keep in mind that smaller devices have restrictions on the markup size they can handle per request.
The main contributors to markup size are the theme and the portlet output. Since all portal JSPs are customizable, you can influence how compact your markup is at the end. Here is what you can do to limit the size of your markup:
Use JSP comments instead of HTML comments inside your JSPs.
Comments of the form <%-- ... --%> will be deleted by the JSP compiler, while comments of the form <!-- ... --> are kept and transported over the wire.
Try to reduce the amount of white space, tabs and line breaks inside your JSP source files since these are retained by the JSP compiler.
This may reduce legibility of the code. It can be helpful to have code in development that is nicely laid out, but it is processed and stripped off its formatting with a tool before the JSP files are applied to your production environment.
Try to avoid sending the same information to the client several times.
If your environment setup for it, you can also send compressed markup using HTTP compression to the client.
Refer to your Web server's and your clients' documentation for more information.
Logging, tracing, and I/O
Logs usually end up on the hard disk at some point. From a performance perspective, anything interacting frequently with the disk presents a potentially expensive operation, so it is best to minimize the use of the Java I/O library in the production environment. Since the I/O is usually provided through the use of some native library layered beneath Java programming, there is some default overhead incurred. An operation like System.out.println synchronizes processing during file I/O, which significantly impacts performance.
In development and test mode, you may want all the logging and debugging to be active, since it could be essential for finding errors. When you deploy your application in a production environment, leaving extensive logging on is just not a viable option. It is a good practice to guard log statements so they are turned on during error and debugging situations only. Do that by using a final Boolean variable, which, when set to false, effectively tells the compiler to optimize out both the checking and execution of the logging code:
static final boolean LOGGING = false; if (LOGGING) {...}
The Java language provides two types of streams: readers/writers and input/output:
- Readers and writers are high level interfaces to support unicode characters in I/O operations.
- Input/output streams provide data access mechanisms at a much lower level; at the byte level.
There is a performance overhead involved with readers/writers because they are intended for character streams, and they encode data to bytes under the covers. Instead, you should use input/output streams whenever you want to manipulate binary data.
To maximize I/O performance, you should buffer read and write operations. If you want to write large amounts of data from a portlet, it is usually a good approach to flush the buffered data partly rather than flushing them completely in a single blow. On the other hand, do not flush the buffer too often.
Synchronization and multi-threading
The Java mechanism that is used to coordinate access to shared objects is called synchronization. The synchronized statement enbales only one thread to enter a code block at a time.
During the lifetime of a portlet, the container sends service requests in different threads to a single portlet instance. Avoid synchronization within a portlet because it has a significant performance impact: synchronization reduces concurrency, since only one thread is allowed to run at a time in a synchronized block of code and all the concurrent threads are queued. There is also performance overhead caused by managing the monitors that the Java virtual machine uses to support synchronization. Besides the performance impact, there is also the possibility of deadlocks that can potentially freeze the single portlet or -- even worse -- the whole portal. Deadlock prevention is the programmer's responsibility, because the monitors do not support any deadlock resolution.
In cases where synchronization is necessary, the synchronized code block should be minimized. It is crucial to accurately identify which code block truly needs to be synchronized and to synchronize as little as possible. If it is not small enough, you should analyze your code and refactor it in such a way that anything that could run asynchronously is located outside of the synchronized block.
Some Java J2SE functionality indirectly uses synchronization. Java collection classes, like Vector or Hashtable are fully synchronized. Java programs pay the costs associated with thread synchronization even when they are used in a single-threaded environment. Newer collections introduced in Java 1.2, like ArrayList are not synchronized. This provides faster access to the data. In situations where you know you need thread safety, use a thread-safe view. Thread-safe views are wrapper classes that add functionality to synchronize the methods of the standard collection. The factory method of the Collections class returns a thread-safe collection that is backed by the instance of the specified collection type:
List list = Collections.sychronizedList(new ArrayList());
Another example of indirect synchronization is the Java I/O libraries. Minimize the use of Java I/O library methods (for example System.out.println())to reduce unnecessary performance overhead.
Do not spawn unmanaged threads from portlets. Currently J2EE strongly discourages from trying to spawn new threads in the container. In fact, J2EE specification 6.2.1 programming restrictions states:
"If application components contain the same functionality provided by J2EE system infrastructure, there are clashes and mis-management of the functionality. For example, ... to manage threads, ..."
A practical reason for not trying to spawn new threads is that new threads do not have full access to the J2EE context. Further, newly created unmanaged threads undermine the goal of WebSphere Portal to achieve a stable, optimized and scalable run time environment. Therefore, use the asynchronous bean feature (See WebSphere Application Server Enterprise V5 and Programming Model Extensions WebSphere Handbook Series) in WebSphere Application Server. An asynchronous bean is a Java object or enterprise bean that has the ability to submit code to be run on a separate thread -- and asynchronously -- using the J2EE context.
The portlets programming model enables developers to create Web applications that can become part of an aggregated view of several of such applications in a client browser. In WebSphere Portal, such applications can not only coexist on a page (that is, the aggregated view), they are also able to communicate with each other while constructing the page. Thus, the implementation of a portlet can influence the overall perceived performance of a page. If a specific "critical" portlet resides on a page, then it may be worthwhile to invest some effort in optimizing this specifc portlet. You should also have a deeper look at portlets that reside on performance-critical pages.
Backend access
Totally self-dependent portlets are a rare case in real world portals. Such portlets are typically used as an addition to or helper tool for a Web site; for example, a pocket calculator. Such portlets can be optimized in their local code execution path only and should not put too much burden on a running portal system.
A more typical usage of portlets is to offer application functionality that requires access to other data sources or transaction systems that also require execution resources apart from the system where the portlets are originally running. Data is potentially retrieved from and stored on other backend systems over a network. The transaction length, isolation level, and data locking that may occur on the backend system needs to be considered in the overall system design.
Be aware that a single portlet is probably not the only client of a backend system. In fact, there are many clients to such a system in the real world -- and even a single portlet can access the same backend system several times simultaneously. A portlet might execute its code in separate application server threads for different user requests. Therefore, it is worth investigating the access patterns and how transactions and locks acquired by a portlet or other clients can potentially influence the average response time of such a backend system.
If a portlet requires intensive backend system access during the action or render phase, the response time (for finishing these phases) more and more depends on the responsiveness of the backend system. (Waiting for responses from outside the portal server to satisfy incoming requests will introduce latency that cannot be recovered by optimizing the execution path of the portlet code.) A good design for communicating with the backend and an understanding of transactional behavior is often more promising.
To avoid times when a portlet -- and the page on which it appears -- fails to respond because of a collapsed backend system, it can be a good practice to incorporate timeouts in your code; be aware, though, that managing and keeping track of time stamps introduces some processing overhead. If the parallel portlet rendering feature in WebSphere Portal is used (discussed later), time outs are configurable for the parallel render threads.
It is also a good programming practice to reduce the interaction and data traffic to such external backend systems, where possible. To achieve this, portlets can cache information if the freshness criteria of the information permits you to do so. This may reduce the roundtrips for fetching the same data over and over again for each incoming request to WebSphere Portal. It also helps to lower the load on the backend system, since it is not involved in providing the same information so many times. Also, if the data does not need to be transferred over the network, the portlet can potentially be rendered more quickly.
Another way of avoiding roundtrips to the backend system can be to retrieve more data than is actually required to fulfill the current request, but that is known to be required in a request that would otherwise follow. With this approach, however, we still advice against general prefetching if it is not known what prefetched data is actually needed in subsequent requests. A good understanding of typical user interactions with the portlet application is needed for a proper design of this nature. Keep in mind that retrieving data in advance has an impact on memory usage of the portal JVM. (See Code design for performance and scalability. ) Such design approaches might require an interface change of the backend system, but it could save considerable processing time that might make such a change worth it.
For caching, WebSphere Application Server offers a dynamic caching feature with its DistributedMap interface to portlets. (See WebSphere Application Server 5.1 Information Center for more information.)
The session and other data stores
Keeping and maintaining data for a portlet that should have a lifetime longer than a single request is a typical portlet programming task. Using PortletSession is often the first approach that is considered. While PortletSession is convenient to use from a programmer's perspective, it requires resources for managing sessions from an application server perspective. The problem can get worse if the session contains more and more data and thus requires more memory.
If the session is configured to be persistently stored in a database, or is configured for memory-to-memory replication (that is, WebSphere Portal is configured for failover in a clustered environment), then the session may become serialized any time its contents changes.
The time it takes to serialize and deserialize session data when they are being written to a remote copy can become considerably large. In rare cases, some objects stored in a session can be marked transient. This will reduce the serialized size of a session, but will not change the in-memory size, which also has an impact on how efficiently an application server can handle sessions.
Large session objects decrease the JVM memory available for creation and execution of application objects. As a result, performance can degrade as the decreased available heap memory leads to more frequent garbage collection.
Another factor is that the in-memory lifetime is always longer than the required usage lifetime, and thus the number of sessions occupying space in the Java heap usually is greater than the number of active users. A session expiration time is configurable in WebSphere Application Server and is indeed required to avoid a case when a user has to log in again after only a few seconds of inactivity. The release of a session is at the responsibility of WebSphere Application Server and the portlet container.
The serialized session size should be smaller than 4 KB because WebSphere Application Server can store such sessions with an acceptable database performance overhead, and it takes less time to transfer such sessions over the network. If the session size grows beyond 32 KB, the database must use table cells configured for binary large objects, which require physical disk access (for most supported databases) if such a session is retrieved or written to the database.
As a first consequence, the creation of sessions should be avoided wherever possible from an application point of view. On most public and unauthenticated pages, sessions are not usually required. Interacting with a portal on such a page is possible via so-called render links which, by definition, do not change the server side state. Render parameters are maintained by the portal for each portlet for all subsequent requests to that page. To avoid having a JSP create a session by default, the page session directive in the JSP should be set to false:
<@ page session="false"%>
Otherwise, this JSP will create a session if one does not exist.
The following Java code fragment shows how you can make sure that an incoming request joins an existing session, rather than unconditionally creating a new one:
With the parameter value of false, a session is not created if no session existed before. If a session did not exist before, it is probably not appropriate to create one in a portlet just for the purpose of storing data in it.
As a second consequence, the session should not be misused as an all-purpose data store mechanism. Remember that the goal is to keep the session size as small as possible. If keeping some data in memory is advantageous due to the design of a portlet, then a cache might be the right answer. Cache entries can be scoped with the session ID to keep a relationship between the session and the data that is to be kept in memory. Keep in mind that this kind of cache will not be cluster aware in case of a fail over; this is sometimes an acceptable trade-off. If the data is recreateable from other data available to the portlet, then the session scope requirement of cached entries is questionable.
In many cases, storing large objects in the session can be circumvented by just storing a key in the session and using this key as a reference to lookup a larger object in some other data structure. Another option would be to use a more compact representation of the same information and put that object into the session.
Furthermore, the portlet design needs to carefully consider what is actually stored in a session. The session is generally intended only for storing the conversational state of the user interaction with the portal application (for example, the contents of a shopping cart in a Web shop portlet). This kind of data is user specific and cannot be recreated by any other means. In WebSphere Portal, this type of data handling is called the session state.
If session state is not really required, there are other data storage options available for portlets:
During the action phase of a portlet, render parameters can be set for the portlet's subsequent render phase. Render parameters are used by a portlet to render its view specific to a specific set of values. Render parameters are maintained by the container from request to request, even if interaction occurs with another portlet. In WebSphere Portal, this type of data handling is called the navigational state.
The PortletPreferences API can be used for storing data for a portlet if such data will be kept across user sessions. Keep in mind that this API is not intended to replace general purpose databases. In WebSphere Portal, this data handling concept is called persistent state.
The PortletConfig API lets a portlet read its configuration, which is provided by the developer using the portlet deployment descriptor; this is valid for all users of the portlet.
The PortletContext API enables the storing of attributes that other portlets in the same application can also access.
Consider other choices than the session for storing data created and used by a portlet. Avoid replicating data into the session that can be recreated from sources other than through user interaction.
Render links and action links
There are advantages to using render parameters other than just to address a specific portlet view.
If an action parameter for a portlet is detected by WebSphere Portal, then special action phase handling must be invoked, making it advantageous to avoid using action parameters. However, be aware that processing render links must not change the server side state of a portlet. The only sanctioned way to change the server side state is to use action links -- and for a transactional type of request, action links are the best choice.
There are many instances where render links can be used instead of action links. For example, consider a newspaper portlet that can show specific pages with the use of Previous and Next buttons. Stepping through the newspaper pages does not necessarily change the server side state, which in this case is the entire information contained in the newspaper. To address the next page of the newspaper, it would be sufficient to encode the next page number into the render link for the shown button. The portlet can decide which page to render based on the page number given in a render parameter.
Also, using render links over action links enhances the chance of leveraging a cache infrastructure, be it a browser cache or a proxy cache, since each rendered view is addressed by a separate URL. The URL is the only key used to access a specific generated view in such a cache infrastructure.
Portlet features
The next sections discuss some of the portlet tuning features available with WebSphere Portal that should be considered by developers, and could influence the implementation technique chosen. Some required settings need to be provided with the portlet's deployment descriptor, and since these items are also supplied by a portlet developer, they are therefore considered custom code.
Enabling portlets for parallel rendering
WebSphere Portal offers the option to have portlets on a page rendered in parallel. This feature is not completely "for free" because computing resources are required to maintain and manage the different threads that are used to render each single portlet.
Parallel portlet rendering may be advantageous in cases where many backend systems are involved that each produce their own latency while rendering a single page. For example, consider a portal page that contains a number of portlets, each of which accesses a different backend system. In serial rendering mode, the overall latency for retrieving the required data from all the backend systems would have to be calculated as the sum of the individual latency times. In parallel rendering mode, the latency would be the maximum of all individual latency times.
If portlets do not use a backend system too often, the overhead for enabling parallel portlet rendering can become greater than the benefits gained from this feature. If portlets on a page can be rendered independently of a backend system, they only need CPU resources local to the portal server machine. In this case, the page render response time will not be improved.
Parallel portlet rendering can be enabled for each portlet separately with the graphical UI, or with the deployment descriptor, or with WebSphere Portal's XML access interface. On top of that, there is a global property value that generally turns parallel portlet rendering on and off.
To properly answer the question of whether or not to enable parallel portlet rendering for a portal, there are several things to consider; for example, the number of backend systems involved for rendering a page, typical page structure, the average number of portlets on a page that exploit parallel portlet rendering, and so on. Such questions may not necessarily be answerable in advance by a portlet developer, but certainly the developer can make sure that a portlet is enabled for parallel portlet rendering if that makes sense up front.
Caching in the portlet container
Portlet-based Web pages are aggregated dynamically because of their ability to deliver dynamic content in a personalized manner. This flexibility comes at a cost. Web site response time increases because of the additional work that has to be done to generate these pages upon request.
New caching technologies improve the performance of dynamic page generation and reduce system load. WebSphere Portal supports fragment caching (also known as servlet caching) using the WebSphere Application Server dynamic cache to keep portlet output in the cache. Requests for a cached portlet retrieve the content from the cache instead of the portlet. The invalidation of the fragment cache can be accomplished by specifying the expiration time in the deployment descriptor. Further, the fragment cache entries are invalidated during the action phase of the portlet.
There is no time-consuming installation and integration work needed to activate fragment caching. The cache is enabled and disabled using simple XML deployment descriptor files and using the WebSphere Application Server administrative console. (See the WebSphere Portal Information Center for details on enabling the servlet caching in WebSphere Application Server.)
To make use of expiration-based caching, portlets must define the duration of the expiration cache in the deployment descriptor portlet.xml (for standardized portlet following JSR 168 specification):
A positive number defines the number of seconds a cache entry exists in the cache.
A value of -1 indicates that the portlet cache never expires.
A value of 0 indicates that caching is disabled for the portlet.
The cached entries must not be shared across all users of the same portlet. This caching is per portlet per user.
For a JSR 168 portlet that has defined an expiration cache in its deployment descriptor, the portlet window can modify the expiration time at run time by setting the EXPIRATION_CACHE property in the RenderResponse, as follows:
renderResponse.setProperty( RenderResponse.EXPIRATION_CACHE, String.valueOf(numberCrunchingCalculation()) );
This approach will work for complex portlets that experience high computation time while calculating their response or request data from a backend, such as from EJB components or a database. In the case of simple portlets, fragment caching should not be enabled. WebSphere Portal uses extra execution resources to calculate the internal cache key for the fragment cache. Performance can regress for simple portlets because cache key calculation becomes more expensive than recalculating the portlet response again.
Fragment caching is not useful for portlets that are truly dynamic in nature; for example, real-time-based portlets that need to collect current data from other data sources on each request, or portlets that change their response markup on every request. This would result in a high number of cache invalidations and hence there would be no gain in performance. Therefore, the portlet should be enabled for caching only if the output of the portlet will be valid for some period of time before it is updated.
Caching in remote caches
With the unique adaptive page caching feature, WebSphere Portal offers the possibility of dynamically caching generated pages in caches external to a portal server (so-called remote caches), if all the page components indicate that they are cacheable. If completely rendered pages are served from remote caches, a roundtrip to the portal server can be avoided and response times for such pages can potentially be as fast as if they were served from static Web sites.
For more complete details on remote caching see the article Develop high performance Web sites with both static and dynamic content using WebSphere Portal V5.1.
Portlets (as well as themes) can contribute their specific remote cache information to the overall remote cache information for a completely rendered page. The remote cache information is a data structure consisting of the information about the cache scope (whether it is cacheable in a shared or non-shared cache) and the expiration time (how long the content is considered valid). The remote cache information of a portlet can be provided via the deployment descriptor or via the WebSphere Portal GUI. Beyond that, a portlet is also able to provide remote cache information at render time for each portlet window, as illustrated in the following code:
. . . import com.ibm.wps.util.RemoteCacheInfo; import javax.portlet.RenderResponse; . . . /* Do rendering */ public void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException { /* Some code might happen here */ . . . /* Publish a dynamic expiration time during rendering */ renderResponse.setProperty( RenderResponse.EXPIRATION_CACHE, String.valueOf(numberCrunchingCalculation()) ); /* Publish a cache scope value of "shared" during rendering */ renderResponse.setProperty( RemoteCacheInfo.KEY_SCOPE, RemoteCacheInfo.Scope.SHARED_STRING ); /* Some other code might happen here */ . . . }
How you set remote cache information depends on the "freshness" requirements and the scope of the rendered view. Keep in mind that if rendered pages are served from caches, the request might not even get to the portal server.
Custom portlet developers should consider exploiting remote caching if caching is available in the infrastructure.
Themes and skins
In portal terminology, themes are sets of JSPs that determine the look and feel of your portal application. Since themes are made of JSPs, the tips offered in the JSP section also apply here. This section details some possible performance pitfalls with the set of JSP files that get combined into a theme.
Typically, a theme consists of many different JSP files, each delivering the content for a certain area of the screen. While it is possible to dynamically include JSPs, it is common -- and generally recommended -- for JSPs to be statically included in other JSPs.
Since many JSPs might be included into others at compile time, the resulting Java source and servlet byte code files can potentially be very large. In general, there is no performance problem with having a large class file, but it is possible that compiling the JSP sources to a class can fail due to size restrictions incorporated in the Java programming language. For example, methods in Java cannot be larger than 64 KB. Large and complex themes can easily reach this limit and will then no longer compile. In this situation, you have three options:
Substitute dynamic includes for some (but not all) static ones.
As mentioned in the JSP section, this trades performance for being able to compile the JSPs at all. From a performance standpoint, this is the least preferred resolution, though it is the easiest to implement.
Try to restrict the usage of scriptlets in the JSPs.
WebSphere Application Server can apply optimizations to code that only calls tag handlers, which can help maintain the 64 KB limit.
Clean up your JSP code.
Very often these files contain more code than is actually necessary. Even removing HTML comment lines or white spaces, or moving JavaScript code into separate files can save sufficient space.
Themes sometimes take over complex tasks within the application. However, you need to be careful here. Remember that the theme will be rendered upon every single request to your portal, so do not introduce expensive computations that put a very high burden on the system.
Be especially careful with mimicking portal functionality. For example, themes could iterate over large numbers of pages in the portal application, and then filter these and only display a navigation structure to the user that includes just a few of the pages the theme requested from the portal APIs. In this case, much of the processing that happens inside the portal will be lost since the results are discarded afterwards. Filtering based on portal access control or personalization rules would be more efficient here.
Furthermore, try to limit the number of links to portal resources from your portal pages. Each URL that the portal has to generate puts additional load on the system. If you need application themes with huge numbers of links, try to cache the contents of some of these pages so that it is not necessary to recalculate all the links on every request.
Themes are also part of the remote caching infrastructure in WebSphere Portal. The remote cache information of a theme is a set of specifically named meta data that can be set via XML access, as shown in the following example:
<!-- Theme "shared" scope and 40 seconds cache expiration --> <theme action="update" active="true" objectid="xmplTheme" uniquename="wps.theme.example"> <parameter name="remote-cache-scope" type="string" update="set">SHARED</parameter> <parameter name="remote-cache-expiry" type="string" update="set">40</parameter> </theme>
A theme cannot provide any render time remote cache information.
WebSphere Portal supports the notion of high-performance skins. These skins are special insofar as they are not generated based on JSPs; their output is created from precompiled Java classes. Of course, this type of skin is less customizable; you can only modify the stylesheet information and included images. However, if performance is the most critical factor for you, you should think about enabling high-performance skins for certain elements on your page or for certain portlets. (See the Information Centers in Resources for more information, including various hints that can help you program high-speed skins and themes.)
Tools are available to assist you in all stages of WebSphere Portal application development and verification. This section describes different categories of tools you can use during different development cycles, and provides a few examples to help you get started with developing and analyzing your custom code.
Development environment
Technically, you can use any kind of text editor to write portlets, themes, and skins, but it's a lot easier using an integrated development environment, like IBM Rational® Application Developer together with the IBM Portal Toolkit. Portlet code samples and basic portal code fragments are also available to help you achieve your first results very fast; the development environment is integrated with a portal server so that you can immediately deploy and test your code.
Performance analysis tools
When your code is ready for deployment, you need to understand its performance implications in detail. There are several steps you can take, and they are summarized below, but there is one general rule that always applies to performance: In most programs, about 80% of the execution time is spent in 20% of the application code. This 20% of code is on the "critical path" and it is these areas that are worth optimizing for performance. For example, the render method of a portlet is much more performance-critical than its init method, since it is called upon in every request.
Code profiling should be done in the early stages of development, or as a first performance test after development. Profiling means that execution time information is collected at the method level, often using the JVMPI interface. Profiler results help you identify the critical path of your application; that is, the code that is executed most of the time. Profilers also often give information on object creation rates and memory consumption.
IBM Rational Application Developer comes with a profiling agent you can use to test your programs.
Eclipse Test and Performance Tools Platform is an Eclipse project that provides open-source profiling support based on Eclipse.
Once your portlet has been deployed into a portal, you should test for the behavior of the portlet under load. Stress or load generators, like Rational Performance Tester, Rational Robot, Apache JMeter (as a cost-effective alternative), and others, are load testing solutions to help you accurately simulate the system behavior under production load. These tools collect much information to help you determine whether your system is in good performance shape, including data on request response times, processor utilization, and more.
During load testing, you should monitor several performance parameters in your portal environment. IBM Tivoli® Performance Viewer (which is shipped with WebSphere Application Server) can be helpful to monitor resource utilization within the application server.
Many problems with portal environments are memory-related. JVM implementations provide two types of information for tools to analyze for performance:
- Output from the garbage collector, verbose:gc.
- Heap dumps, which are helpful when hunting for memory leaks.
Check out IBM alphaWorks for analysis tools for the garbage collector output. heapRoots, on the other hand, is a powerful heap dump analysis aid. The IBM Java Diagnostics Guides also provide helpful information for dealing with portal-related performance issues. See Resources for links to these references.
Very often you will not need this complete set of tools when developing code for WebSphere Portal, but for larger portal rollouts in your production environment it is essential to understand your portal code from a performance point of view.
When creating custom portal code, there are a number of areas that the developer must consider to ensure that portal performance is optimized. To summarize:
Focus on improving the critical code path. A critical code path is one that takes a long time to process or is very frequently executed. Find out which methods of which classes are on the critical path. Outside the critical path, optimizations are rather useless.
Consider both execution performance and memory allocation.
Use appropriate tools to measure and profile your code for the most typical user interactions.
Solutions to a coding problem may differ in orders of magnitude with respect to performance.
A specific implementation to solve a discovered performance problem must be understood in detail.
Consider the backend access pattern while designing your custom code.
Do not misuse the session as an all purpose data store for a portlet. There are better ways to handle data for various implementation requirements.
Consider exploiting the special features provided by WebSphere Application Server and WebSphere Portal to optimize portlet performance, provided the target environment is also exploiting the same feature(s).
- JSR 168: Portlet Specification
- Best practices: Developing portlets using JSR 168 and WebSphere Portal V5.02
- Meet the Experts: Marshall Lamb on WebSphere Portal Programming
- Portlet Development Best Practices and Coding Guidelines
- WebSphere Application Server Development Best Practices for Performance and Scalability
- IBM WebSphere Portal for Multiplatforms Version 5.0 Performance Tuning Guide
- WebSphere Application Server 5.1 Information Center
- WebSphere Business Integration Server Foundation 5.1 Information Center
- WebSphere Portal 5.1 Information Center
- Redbook: IBM WebSphere V5.1 Performance, Scalability, and High Availability WebSphere Handbook Series
- Redbook: WebSphere Application Server Enterprise V5 and Programming Model Extensions WebSphere Handbook Series
- Java Performance Tuning by Jack Shirazi, O'Reilly & Associates (2003), ISBN: 0596003773
- Java Performance and Scalability by Dov Bulka, Addison Wesley (2000), ISBN: 0201704293
- Java Platform Performance: Strategies & Tactics by Steve Wilson, Addison-Wesley (2000), ISBN: 0201709694
- Performance Analysis for Java Websites by Stacy Joines, Addison Wesley (2002), ISBN: 0201844540
- IBM Rational Application Developer
- Eclipse Test & Performance Tools Platform
- JVMPI documentation
- IBM Java Diagnostics Guides
- IBM WebSphere Developer Technical Journal: Develop high performance Web sites with both static and dynamic content using WebSphere Portal V5.1
Get products and technologies
- IBM Pattern Modeling and Analysis Tool for Java Garbage Collector
- Diagnostic Tool for Java Garbage Collector
- heapRoots
Dig deeper into WebSphere on developerWorks
- Overview
- New to WebSphere
- Technical library (tutorials and more)
- Forums
- Community
- Downloads
- Products
- Events
developerWorks Premium
Exclusive tools to build your next great app. Learn more.
dW Answers
Ask a technical question
Explore more technical topics
Tutorials & training to grow your development skills


text:
Boxing Forum - View Single Post - Could a Prime Antonio Margarito (05-09) beat a past prime Mayweather at 37 years old?
Could a Prime Antonio Margarito (05-09) beat a past prime Mayweather at 37 years old?
View Single Post
Join Date: Nov 2009
Posts: 2,936
Quoted: 0 Post(s)
Rep Power:
Points: 544,951.36
Bank: 0.00
Total Points: 544,951.36
I don't believe anyone genuinely thinks Tony would have beaten Mayweather then or now. But it would have been interesting to see how Mayweather would have dealt with an incredibly durable, supremely well-conditioned, relentless swarmer who had the will and determination that few others possessed.
Mayweather had just moved up to that weight class, was relatively small for it at that particular time and it was a pretty compelling fight around 2006-2008. Floyd potentially could have whitewashed him and pitched a shutout, or he potentially could have found himself in a difficult, competitive bout against a man who could have zero respect for his power and who was capable of setting the sort of pace that would unsettle the smaller, economical counter-puncher and favour the bigger, perhaps stronger, high-volume punching pressure fighter.
I'm not saying it would happen for certain, but Floyd wouldn't be the first outstanding talent to face adversity with regards to a fighter who's will is every bit as strong as his opponents considerable skill.
Quick reply to this message
View Public Profile
Send a private message to prinzemanspopa
Find More Posts by prinzemanspopa


text:
Expanding Use of NGS Has Largely...
LC-MS Gains Favor Due To the...
Wall Street Decline Takes Its Toll...
Quadruple Helices Appear To Have Role...
Eureka Genomics is developing a custom assay for the genotyping of barley, enabling identification of over 400 single nucleotide polymorphisms (SNP) in a single test. The assay will offer a low-cost opportunity for researchers to identify and optimize traits such as yield, quality, and environmental resilience for commercial crop production.
"As the Eureka technology offers the flexibility to increase both the number of SNPs and samples per assay at low additional cost, we are already focused on improving SNP representation and multiplex capability, further reducing the cost per datapoint, a key requirement for widespread adoption in commercial plant breeding," said Robbie Waugh, head of genetics at the James Hutton Institute.
The marker assay (LDMA) being offered by Eureka Genomics provides an alternative to traditional technologies for profiling hundreds of SNPs (or other genetic markers) in thousands of samples using next generation sequencing. According to the company, the assay can be broadly applied to the detection of SNPs, CNV, presence/absence, and methylation and is compatible with DNA or RNA from virtually any organism, even when genome information may be incomplete.
"The LDMA lets researchers design profiling panels that target the markers that matter most for their project, rather than wasting time and resources getting data that is irrelevant to their goals," said Andrea White, director of business development for Eureka Genomics."
Barley is the world's fourth most important cereal and has worldwide economic value for brewing and whisky-distilling industries, animal feed, and potential for improving human health. By developing the barley panel in conjunction with the James Hutton Institute based in Scotland, Eureka Genomics will be able to introduce the assay both in Europe and in the U.S. next month.
To save this item to your Favorites,
log into GEN Select.
We'll be sure to take you back here after you do.
Not a member of GEN Select?
To comment on this article,
log into GEN Select.
We'll be sure to take you back here after you do.
Join 110,000 colleagues who rely on GEN Highlights for breaking news and exclusive articles shaping today's life science tools and technologies.
You're all set! Thank you for subscribing to GEN Highlights.
While Zika continues to garner a lot of news coverage, a Mayo Clinic survey reveals that Americans believe the country's most significant healthcare challenge is cancer. Compared to other diseases, does the possibility of developing cancer worry you the most?
Be sure to add [email protected]
to your Address Book or Safe Senders List.
here for instructions.
If you have any questions about your subscription, click
here to email us or call at (914) 740-2189.
You may also be interested in subscribing to the GEN magazine, an indispensable
resource for everyone involved in the business of translating discoveries at the
bench into solutions that fight disease and improve health, agriculture, and the
environment. Subscribe
today to see why over 60,000 biotech professionals read GEN to
keep current in the areas of genomics, proteomics, drug discovery, biomarker discovery,
bioprocessing, molecular diagnostics, collaborations, biotech business trends, and
© 2016 Genetic Engineering & Biotechnology News All Rights Reserved