Enter any website URL to analyze its complete technology stack

Executive Summary for www.learnopengles.com

930 Response Time (ms)
200 HTTP Status
21 Scripts
16 Images
16 Links
HTTP/1.1 Protocol

SEO & Content Analysis

Basic Information
Page Title
Learn OpenGL ES
Meta Description
Learn OpenGL ES for Android, WebGL for the web, and more.
HTML Language
en-US
Robots.txt Present
Sitemap Present
total_urls: 56
SEO Meta Tags
content-type: text/html; charset=UTF-8
Page Content

Learn OpenGL ES

In my previous post on this topic, A performance comparison between Java and C on the Nexus 5, I compared the performance of an audio low-pass filter in Java and C. The results were clear: The C version outperformed, and by a significant amount. This result brought more attention to the post than I was expecting; some of you were also curious about RenderScript, and I’m pleased to say that Jean-Luc Brouillet, a member of Google’s RenderScript team, got in touch with me and generously volunteered an implementation of the DSP code in RenderScript.With this new code, I refactored the code into a new benchmark with test audio data, so that I could compare the different implementations and verify their output. I’ll be sharing both the code and the results with you today.Motivations and intentionsSome of you might be curious about why I am so interested in this subject. 🙂 I normally spend most of my development hours coding for Android, using Java; in fact, my first book, OpenGL ES 2 for Android: A Quick-Start Guide, is a beginner’s guide to OpenGL that focuses on Android and Java.Normally, when I develop code, the most important questions on my mind are: “Is this easy to maintain?” “Is it correct?” “If I come back and revisit this code a month later, am I going to understand what the heck I was doing?” Since Java is the primary development language on Android, it just makes sense for me to do most of my development there.So why the recent focus on native development? Here are two big reasons:The performance of Java on Android isn’t suitable for everything. For critical performance paths, it can be a big competitive advantage to move that code over to native, so that it completes in less time and uses less battery.I’m interested in branching out to other platforms down the road, probably starting with iOS, and I’m curious if it makes sense to share some code between iOS and Android using a common code base in C/C++. It’s important that this code runs without many abstractions in the way, so I’m not very interested in custom/proprietary solutions like Xamarin’s C# or an HTML5-based toolkit.It’s starting to become clear to me that it can make sense to work with more than one language, and to choose these languages in situations where the benefits outweigh the cost. Trying to work with Android’s UI toolkit from C++ is painful; running a DSP filter from Java and watching it use more battery and take more time than it needs to is just as painful.Our new test scenarioFor this round of benchmarks, we’ll be comparing several different implementations of a low-pass IIR filter, implemented with coefficients generated with mkfilter. We’ll run a test audio file through each implementation, and record the best score for each.How does the test work?First, we load a test audio file into memory.We then execute the DSP algorithm over the test audio, benchmarking the elapsed time. The data is processed in chunks to reflect the fact that this is similar to how we would process data coming off of the microphone.The results are written to a new audio file in the device’s default storage, under “PerformanceTest/”.Here are our test implementations:Java. This is a straightforward implementation of the algorithm.Java (tuned). This is the same as 1, but with all of the functions manually inlined.C. This uses the Java Native Interface (JNI) to pass the data back and forth.RenderScript. A big thank you to Mr. Brouillet from the RenderScript team for taking the time to contribute this!The tests were run on a Nexus 5 device running Android 4.4.3. Here are the results:ResultsImplementationExecution environmentCompilerShorts/secondRelative run time(lower is better)CDalvik JNIgcc 4.617,639,0811.00CDalvik JNIgcc 4.816,516,7571.07RenderScriptDalvikRenderScript (API 19)15,206,4951.16RenderScriptDalvikRenderScript (API 18)13,234,3971.33CDalvik JNIclang 3.413,208,4081.34Java (tuned)Art (Proguard)7,235,6072.44Java (tuned)Art7,097,3632.49Java (tuned)Dalvik5,678,9903.11Java (tuned)Dalvik (Proguard)5,365,8143.29JavaArt (Proguard)3,512,4265.02JavaArt3,049,9865.78JavaDalvik (Proguard)1,220,60014.45JavaDalvik1,083,01516.29For this test, the C implementation is the king of the hill, with gcc 4.6 giving the best performance. The gcc compiler is followed by RenderScript and clang 3.4, and the two Java implementations are at the back of the pack, with Dalvik giving the worst performance.CThe C implementation compiled with gcc gave the best performance out of the entire group. All tests were done with -ffast-math and -O3, using the NDK r9d. Switching between Dalvik and ART had no impact on the C run times.I’m not sure why there is still a large gap between clang and gcc; would everything on iOS run that much faster if Apple was using gcc?  Clang will likely continue to improve and I hope to see this gap closed in the future. I’m also curious about why gcc 4.6 seems to generate better code than 4.8. Perhaps someone familiar with ARM assembly and the compilers would be able to weigh in why?Even though I’m a newbie at C and I learned about JNI in part by doing these benchmarks, I didn’t find the code overly difficult to write. There’s enough documentation out there that I was able to figure things out, and the algorithm output matches that of the other implementations; however, since C is an unsafe language, I’m not entirely convinced that I haven’t stumbled into undefined behaviour or otherwise done something insane. 🙂RenderScriptIn the previous post, someone asked about RenderScript, so I started working on an implementation. Unfortunately, I had zero experience with RenderScript at the time so I wasn’t able to get it working. Luckily, Jean-Luc Brouillet from the RenderScript team also saw the post and ported over the algorithm for me!As you can see, the results are very promising: RenderScript offers better performance than clang and almost the same performance as gcc, without requiring use of the NDK or of JNI glue! As with C, switching between Dalvik and ART had no impact on the run times.RenderScript also offers the possibility to easily parallelize the code and/or run it on the GPU which can potentially give a huge speedup, though unfortunately we weren’t able to take advantage of that here since this particular DSP algorithm is not trivially parallelizable. However, for other algorithms like a simple gain, RenderScript can give a significant boost with small changes to the code, and without having to worry about threading or other such headaches.In my humble view, the RenderScript implementation does need some more polishing and the documentation needs to be significantly improved, as I doubt I would have gotten it working on my own without help. Here are some of the issues that I ran into with the RenderScript port:Not all functions are documented. For example, the algorithm uses rsSetElementAt_short() which I can’t find anywhere except for some obscure C files in the Android source code.The allocation functions are missing a way to copy data into an offset of an array. To work around this, I use a scratch buffer and System.arraycopy() to move the data around, and to keep things fair, I changed the other implementations to work in the same way. While this slows them down slightly, I don’t believe it’s an unfair advantage for RenderScript, because in real-world usage, I would expect to process the data coming off the microphone and write that directly into a file, not into an offset of some array.The fastest RenderScript implementation only works on Android 4.4 KitKat devices. Going down one version to Android 4.3 changes the RenderScript API which requires me to change the code slightly, slowing things down for both 4.3 and 4.4. RenderScript does offer a “support” mode via the support API which should enable backwards compatibility, but I wasn’t able to get this to work for me for APIs older than 18 (Android 4.3).So while there are some issues with RenderScript as implemented today, these are all issues that can hopefully be fixed. RenderScript also has the significant advantage of running code on the CPU and GPU in parallel, and doesn’t require JNI glue code. This makes it a serious contender to C, especially if portability to older devices or other platforms is not a big concern.JavaAs with last time, Java fills out the bottom of the pack. The performance is especially terrible with the default Dalvik implementation; in fact, it would be even worse if I hadn’t manually replaced the modulo operator with a bit mask, which I was hoping the compiler could do with the static information available to it, but it doesn’t.Some people asked about Proguard, so I tried it out with the following config (full details in the test project):-optimizationpasses 5-allowaccessmodification-dontpreverify-dontusemixedcaseclassnames-dontskipnonpubliclibraryclasses-verboseThe results were mixed. Switching between Dalvik and ART made much more of a difference, as did manually inlining all of the functions together. The best result with Dalvik was without Proguard, and was 3.11x slower than the best C implementation. The best result with ART was with Proguard, and was 2.44x slower than the best C implementation. If we compare the normal Java version to the best C result, we get a 5.02x slowdown with ART and a 14.45x slowdown with Dalvik.It does look like the performance of Java will be getting a lot better once ART becomes widely deployed; instead of huge slowdowns, we’ll be seeing between 3x and 5x, which does make a difference. I can already see the improvements when sorting and displaying ListViews in UI code, so this isn’t just something that affects niche code like audio DSP filters.Desktop results (just for fun)Just like last time, again, here are some desktop results, just for fun. 🙂 These tests were run on a 2.6 GHz Intel Core i7 running OS X 10.9.3.ImplementationExecution environmentCompilerShorts/secondRelative speed(higher is better)CJava SE 1.6u65 JNIgcc 4.9129,909,6627.36CJava SE 1.6u65 JNIclang 3.496,022,6445.44JavaJava SE 1.8u5 (+XX:AggressiveOpts)82,988,3324.70Java (tuned)Java SE 1.8u5 (+XX:AggressiveOpts)79,288,0254.50JavaJava SE 1.8u564,964,3993.68Java (tuned)Java SE 1.8u564,748,2013.67Java (tuned)Java SE 1.6u6563,965,5753.63JavaJava SE 1.6u6553,245,8643.02As on the Nexus 5, the C implementation compiled with gcc dominates; however, I’m very impressed with where Java ended up!CI used the following compilers with optimization flags -march=native -ffast-math -O3:Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)gcc version 4.9.0 20140416 (prerelease) (MacPorts gcc49 4.9-20140416_2)As on the Nexus 5, gcc’s generated code is much faster than clang’s; perhaps this will change in the future but for now, gcc is still the king. I also find it interesting that the gap between the best run time here and the best run time on the Nexus 5 is similar to the gap between C and ART on the Nexus 5. Not so far apart, they are!JavaI’m also impressed with the latest Java for OS X. While manually inlining all of the functions together was required for an improvement on Java 1.6, the manually-inlined version was actually slower on Java 1.8. This shows that not only is this sort of code abuse no longer required on the latest Java, but also that the compiler is smarter than we are at optimizing the code.Adding +XX:AggressiveOpts to Java 1.8 sped things up even more, almost closing the gap with clang! That is very impressive in my eyes, since Java has an old reputation of being a slow language, but in some cases and situations, it can be almost as fast as C if not faster.The worst Java performance is 2.43x slower than the best C performance, which is about the same relative difference as the best Java performance on Android with ART. Performance differences aren’t always just about language choice; they can also be very dependent on the quality of implementation. At this time, the Google team has made different trade-offs which place ART at around the same relative level of performance, for this specific test case, as Java 1.6. The improved performance of Java 1.8 on the desktop shows that it’s clearly possible to close up the gap on Android in the future.Explore the code!The project can be downloaded at GitHub: https://github.com/learnopengles/dsp-perf-test. To compile the code, download or clone the repository and import the projects into Eclipse with File->Import->Existing Projects Into Workspace. If the Android project is missing references, go to its properties, Java Build Path, Projects, and add “JavaPerformanceTest”.The results are written to “PerformanceTest/” on the device’s default storage, so please double-check that you don’t have anything there before running the tests.So, what do you think? Does it make sense to drop down into native code? Or are native languages a relic of the past, and there’s no reason to use anything other than modern, safe languages? I would love to hear your feedback.;

