cache_stats 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1afca83ac0a6f24aca3e9b173713e3f5f347166d
4
+ data.tar.gz: 707415500e04d774c91c0f20d80b16d49e85f4dd
5
+ SHA512:
6
+ metadata.gz: 34ddc9a5ba28453968ed332ce053a6f6fa393dd2c9733f1eb2dc5f5d656867b621fc0b2e1e9984dbd6ab01c0826cfe9bfe351112b1f5bdc74ebf9c03a24bcfcb
7
+ data.tar.gz: 28b442f582ac5ba04c9825a609568052a8c9b7dfadc6699b2e37cd9c217719e634aa71b951d5688475020cf01939f6f0ceca95dc085c05eba20c7c24fbadda7a
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem "rake-compiler"
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jeff McDonald
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # CacheStats
2
+
3
+ View file cache residency of files.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'cache_stats'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install cache_stats
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'rake/extensiontask'
2
+
3
+ Rake::ExtensionTask.new("cache_stats")
@@ -0,0 +1,15 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "cache_stats"
5
+ spec.version = "0.0.1"
6
+ spec.authors = ["Jeff McDonald"]
7
+ spec.email = ["jeff@jmickeyd.com"]
8
+ spec.description = "View file cache residency info"
9
+ spec.summary = spec.description
10
+ spec.homepage = "https://github.com/jmickeyd/cache_stats"
11
+ spec.license = "MIT"
12
+
13
+ spec.files = `git ls-files`.split($/)
14
+ spec.extensions = ["ext/cache_stats/extconf.rb"]
15
+ end
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'cache_stats'
6
+
7
+ if ARGV.empty?
8
+ puts "USAGE: #{$0} <file1> [<file2> ...]"
9
+ end
10
+
11
+ ARGV.each do |filename|
12
+ stats = File.cache_stats filename
13
+ print '['
14
+ (0..stats.total_pages - 1).each do |page|
15
+ print stats[page] ? 'X' : ' '
16
+ end
17
+ print '] '
18
+ print "#{stats.cached_pages}/#{stats.total_pages}\n"
19
+ end
@@ -0,0 +1,143 @@
1
+ #ifdef __linux__
2
+ #define _LARGEFILE_SOURCE
3
+ #define _FILE_OFFSET_BITS 64
4
+ #endif
5
+
6
+ #include <fcntl.h>
7
+ #include <stdint.h>
8
+ #include <stdio.h>
9
+ #include <sys/mman.h>
10
+ #include <sys/types.h>
11
+ #include <sys/stat.h>
12
+ #include <unistd.h>
13
+ #include <ruby.h>
14
+ #include <ruby/intern.h>
15
+
16
+ VALUE cache_stats_class;
17
+ uint64_t max_mapping_pages;
18
+ int page_size;
19
+
20
+ typedef struct
21
+ {
22
+ uint64_t num_values;
23
+ uint64_t num_set_values;
24
+ char bitmap[0];
25
+ } cache_stats_t;
26
+
27
+ static void set_bit(cache_stats_t *stats, uint64_t position)
28
+ {
29
+ stats->bitmap[position / 8] |= (1 << (position % 8));
30
+ }
31
+
32
+ static VALUE cache_stats_index(VALUE self, VALUE index)
33
+ {
34
+ long i = NUM2LONG(index);
35
+ cache_stats_t *stats;
36
+ Data_Get_Struct(self, cache_stats_t, stats);
37
+ if (i >= stats->num_values || i < 0)
38
+ return Qnil;
39
+ return (stats->bitmap[i / 8] & (1 << (i % 8))) ? Qtrue : Qfalse;
40
+ }
41
+
42
+ static VALUE cache_stats_total_pages(VALUE self)
43
+ {
44
+ cache_stats_t *stats;
45
+ Data_Get_Struct(self, cache_stats_t, stats);
46
+ return LONG2NUM(stats->num_values);
47
+ }
48
+
49
+ static VALUE cache_stats_cached_pages(VALUE self)
50
+ {
51
+ cache_stats_t *stats;
52
+ Data_Get_Struct(self, cache_stats_t, stats);
53
+ return LONG2NUM(stats->num_set_values);
54
+ }
55
+
56
+ static VALUE file_cache_stats(VALUE self, VALUE file)
57
+ {
58
+ VALUE result = Qnil;
59
+ struct stat file_stats;
60
+
61
+ const char *filename = StringValueCStr(file);
62
+ int fd = open(filename, O_RDONLY);
63
+ if (fd < 0) goto out;
64
+
65
+ if (fstat(fd, &file_stats)) goto close;
66
+
67
+ int file_pages = (file_stats.st_size + page_size - 1) / page_size;
68
+
69
+ cache_stats_t *stats = malloc(sizeof(cache_stats_t) + (file_pages + 7) / 8);
70
+ if (!stats) goto close;
71
+ memset(stats, 0, sizeof(cache_stats_t) + (file_pages + 7) / 8);
72
+ stats->num_values = file_pages;
73
+
74
+ uint64_t local_max_mapping_pages = max_mapping_pages;
75
+ char *override_env = getenv("CACHE_STATS_MAX_MAPPING_PAGES");
76
+ if (override_env)
77
+ {
78
+ uint64_t override = strtoll(override_env, NULL, 10);
79
+ if (override) local_max_mapping_pages = override;
80
+ }
81
+
82
+ size_t vec_size = (file_pages < local_max_mapping_pages) ? file_pages : local_max_mapping_pages;
83
+ char *vec = malloc(vec_size);
84
+ if (!vec) goto close;
85
+
86
+ uint64_t offset_pages = 0;
87
+ do
88
+ {
89
+ uint64_t mapping_pages = (file_pages - offset_pages < local_max_mapping_pages) ? file_pages - offset_pages : local_max_mapping_pages;
90
+
91
+ void *addr = mmap(NULL, mapping_pages * page_size, PROT_READ, MAP_SHARED, fd, offset_pages * page_size);
92
+ if (addr == MAP_FAILED) goto close;
93
+
94
+ if (mincore(addr, mapping_pages * page_size, vec))
95
+ {
96
+ munmap(addr, mapping_pages * page_size);
97
+ goto close;
98
+ }
99
+
100
+ for (int i = 0; i < mapping_pages; ++i)
101
+ {
102
+ if (vec[i] & 1)
103
+ {
104
+ stats->num_set_values++;
105
+ set_bit(stats, i + offset_pages);
106
+ }
107
+ }
108
+
109
+ munmap(addr, mapping_pages * page_size);
110
+ offset_pages += mapping_pages;
111
+ } while ( offset_pages < file_pages);
112
+
113
+ result = Data_Wrap_Struct(cache_stats_class, 0, free, stats);
114
+ close:
115
+ close(fd);
116
+ out:
117
+ return result;
118
+ }
119
+
120
+ void Init_cache_stats()
121
+ {
122
+ if(sizeof(int *) == 4)
123
+ {
124
+ max_mapping_pages = 131072; //512MiB
125
+ }
126
+ else
127
+ {
128
+ max_mapping_pages = UINT64_MAX;
129
+ }
130
+
131
+ page_size = sysconf(_SC_PAGESIZE);
132
+
133
+ cache_stats_class = rb_define_class("CacheStats", rb_cObject);
134
+ rb_define_method(cache_stats_class, "total_pages", cache_stats_total_pages, 0);
135
+ rb_define_method(cache_stats_class, "cached_pages", cache_stats_cached_pages, 0);
136
+ rb_define_method(cache_stats_class, "[]", cache_stats_index, 1);
137
+
138
+ VALUE file_class = rb_const_get(rb_cObject, rb_intern("File"));
139
+ rb_define_singleton_method(file_class,
140
+ "cache_stats",
141
+ file_cache_stats,
142
+ 1);
143
+ }
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile("cache_stats")
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cache_stats
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeff McDonald
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-12 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: View file cache residency info
14
+ email:
15
+ - jeff@jmickeyd.com
16
+ executables: []
17
+ extensions:
18
+ - ext/cache_stats/extconf.rb
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - LICENSE.txt
24
+ - README.md
25
+ - Rakefile
26
+ - cache_stats.gemspec
27
+ - examples/printcache.rb
28
+ - ext/cache_stats/cache_stats.c
29
+ - ext/cache_stats/extconf.rb
30
+ homepage: https://github.com/jmickeyd/cache_stats
31
+ licenses:
32
+ - MIT
33
+ metadata: {}
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 2.0.3
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: View file cache residency info
54
+ test_files: []