Browse Source

Info and examples for the hashing component.

Frederic G. MARAND 6 years ago
parent
commit
3fa864e013
6 changed files with 471 additions and 87 deletions
  1. 125 78
      .idea/workspace.xml
  2. 9 4
      docs/README.md
  3. 61 0
      docs/hash.md
  4. 134 5
      docs/protocol.yml
  5. 112 0
      third/bloom/jenkins.go
  6. 30 0
      third/bloom/jenkins_test.go

+ 125 - 78
.idea/workspace.xml

@@ -2,11 +2,12 @@
 <project version="4">
   <component name="ChangeListManager">
     <list default="true" id="36eaad7a-0726-4217-b7e5-1b2c680697a1" name="Default" comment="">
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/.idea/runConfigurations/go_run_main_go.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/main.go" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/libraries/GOPATH__gache_.xml" afterPath="$PROJECT_DIR$/.idea/libraries/GOPATH__gache_.xml" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/misc.xml" afterPath="$PROJECT_DIR$/.idea/misc.xml" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/docs/hash.md" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/third/bloom/jenkins.go" />
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/third/bloom/jenkins_test.go" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
+      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/README.md" afterPath="$PROJECT_DIR$/docs/README.md" />
+      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/docs/protocol.yml" afterPath="$PROJECT_DIR$/docs/protocol.yml" />
     </list>
     <ignored path="gache.iws" />
     <ignored path=".idea/workspace.xml" />
@@ -25,28 +26,7 @@
     <favorites_list name="gache" />
   </component>
   <component name="FileEditorManager">
-    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
-      <file leaf-file-name="protocol.yml" pinned="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/docs/protocol.yml">
-          <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="655">
-              <caret line="159" column="55" selection-start-line="159" selection-start-column="55" selection-end-line="159" selection-end-column="55" />
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="main.go" pinned="false" current-in-tab="true">
-        <entry file="file://$PROJECT_DIR$/main.go">
-          <provider selected="true" editor-type-id="text-editor">
-            <state relative-caret-position="405">
-              <caret line="28" column="47" selection-start-line="28" selection-start-column="47" selection-end-line="28" selection-end-column="47" />
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-    </leaf>
+    <leaf />
   </component>
   <component name="FileTemplateManagerImpl">
     <option name="RECENT_TEMPLATES">
@@ -73,10 +53,15 @@
         <option value="$PROJECT_DIR$/docs/components.md" />
         <option value="$PROJECT_DIR$/docs/readline.md" />
         <option value="$PROJECT_DIR$/docs/runner_cli.md" />
-        <option value="$PROJECT_DIR$/docs/README.md" />
         <option value="$PROJECT_DIR$/docs/runner_config.md" />
-        <option value="$PROJECT_DIR$/docs/protocol.yml" />
         <option value="$PROJECT_DIR$/main.go" />
+        <option value="$PROJECT_DIR$/docs/protocol.yml" />
+        <option value="$PROJECT_DIR$/docs/README.md" />
+        <option value="$PROJECT_DIR$/third.go" />
+        <option value="$PROJECT_DIR$/third/jenkins.go" />
+        <option value="$PROJECT_DIR$/third/bloom/v1.go" />
+        <option value="$PROJECT_DIR$/third/bloom/jenkins.go" />
+        <option value="$PROJECT_DIR$/docs/hash.md" />
       </list>
     </option>
   </component>
@@ -142,41 +127,6 @@
       <pane id="AndroidView">
         <subPane />
       </pane>
-      <pane id="ProjectPane">
-        <subPane>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="gache" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="gache" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="gache" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="gache" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="gache" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="docs" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-        </subPane>
-      </pane>
-      <pane id="PackagesPane" />
       <pane id="Scope">
         <subPane subId="Project Files">
           <PATH>
@@ -191,6 +141,17 @@
           </PATH>
         </subPane>
       </pane>