Network & Infrastructure

DNS & Hosting
IP Address
198.72.126.225
Reverse DNS
mtl201.greengeeks.net
SSL/TLS Certificate
Issuer
CN=R13, O=Let's Encrypt, C=US
Protocol Tls13
Expires In 35 days
HSTS Enabled

Technology Stack

Content Management Systems
WordPress
JavaScript Frameworks
jQuery
Server Technologies
Generator: WordPress 5.8.12 PHP (inferred from WordPress)

Services & Integrations

Analytics & Tracking
Google Analytics GA4
Advertising & Marketing
Amazon Ads
E-commerce Platforms
PrestaShop

CDN & Media Providers

Web Fonts
Google Fonts

Dynamic Analysis & Security

Dynamic JavaScript Analysis
Angular (Data Attributes) Bootstrap (CSS Classes) ES6+ JavaScript Features jQuery (CDN Detection) jQuery (script Resource)
Security Headers
HSTS X-Content-Type-Options X-Frame-Options

Resource Analysis

External Resource Hosts
fonts.googleapis.com
gmpg.org
ir-na.amazon-adsystem.com
pragprog.com
s.w.org
secure.gravatar.com
static.addtoany.com
www.learnopengles.com
UI Frameworks & Libraries
Angular Material (Class Names) Bootstrap (Class Names) D3.js Ionic (Class Names) Slate Vuetify (Class Names)
Analysis Complete

Analyzed www.learnopengles.com with 4 technologies detected across 7 categories

Analysis completed in 930 ms • 2026-03-23 07:44:18 UTC