[libgens] CrazyEffect: Improve performance on systems where RAND_MAX >= 0x3FFFFFFF.
authorDavid Korth <gerbilsoft@gerbilsoft.com>
Wed, 2 Sep 2015 06:26:13 +0000 (02:26 -0400)
committerDavid Korth <gerbilsoft@gerbilsoft.com>
Wed, 2 Sep 2015 06:26:13 +0000 (02:26 -0400)
glibc's RAND_MAX is 0x7FFFFFFF. We can cache the high bits as a second
random number in order to cut the number of rand() calls in half.

This increases performance on my system from around ~45-50 fps to
~56-60 fps in both the debug and release builds. There's no difference
between the two, so I suspect that rand() is the main bottleneck.

TODO: Use a faster rand() implementation, e.g. Mersenne Twister?

src/libgens/Effects/CrazyEffect.cpp
src/libgens/Effects/CrazyEffect.hpp

index 332da1b..4c4fb3c 100644 (file)
@@ -37,12 +37,49 @@ namespace LibGens {
 
 // TODO: Private class.
 
+/**
+ * Get a random number in the range [0,0x7FFF].
+ * This uses the internal random number
+ * cache if it's available.
+ * @return Random number.
+ */
+unsigned int CrazyEffect::getRand(void)
+{
+       // TODO: Faster rand() implementation, e.g. Mersenne Twister?
+       unsigned int ret;
+#if RAND_MAX >= 0x3FFFFFFF
+       if (rand_cache <= 0x7FFF) {
+               // rand_cache is valid.
+               ret = rand_cache;
+               rand_cache = ~0;
+               return ret;
+       }
+#endif
+
+       // Get a random number.
+       ret = rand();
+#if RAND_MAX >= 0x3FFFFFFF
+       // Cache the high bits as a second random number.
+       rand_cache = (ret >> 15) & 0x7FFF;
+       ret &= 0x7FFF;
+#endif
+       return ret;
+}
+
+/**
+ * Adjust a pixel's color.
+ * @param pixel     [in] Type of pixel.
+ * @param add_shift [in] Shift value for the add value.
+ * @param px        [in] Pixel data.
+ * @param mask      [in] Pixel mask.
+ * @return Adjusted pixel color.
+ */
 template<typename pixel, uint8_t add_shift>
-static inline pixel adj_color(pixel px, pixel mask)
+inline pixel CrazyEffect::adj_color(pixel px, pixel mask)
 {
        pixel add = 1 << add_shift;
        px &= mask;
-       if ((rand() & 0x7FFF) > 0x2C00) {
+       if ((getRand() & 0x7FFF) > 0x2C00) {
                if ((mask - add) <= px) {
                        px = mask;
                } else {
@@ -124,6 +161,9 @@ inline void CrazyEffect::T_doCrazyEffect(pixel *outScreen)
 
 CrazyEffect::CrazyEffect()
        : m_colorMask(CM_WHITE)
+#if RAND_MAX >= 0x3FFFFFFF
+       , rand_cache(~0)
+#endif
 { }
 
 /**
index ceb0483..797806f 100644 (file)
 #ifndef __LIBGENS_EFFECTS_CRAZYEFFECT_HPP__
 #define __LIBGENS_EFFECTS_CRAZYEFFECT_HPP__
 
-#include <stdint.h>
 #include "../macros/common.h"
 
+// C includes.
+#include <stdint.h>
+#include <stdlib.h>
+
 namespace LibGens {
 
 class MdFb;
@@ -71,6 +74,35 @@ class CrazyEffect
 
                // Color mask.
                ColorMask m_colorMask;
+
+               // TODO: Move this stuff to a private class.
+
+               /**
+                * Get a random number in the range [0,0x7FFF].
+                * This uses the internal random number
+                * cache if it's available.
+                * @return Random number.
+                */
+               unsigned int getRand(void);
+
+               /**
+                * Adjust a pixel's color.
+                * @param pixel     [in] Type of pixel.
+                * @param add_shift [in] Shift value for the add value.
+                * @param px        [in] Pixel data.
+                * @param mask      [in] Pixel mask.
+                * @return Adjusted pixel color.
+                */
+               template<typename pixel, uint8_t add_shift>
+               inline pixel adj_color(pixel px, pixel mask);
+
+#if RAND_MAX >= 0x3FFFFFFF
+               // Random number cache.
+               // glibc's RAND_MAX is 0x7FFFFFFF, so we can
+               // get two random numbers from [0,0x7FFF]
+               // with a single call to rand().
+               unsigned int rand_cache;
+#endif
 };
 
 inline CrazyEffect::ColorMask CrazyEffect::colorMask(void) const