+      <pane id="ProjectPane">
+        <subPane>
+          <PATH>
+            <PATH_ELEMENT>
+              <option name="myItemId" value="gache" />
+              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+            </PATH_ELEMENT>
+          </PATH>
+        </subPane>
+      </pane>
+      <pane id="PackagesPane" />
     </panes>
   </component>
   <component name="PropertiesComponent">
@@ -202,7 +163,7 @@
     <property name="MemberChooser.copyJavadoc" value="false" />
     <property name="settings.editor.selected.configurable" value="com.goide.configuration.GoConfigurableProvider$GoProjectSettingsConfigurable" />
     <property name="settings.editor.splitter.proportion" value="0.2" />
-    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$/../../../../../Memcached/memcached/doc/protocol.txt" />
     <property name="android.project.structure.last.selected" value="SDK Location" />
     <property name="android.project.structure.proportion" value="0.15" />
     <property name="configurable.Global.libraries.is.expanded" value="true" />
@@ -214,10 +175,11 @@
     <property name="DefaultGoTemplateProperty" value="Go Application" />
   </component>
   <component name="RecentsManager">
-    <key name="CopyFile.RECENT_KEYS">
+    <key name="MoveFile.RECENT_KEYS">
+      <recent name="$PROJECT_DIR$/third/bloom" />
       <recent name="$PROJECT_DIR$/docs" />
     </key>
-    <key name="MoveFile.RECENT_KEYS">
+    <key name="CopyFile.RECENT_KEYS">
       <recent name="$PROJECT_DIR$/docs" />
     </key>
   </component>
@@ -563,17 +525,17 @@
   </component>
   <component name="ToolWindowManager">
     <frame x="0" y="23" width="1676" height="1027" extended-state="6" />
-    <editor active="true" />
+    <editor active="false" />
     <layout>
       <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
       <window_info id="Image Layers" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
       <window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
       <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32939914" sideWeight="0.5" order="0" side_tool="true" content_ui="tabs" />
+      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32832617" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
       <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
-      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.32832617" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
       <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
-      <window_info id="Project" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2702864" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
+      <window_info id="Project" active="true" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.2702864" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
       <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.13902149" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
       <window_info id="Theme Preview" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
@@ -751,11 +713,65 @@
         </state>
       </provider>
     </entry>
+    <entry file="file://$PROJECT_DIR$/main.go">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="525">
+          <caret line="36" column="1" selection-start-line="36" selection-start-column="1" selection-end-line="36" selection-end-column="1" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../../../../../Memcached/memcached/doc/threads.txt">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="0">
+          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../../../../../Memcached/memcached/doc/readme.txt">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="0">
+          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../../../../../Memcached/memcached/doc/protocol-binary-range.xml">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="-540">
+          <caret line="12" column="0" selection-start-line="12" selection-start-column="0" selection-end-line="12" selection-end-column="0" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../../../../../Memcached/memcached/doc/protocol-binary.xml">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="-1575">
+          <caret line="0" column="0" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../../../../../Memcached/memcached/doc/protocol.txt">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="874">
+          <caret line="784" column="0" selection-start-line="784" selection-start-column="0" selection-end-line="784" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/docs/protocol.yml">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="850">
+          <caret line="297" column="3" selection-start-line="297" selection-start-column="3" selection-end-line="297" selection-end-column="3" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
     <entry file="file://$PROJECT_DIR$/docs/README.md">
       <provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
         <state split_layout="SPLIT">
-          <first_editor relative-caret-position="369">
-            <caret line="26" column="46" selection-start-line="26" selection-start-column="46" selection-end-line="26" selection-end-column="46" />
+          <first_editor relative-caret-position="324">
+            <caret line="23" column="0" selection-start-line="23" selection-start-column="0" selection-end-line="23" selection-end-column="0" />
+            <folding />
           </first_editor>
           <second_editor>
             <js_state />
@@ -765,28 +781,59 @@
       <provider editor-type-id="split-provider[text-editor;markdown-preview-editor]">
         <state split_layout="FIRST">
           <first_editor relative-caret-position="750">
