Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Memory Leaks, Tweaks, and Techniques

Memory Leaks, Tweaks, and Techniques

Richard Schneeman

November 07, 2015
Tweet

More Decks by Richard Schneeman

Other Decks in Programming

Transcript

  1. RAM

  2. #include <stdlib.h> void f(void) { int* x = malloc(10 *sizeof(int));

    x[10] = 0; } int main(void) { f(); return 0; }
  3. #include <stdlib.h> void f(void) { int* x = malloc(10 *sizeof(int));

    x[10] = 0; } int main(void) { f(); return 0; }
  4. $ valgrind --tool=memcheck ./memoryleak ==31747== Memcheck, a memory error detector

    ==31747== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==31747== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==31747== Command: ./memoryleak ==31747== ==31747== Invalid write of size 4 ==31747== at 0x100000F4C: f (memoryleak.c:6) ==31747== by 0x100000F73: main (memoryleak.c:10) ==31747== Address 0x100ae34a8 is 0 bytes after a block of size 40 alloc'd ==31747== at 0x100008EBB: malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/ valgrind/vgpreload_memcheck-amd64-darwin.so) ==31747== by 0x100000F43: f (memoryleak.c:5) ==31747== by 0x100000F73: main (memoryleak.c:10) ==31747== ==31747== ==31747== HEAP SUMMARY: ==31747== in use at exit: 35,304 bytes in 431 blocks ==31747== total heap usage: 503 allocs, 72 frees, 41,272 bytes allocated ==31747== ==31747== LEAK SUMMARY: ==31747== definitely lost: 40 bytes in 1 blocks ==31747== indirectly lost: 0 bytes in 0 blocks ==31747== possibly lost: 0 bytes in 0 blocks ==31747== still reachable: 0 bytes in 0 blocks ==31747== suppressed: 35,264 bytes in 430 blocks ==31747== Rerun with --leak-check=full to see details of leaked memory ==31747== ==31747== For counts of detected and suppressed errors, rerun with: -v ==31747== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
  5. $ valgrind --tool=memcheck ./memoryleak ==31747== Memcheck, a memory error detector

    ==31747== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==31747== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==31747== Command: ./memoryleak ==31747== ==31747== Invalid write of size 4 ==31747== at 0x100000F4C: f (memoryleak.c:6) ==31747== by 0x100000F73: main (memoryleak.c:10) ==31747== Address 0x100ae34a8 is 0 bytes after a block of size 40 alloc'd ==31747== at 0x100008EBB: malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/ valgrind/vgpreload_memcheck-amd64-darwin.so) ==31747== by 0x100000F43: f (memoryleak.c:5) ==31747== by 0x100000F73: main (memoryleak.c:10) ==31747== ==31747== ==31747== HEAP SUMMARY: ==31747== in use at exit: 35,304 bytes in 431 blocks ==31747== total heap usage: 503 allocs, 72 frees, 41,272 bytes allocated ==31747== ==31747== LEAK SUMMARY: ==31747== definitely lost: 40 bytes in 1 blocks ==31747== indirectly lost: 0 bytes in 0 blocks ==31747== possibly lost: 0 bytes in 0 blocks ==31747== still reachable: 0 bytes in 0 blocks ==31747== suppressed: 35,264 bytes in 430 blocks ==31747== Rerun with --leak-check=full to see details of leaked memory ==31747== ==31747== For counts of detected and suppressed errors, rerun with: -v ==31747== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
  6. $ valgrind --tool=memcheck ./memoryleak ==31747== Memcheck, a memory error detector

    ==31747== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==31747== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==31747== Command: ./memoryleak ==31747== ==31747== Invalid write of size 4 ==31747== at 0x100000F4C: f (memoryleak.c:6) ==31747== by 0x100000F73: main (memoryleak.c:10) ==31747== Address 0x100ae34a8 is 0 bytes after a block of size 40 alloc'd ==31747== at 0x100008EBB: malloc (in /usr/local/Cellar/valgrind/3.11.0/lib/ valgrind/vgpreload_memcheck-amd64-darwin.so) ==31747== by 0x100000F43: f (memoryleak.c:5) ==31747== by 0x100000F73: main (memoryleak.c:10) ==31747== ==31747== ==31747== HEAP SUMMARY: ==31747== in use at exit: 35,304 bytes in 431 blocks ==31747== total heap usage: 503 allocs, 72 frees, 41,272 bytes allocated ==31747== ==31747== LEAK SUMMARY: ==31747== definitely lost: 40 bytes in 1 blocks ==31747== indirectly lost: 0 bytes in 0 blocks ==31747== possibly lost: 0 bytes in 0 blocks ==31747== still reachable: 0 bytes in 0 blocks ==31747== suppressed: 35,264 bytes in 430 blocks ==31747== Rerun with --leak-check=full to see details of leaked memory ==31747== ==31747== For counts of detected and suppressed errors, rerun with: -v ==31747== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
  7. Memory “1” “2” “3”“4” “5” “6” “7” RETAINED = []

    1.upto(100_000_000).each do |i| RETAINED << “#{i}” end
  8. def make_objects array = [] 1.upto(100_000_000).each do |i| array <<

    "#{i}" end return nil end make_objects GC.start(full_mark: true, immediate_sweep: true)
  9. def make_objects array = [] 1.upto(100_000_000).each do |i| array <<

    "#{i}" end return nil end make_objects GC.start(full_mark: true, immediate_sweep: true)
  10. def make_objects array = [] 1.upto(100_000_000).each do |i| array <<

    "#{i}" end return nil end make_objects GC.start(full_mark: true, immediate_sweep: true)
  11. WAT

  12. GC.start(full_mark: true, immediate_sweep: true) GC.disable # Code goes here before

    = GC.stat[:total_freed_objects] GC.enable GC.start(full_mark: true, immediate_sweep: true) after = GC.stat[:total_freed_objects] # => “Objects cleared by GC: 100_010_687”
  13. #include <stdlib.h> void f(void) { int* x = malloc(10 *sizeof(int));

    x[10] = 0; } int main(void) { f(); return 0; }
  14. No

  15. $ bundle exec derailed bundle:mem TOP: 54.1836 MiB mail: 18.9688

    MiB mime/types: 17.4453 MiB mail/field: 0.4023 MiB mail/message: 0.3906 MiB action_view/view_paths: 0.4453 MiB action_view/base: 0.4336 MiB
  16. $ bundle exec derailed exec perf:objects # ... ## allocated

    memory by location --------------------------------------- 1935548 /Users/richardschneeman/.gem/ruby/2.2.3/gems/actionpack-4.2.3/lib/action_dispa 896100 /Users/richardschneeman/.gem/ruby/2.2.3/gems/pg-0.16.0/lib/pg/result.rb:10 741488 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerecord-4.2.3/lib/active_rec 689299 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activesupport-4.2.3/lib/active_su 660672 /Users/richardschneeman/.gem/ruby/2.2.3/gems/actionpack-4.2.3/lib/action_dispa 606384 /Users/richardschneeman/Documents/projects/codetriage/app/views/repos/\_repo.h 579384 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activesupport-4.2.3/lib/active\_s 532800 /Users/richardschneeman/.gem/ruby/2.2.3/gems/actionpack-4.2.3/lib/action_dispa 391392 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerecord-4.2.3/lib/active_rec 385920 /Users/richardschneeman/.gem/ruby/2.2.3/gems/temple-0.7.5/lib/temple/utils.rb:
  17. $ PATH_TO_HIT=rails/rails bundle exec derailed exec perf:objects Booting: production Running

    1 times Total allocated: 21495556 bytes (207735 objects) Total retained: 15041423 bytes (133220 objects) allocated memory by gem ----------------------------------- 19427636 activerecord-4.2.3 1471380 activesupport-4.2.3 214048 actionview-4.2.3 151066 actionpack-4.2.3 121983 codetriage/app 24308 will_paginate-3.0.7 23193 rack-1.6.4 21105 arel-6.0.3 13397 ruby-2.2.3/lib 5560 warden-1.2.3 5536 rack-timeout-0.3.2 3912 activemodel-4.2.3 3000 hashie-3.4.2 2154 devise-3.5.2 1573 omniauth-1.2.2 1536 i18n-0.7.0 1495 railties-4.2.3 787 temple-0.7.6
  18. Per

  19. allocated memory by location ----------------------------------- 5131624 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerec 4616480 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerec 1336408

    /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerec 1336088 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerec 1330904 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerec 1325648 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerec 921807 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activesup 737376 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerec 596288 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerec 460720 /Users/richardschneeman/.gem/ruby/2.2.3/gems/activerec
  20. ???

  21. allocated objects by class ----------------------------------- 108939 String 35456 Hash 21605

    Array 5890 Proc 5886 RubyVM::Env 5859 ActiveRecord::Attribute::FromDatabase 5759 ActiveRecord::AttributeSet 5759 ActiveRecord::LazyAttributeHash 5731 ActiveRecord::Associations::BelongsToAssociation 5731 Issue 217 ActiveSupport::SafeBuffer 173 MatchData 112 ActionView::OutputBuffer 59 Time 43 ActiveRecord::Relation 42 ActiveRecord::ConnectionAdapters::PostgreSQL::Name 27 ActiveRecord::AssociationRelation 27 User }
  22. allocated objects by class ----------------------------------- 108939 String 35456 Hash 21605

    Array 5890 Proc 5886 RubyVM::Env 5859 ActiveRecord::Attribute::FromDatabase 5759 ActiveRecord::AttributeSet 5759 ActiveRecord::LazyAttributeHash 5731 ActiveRecord::Associations::BelongsToAssociation 5731 Issue 217 ActiveSupport::SafeBuffer 173 MatchData 112 ActionView::OutputBuffer 59 Time 43 ActiveRecord::Relation 42 ActiveRecord::ConnectionAdapters::PostgreSQL::Name 27 ActiveRecord::AssociationRelation 27 User }
  23. allocated objects by class ----------------------------------- 108939 String 35456 Hash 21605

    Array 5890 Proc 5886 RubyVM::Env 5859 ActiveRecord::Attribute::FromDatabase 5759 ActiveRecord::AttributeSet 5759 ActiveRecord::LazyAttributeHash 5731 ActiveRecord::Associations::BelongsToAssociation 5731 Issue 217 ActiveSupport::SafeBuffer 173 MatchData 112 ActionView::OutputBuffer 59 Time 43 ActiveRecord::Relation 42 ActiveRecord::ConnectionAdapters::PostgreSQL::Name 27 ActiveRecord::AssociationRelation 27 User
  24. allocated objects by class ----------------------------------- 108939 String 35456 Hash 21605

    Array 5890 Proc 5886 RubyVM::Env 5859 ActiveRecord::Attribute::FromDatabase 5759 ActiveRecord::AttributeSet 5759 ActiveRecord::LazyAttributeHash 5731 ActiveRecord::Associations::BelongsToAssociation 5731 Issue 217 ActiveSupport::SafeBuffer 173 MatchData 112 ActionView::OutputBuffer 59 Time 43 ActiveRecord::Relation 42 ActiveRecord::ConnectionAdapters::PostgreSQL::Name 27 ActiveRecord::AssociationRelation 27 User
  25. Started GET "/rails/rails" for ::1 at 2015-11-04 14:54:55 -0600 ActiveRecord::SchemaMigration

    Load (19.2ms) SELECT "schema_migrations".* FROM "schema_migration Processing by ReposController#show as HTML Parameters: {"full_name"=>"rails/rails"} Repo Load (21.2ms) SELECT "repos".* FROM "repos" WHERE "repos"."full_name" = $1 LIMIT 1 [["fu source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=1006ms state=activ Issue Load (1091.1ms) SELECT "issues".* FROM "issues" WHERE "issues"."repo_id" IN (36) source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=2093ms state=activ source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=3101ms state=activ source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=4027ms state=activ (48.1ms) SELECT COUNT(*) FROM "users" INNER JOIN "repo_subscriptions" ON "users"."id" = "repo_ User Load (53.4ms) SELECT "users".* FROM "users" INNER JOIN "repo_subscriptions" ON "users"."i Rendered subscribers/_avatars.html.slim (138.9ms) CACHE (0.0ms) SELECT COUNT(*) FROM "users" INNER JOIN "repo_subscriptions" ON "users"."id" = "r (0.6ms) SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "users" INNER JOIN "re 36]] Issue Load (41.8ms) SELECT "issues".* FROM "issues" WHERE "issues"."repo_id" = $1 AND "issues" (44.2ms) SELECT COUNT(*) FROM "issues" WHERE "issues"."repo_id" = $1 AND "issues"."state" = $2 Rendered repos/show.html.slim within layouts/application (496.5ms) source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=5005ms state=activ Rendered application/_head.html.slim (1360.4ms) Rendered application/_flashes.html.slim (15.9ms) Rendered application/_logo.html.slim (21.5ms) Rendered application/_nav.html.slim (73.0ms) Rendered application/_thoughtbot.html.slim (11.5ms) Rendered application/_footer.html.slim (36.4ms) Completed 200 OK in 5760ms (Views: 1889.1ms | ActiveRecord: 1323.2ms) source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=6004ms state=activ
  26. Started GET "/rails/rails" for ::1 at 2015-11-04 14:54:55 -0600 ActiveRecord::SchemaMigration

    Load (19.2ms) SELECT "schema_migrations".* FROM "schema_migration Processing by ReposController#show as HTML Parameters: {"full_name"=>"rails/rails"} Repo Load (21.2ms) SELECT "repos".* FROM "repos" WHERE "repos"."full_name" = $1 LIMIT 1 [["fu source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=1006ms state=activ Issue Load (1091.1ms) SELECT "issues".* FROM "issues" WHERE "issues"."repo_id" IN (36) source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=2093ms state=activ source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=3101ms state=activ source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=4027ms state=activ (48.1ms) SELECT COUNT(*) FROM "users" INNER JOIN "repo_subscriptions" ON "users"."id" = "repo_ User Load (53.4ms) SELECT "users".* FROM "users" INNER JOIN "repo_subscriptions" ON "users"."i Rendered subscribers/_avatars.html.slim (138.9ms) CACHE (0.0ms) SELECT COUNT(*) FROM "users" INNER JOIN "repo_subscriptions" ON "users"."id" = "r (0.6ms) SELECT COUNT(count_column) FROM (SELECT 1 AS count_column FROM "users" INNER JOIN "re 36]] Issue Load (41.8ms) SELECT "issues".* FROM "issues" WHERE "issues"."repo_id" = $1 AND "issues" (44.2ms) SELECT COUNT(*) FROM "issues" WHERE "issues"."repo_id" = $1 AND "issues"."state" = $2 Rendered repos/show.html.slim within layouts/application (496.5ms) source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=5005ms state=activ Rendered application/_head.html.slim (1360.4ms) Rendered application/_flashes.html.slim (15.9ms) Rendered application/_logo.html.slim (21.5ms) Rendered application/_nav.html.slim (73.0ms) Rendered application/_thoughtbot.html.slim (11.5ms) Rendered application/_footer.html.slim (36.4ms) Completed 200 OK in 5760ms (Views: 1889.1ms | ActiveRecord: 1323.2ms) source=rack-timeout id=22a6fea79c2f050a9d9999b007298d12 timeout=30000ms service=6004ms state=activ
  27. No

  28. allocated memory by location ----------------------------------- 5131624 active_record/result.rb:116 1336408 active_record/attribute_set/builder.rb:30 1336088

    active_record/persistence.rb:69 1330904 active_record/core.rb:547 1325648 active_record/attribute_methods.rb:359 921807 active_support/callbacks.rb:81 737376 active_record/core.rb:114 596288 active_record/associations.rb:162 460720 active_record/attribute_set/builder.rb:16