-            <caret line="50" column="2" selection-start-line="50" selection-start-column="2" selection-end-line="50" selection-end-column="2" />
+            <caret line="51" column="2" selection-start-line="51" selection-start-column="2" selection-end-line="51" selection-end-column="2" />
+            <folding />
           </first_editor>
           <second_editor />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/docs/protocol.yml">
+    <entry file="file://$PROJECT_DIR$/third.go">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="655">
-          <caret line="159" column="55" selection-start-line="159" selection-start-column="55" selection-end-line="159" selection-end-column="55" />
+        <state relative-caret-position="0">
+          <caret line="0" column="12" selection-start-line="0" selection-start-column="12" selection-end-line="0" selection-end-column="12" />
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/main.go">
+    <entry file="file://$PROJECT_DIR$/third/bloom/jenkins.go">
       <provider selected="true" editor-type-id="text-editor">
-        <state relative-caret-position="405">
-          <caret line="28" column="47" selection-start-line="28" selection-start-column="47" selection-end-line="28" selection-end-column="47" />
+        <state relative-caret-position="315">
+          <caret line="21" column="22" selection-start-line="21" selection-start-column="22" selection-end-line="21" selection-end-column="22" />
           <folding />
         </state>
       </provider>
     </entry>
+    <entry file="file://$PROJECT_DIR$/third/bloom/jenkins_test.go">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="450">
+          <caret line="30" column="0" selection-start-line="30" selection-start-column="0" selection-end-line="30" selection-end-column="0" />
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/docs/hash.md">
+      <provider selected="true" editor-type-id="split-provider[text-editor;MarkdownPreviewEditor]">
+        <state split_layout="SPLIT">
+          <first_editor relative-caret-position="660">
+            <caret line="44" column="101" selection-start-line="44" selection-start-column="101" selection-end-line="44" selection-end-column="101" />
+            <folding />
+          </first_editor>
+          <second_editor>
+            <js_state />
+          </second_editor>
+        </state>
+      </provider>
+      <provider editor-type-id="split-provider[text-editor;markdown-preview-editor]">
+        <state split_layout="SPLIT">
+          <first_editor relative-caret-position="165">
+            <caret line="11" column="0" selection-start-line="11" selection-start-column="0" selection-end-line="11" selection-end-column="0" />
+            <folding />
+          </first_editor>
+          <second_editor />
+        </state>
+      </provider>
+    </entry>
   </component>
   <component name="masterDetails">
     <states>

+ 9 - 4
docs/README.md

@@ -5,10 +5,10 @@
 Like Memcached, plus...
 
 * Usability:
-  * True FLUSHALL
+  * True FLUSHALL equivalent to an instance restart
   * Single process for multiple bins
 * Management
-  * Complete locking dump/restore
+  * Complete locking dump/restore (compare cachedump` / `lru_crawler metadump all`)
   * Snapshots
 * Tag support
 * Pluggable storage
@@ -16,7 +16,7 @@ Like Memcached, plus...
   * Write-back/write-through replication
   * Chained storage (fast → slow)
 
-But probably slower overall, but more convenient.
+Likely to be slower overall, but more convenient.
 
 ## Components
 
@@ -36,6 +36,7 @@ But probably slower overall, but more convenient.
   * [Event handling](event_handling.md)
 * [Readline equivalence](readline.md) for ASCII presentation interactions
 * Storage
+  * [Hash logic](hash.md) for keys
   * Pluggable storage
     * Journaling
   * Storage engines
@@ -46,7 +47,11 @@ But probably slower overall, but more convenient.
       * Main memory allocation
       * Slab allocator
   * Reporting
-  * Background expiration lurker
+  * Background expiration lurker (cf standard `lru_crawler`)
 
 ### Client library
 
+### Testing tools
+
+* memslap, from libmemcached
+  * On MBP2016, memcached 1.5.0 makes 25kqps on the set test, 

+ 61 - 0
docs/hash.md

@@ -0,0 +1,61 @@
+# Hash logic
+
+Keys are hashed. 
+
+## Memcached hashes
+
+Memcached itself uses either:
+
+* [Jenkins hash](https://en.wikipedia.org/wiki/Jenkins_hash_function)
+  * http://burtleburtle.net/bob/hash/doobs.html
+  * http://burtleburtle.net/bob/c/lookup3.c Public domain.
+* [Murmur 3 hash](https://en.wikipedia.org/wiki/MurmurHash)
+  * [Murmur 3 in Go](https://github.com/spaolacci/murmur3)
+  
+## Golang
+
+Beyond the Go ports of these hashes, Go includes native alternatives: 
+
+* Jenkins hash
+  * https://github.com/mtchavez/jenkins MIT license.
+  * https://github.com/tsaost/bjh port of lookup3.c. BSD license.
+  * https://github.com/Apsalar/lookup3 hashlittle() from lookup3.c. Optimized for compatibility/portability,
+    not for performance. Implements `hash.Hash32`. Public domain.
+  * https://github.com/MstrVLT/lookup3/ port of lookup3.c. License undefined.
+* Murmur 3:
+  * https://github.com/reusee/mmh3 MIT license.
+  * https://github.com/huichen/murmur APL 2.0 license.
+  * https://github.com/go-ego/murmur APL 2.0 license. Based on huichen's version.
+  * https://github.com/beevik/murmur License undefined.
+  * https://github.com/ericx10ng/murmurhash2-go License undefined: was MIT but got removed.
+* xxhash:
+  * https://github.com/vova616/xxhash/blob/master/xxhash.go (not ARM-compatible). MIT license.
+* Golang standard library hashes:
+  * hash/adler32
+    * https://golang.org/pkg/hash/adler32/
+  * hash/crc32
+    * https://golang.org/pkg/hash/crc32/
+    * The Castagnoli polynomial may be hardware-accelerated on post-Nehalem CPUs compiled with 6g
+        (https://stackoverflow.com/questions/23436358/bob-jenkins-hash-getting-bad-performance)
+  * hash/crc64:
+    * https://golang.org/pkg/hash/crc64/
+  * hash/fnv:
+    * https://golang.org/pkg/hash/fnv/
+* Golang [crypto](https://golang.org/pkg/crypto/#pkg-subdirectories) package includes many 
+  cryptographic hashed with optimized implementations too. Most interesting are probably MD5 and SHA1
+  * AES (Rijndael), 
+  * Cipher package provides bloc cipher modes around low-level ciphers, no specific hashes.
+  * DES (DIPS 46-3)
+  * DSA (FIPS 186-3)
+  * ECDSA (FIPS 186-3)
+  * Elliptic package doesn't directly apply
+  * HMAC
+  * MD5 (RFC 1321)
+  * rand package doesn't directly apply
+  * RC4, RSA provide encryption, don't directly apply
+  * SHA1 (RFC 3174). Reported to be as fast as a Jenkins hash, but may not has optimal distribution
+    properties
+  * SHA-256, SHA-384, SHA512, SHA512-224, SHA-512/256 (FIPC 180-4)
+  * subtle package doesn't directly apply
+  * TLS 1.2, doesn't directly apply
+  * X.509, doesn't directly apply

+ 134 - 5
docs/protocol.yml

@@ -122,13 +122,30 @@ other:
         - "DELETED\r\n" to indicate success
         - "NOT_FOUND\r\n" to indicate that the item with this key was not found.
       - See the "flush_all" command below for immediate invalidation of all existing items.
+    - "flush_all [<delay>]\r\n":
+       - It always succeeds, and the server sends "OK\r\n" in response (unless "noreply" is given as the last parameter).
+       - Its effect is to invalidate all existing items immediately (by default) or after the
+         expiration specified in <delay>.
+       - After invalidation none of the items will be returned in response to a retrieval command
+         (unless it's stored again under the same key *after* flush_all has invalidated the items).
+       - flush_all doesn't actually free all the memory taken up by existing items; that will happen
+         gradually as new items are stored.
+       - The most precise definition of what flush_all does is the following: it causes all items
+         whose update time is earlier than the time at which flush_all was set to be executed to be
+         ignored for retrieval purposes.
+       - The intent of flush_all with a delay, was that in a setting where you have a pool of
+         memcached servers, and you need to flush all content, you have the option of not resetting
+         all memcached servers at the same time (which could e.g. cause a spike in database load
+         with all clients suddenly needing to recreate content that would otherwise have been found
+         in the memcached daemon). The delay option allows you to have them reset in e.g. 10 second
+         intervals (by passing 0 to the first, 10 to the second, 20 to the third, etc. etc.).
     - increment/decrement:
       - change data for some item in-place, incrementing or decrementing it.
-      - "incr|decr <key> <value> [noreply]\r\n"
-      - <key> is the key of the item the client wishes to change
-      - <value> is the amount by which the client wants to increase/decrease the item. It is a
+      - "incr|decr <key> <value> [noreply]\r\n":
+        - <key> is the key of the item the client wishes to change
+        - <value> is the amount by which the client wants to increase/decrease the item. It is a
         decimal representation of a 64-bit unsigned integer.
-      - "noreply" optional parameter instructs the server to not send the reply.
+        - "noreply" optional parameter instructs the server to not send the reply.
       - The response will be one of:
         - "NOT_FOUND\r\n" to indicate the item with this value was not found
         - "<value>\r\n" , where <value> is the new value of the item's data, after the
@@ -144,7 +161,83 @@ other:
       - Decrementing a number such that it loses length isn't guaranteed to decrement its returned
         length.  The number MAY be space-padded at the end, but this is purely an implementation
         optimization, so you also shouldn't rely on that.
-    - quit:
+    - "quit\r\n":
+      - Upon receiving this command, the server closes the connection. However, the client may also
+        simply close the connection when it no longer needs it, without issuing this command.
+    - slabs automove:
+      - "slabs automove <0|1|2>":
+        - 0|1|2 is the indicator on whether to enable the slabs automover or not.
+          - <0> means to set the thread on standby
+          - <1> means to run the builtin slow algorithm to choose pages to move
+          - <2> is a highly aggressive mode which causes pages to be moved every time there is an
+            eviction. It is not recommended to run for very long in this mode unless your access
+            patterns are very well understood.
+      - The response should always be "OK\r\n"
+    - slabs reassign:
+      - distribute memory once a running instance has hit its limit. It might be desireable to have
+        memory laid out differently than was automatically assigned after the server started.
+      - "slabs reassign <source class> <dest class>\r\n":
+          - <source class> is an id number for the slab class to steal a page from.
+            - A source class id of -1 means "pick from any valid class"
+          - <dest class> is an id number for the slab class to move a page to
+      - The response line could be one of:
+        - "OK" to indicate the page has been scheduled to move
+        - "BUSY [message]" to indicate a page is already being processed, try again later.
+        - "BADCLASS [message]" a bad class id was specified
+        - "NOSPARE [message]" source class has no spare pages
+        - "NOTFULL [message]" dest class must be full to move new pages to it
+        - "UNSAFE [message]" source class cannot move a page right now
+        - "SAME [message]" must specify different source/dest ids.
+      - 1.5.0: "NOTE: This command is subject to change as of this writing."
+    - stats:
+      - "stats\r\n":
+        - it causes the server to output general-purpose statistics and settings, documented below.
+      - "stats <args>\r\n":
+        - Depending on <args>, various internal data is sent by the server. The kinds of arguments
+          and the data sent are not documented in this version of the protocol, and are subject to
+          change for the convenience of memcache developers.
+      - Upon receiving the "stats" command without arguments, the server sents a number of lines
+        which look like this:
+        - "STAT <name> <value>\r\n"
+          - "<name>" is the name of this statistic,
+          - "<value>" is the data.
+      - The server terminates this list with the line:
+        - "END\r\n"
+      - refer to the protocl document for the actual list of values, liable to change on each
+        version of memcached.
+      - "stats settings\r\n":
+        - returns details of the settings of the running memcached.  This is primarily made up of
+          the results of processing commandline options.
+        - these are not guaranteed to return in any specific order and the list in the protocol
+          document may not be exhaustive.  Otherwise, this returns like any other stats command.
+      - "stats items\r\n":
+        - Rows look like "STAT items:<slabclass>:<stat> <value>\r\n"
+          - <slabclass> aligns with class ids used by the "stats slabs" command. Where "stats slabs"
+            describes size and memory usage, "stats items" shows higher level information.
+          - <stat> is the name of the statistic being reported by the row
+          - <value> is the value of the statistic
+      - "stats sizes\r\n":
+        - Rows look like "<size> <count>\r\n"
+          - <size> is an approximate size of the item, within 32 bytes.
+          - <count> is the amount of items that exist within that 32-byte range.
+        - May also return "STAT sizes_status disabled"
+        - Since 1.4.27, needs to be enabled from the CLI or command "STAT sizes_status disabled"
+          which may not work
+        - This is essentially a display of all of your items if there was a slab class for every 32
+          bytes. You can use this to determine if adjusting the slab growth factor would save memory
+          overhead. For example: generating more classes in the lower range could allow items to fit
+          more snugly into their slab classes, if most of your items are less than 200 bytes in size.
+      - "stats sizes_enable\r\n":
+        - enable the histogram at runtime. This has a small overhead to every store or delete
+          operation. If you don't want to incur this, leave it off.
+      - "stats slabs\r\n" Row may look like:
+        - "STAT <slabclass>:<stat> <value>\r\n"
+          - <slabclass> aligns with class ids used by the "stats slabs" command.
+          - <stat> is the name of the statistic being reported by the row
+          - <value> is the value of the statistic
+        - "STAT <stat> <value>\r\n"
+          - <stat> is the name of the statistic being reported by the row
+          - <value> is the value of the statistic
     - touch:
       - update the expiration time of an existing item without fetching it.
       - "touch <key> <exptime> [noreply]\r\n"
@@ -156,6 +249,42 @@ other:
       - The response line to this command can be one of:
         - "TOUCHED\r\n" to indicate success
         - "NOT_FOUND\r\n" to indicate that the item with this key was not found.
+    - "verbosity <level>\r\n":
+      - Always succeeds, and the server sends "OK\r\n" in response (unless "noreply" is given as the
+        last parameter). Its effect is to set the verbosity level of the logging output.
+    - "version\r\n":
+      - Response: "VERSION <version>\r\n"
+        - <version> is the version string for the server.
+udp:
+  uses:
+    - The UDP interface does not provide guaranteed delivery,
+    - so should only be used for operations that aren't required to succeed;
+    - typically used for "get" requests where a missing or incomplete response can simply be treated as a cache miss.
+  format:
+    - Each UDP datagram contains a simple frame header, followed by data in the same format as the
+      TCP protocol described above.
+      - The frame header is 8 bytes long. All values are 16-bit integers in network byte order, high byte first:
+        0-1: Request ID
+          - The request ID is supplied by the client. Typically it will be a monotonically increasing
+            value starting from a random seed, but the client is free to use whatever request IDs it likes.
+          - The server's response will contain the same ID as the incoming request.
+          - The client uses the request ID to differentiate between responses to outstanding requests if
+            there are several pending from the same server;
+          - Any datagrams with an unknown request ID are probably delayed responses to an earlier
+            request and should be discarded.
+        2-3: Sequence number
+          - The sequence number ranges from 0 to n-1, where n is the total number of datagrams in the message.
+          - The client should concatenate the payloads of the datagrams for a given response in
+            sequence number order; the resulting byte stream will contain a complete response in the
+            same format as the TCP protocol (including terminating \r\n sequences).
+        4-5: Total number of datagrams in this message
+        6-7: Reserved for future use; must be 0
+    - In the current implementation, requests must be contained in a single UDP datagram, but
+      responses may span several datagrams.
+    - The only common requests that would span multiple datagrams are huge multi-key "get" requests
+      and "set" requests, both of which are more suitable to TCP transport for reliability reasons
+      anyway.
+
 versions:
   - Some notable changes... see Changelog for full list
   - 2003 / 1.1.10: added flush_all command

+ 112 - 0
third/bloom/jenkins.go

@@ -0,0 +1,112 @@
+/**
+ * Straight copy from:
+ * https://stackoverflow.com/questions/23436358/bob-jenkins-hash-getting-bad-performance
+ *
+ * @license undefined
+ */
+
+package bloom
+
+type jenkinsHash struct {
+}
+
+// adapted from http://bretmulvey.com/hash/7.html
+func (_ jenkinsHash) ComputeHash(data []byte) (uint64, error) {
+	var a, b, c uint64
+	a, b = 0x9e3779b9, 0x9e3779b9
+	c = 0
+	i := 0
+
+	for i = 0; i < len(data)-12; {
+		a += uint64(data[i]) | uint64(data[i+1]<<8) | uint64(data[i+2]<<16) | uint64(data[i+3]<<24)
+		i += 4
+		b += uint64(data[i]) | uint64(data[i+1]<<8) | uint64(data[i+2]<<16) | uint64(data[i+3]<<24)
+		i += 4
+		c += uint64(data[i]) | uint64(data[i+1]<<8) | uint64(data[i+2]<<16) | uint64(data[i+3]<<24)
+
+		a, b, c = mix(a, b, c)
+	}
+
+	c += uint64(len(data))
+
+	if i < len(data) {
+		a += uint64(data[i])
+		i++
+	}
+	if i < len(data) {
+		a += uint64(data[i]) << 8
+		i++
+	}
+	if i < len(data) {
+		a += uint64(data[i]) << 16
+		i++
+	}
+	if i < len(data) {
+		a += uint64(data[i]) << 24
+		i++
+	}
+
+	if i < len(data) {
+		b += uint64(data[i])
+		i++
+	}
+	if i < len(data) {
+		b += uint64(data[i]) << 8
+		i++
+	}
+	if i < len(data) {
+		b += uint64(data[i]) << 16
+		i++
+	}
+	if i < len(data) {
+		b += uint64(data[i]) << 24
+		i++
+	}
+
+	if i < len(data) {
+		c += uint64(data[i]) << 8
+		i++
+	}
+	if i < len(data) {
+		c += uint64(data[i]) << 16
+		i++
+	}
+	if i < len(data) {
+		c += uint64(data[i]) << 24
+		i++
+	}
+
+	a, b, c = mix(a, b, c)
+	return c, nil
+}
+
+func mix(a, b, c uint64) (uint64, uint64, uint64) {
+	a -= b
+	a -= c
+	a ^= (c >> 13)
+	b -= c
+	b -= a
+	b ^= (a << 8)
+	c -= a
+	c -= b
+	c ^= (b >> 13)
+	a -= b
+	a -= c
+	a ^= (c >> 12)
+	b -= c
+	b -= a
+	b ^= (a << 16)
+	c -= a
+	c -= b
+	c ^= (b >> 5)
+	a -= b
+	a -= c
+	a ^= (c >> 3)
+	b -= c
+	b -= a
+	b ^= (a << 10)
+	c -= a
+	c -= b
+	c ^= (b >> 15)
+	return a, b, c
+}

+ 30 - 0
third/bloom/jenkins_test.go

@@ -0,0 +1,30 @@
+package bloom
+
+import (
+	"testing"
+
+	"crypto/sha1"
+	"crypto/sha256"
+)
+
+func BenchmarkJenkins(b *testing.B) {
+	j := jenkinsHash{}
+
+	for i := 0; i < b.N; i++ {
+		j.ComputeHash([]byte{byte(i)})
+	}
+}
+
+func BenchmarkSHA1(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		sha1.Sum([]byte{byte(i)})
+	}
+}
+
+
+func BenchmarkSHA256(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		sha256.Sum256([]byte{byte(i)})
+	}
+}
+