Commit 79dd92c8 authored by Sean McGivern's avatar Sean McGivern

Optimise upload path calls

String#underscore isn't particularly slow, but it's possible for us to
call it many times in a users autocomplete request, with mostly-static
values ('User', 'Group', etc.). We can memoise this and save a
surprising amount of time (around 10% of the total request time in some
cases).
parent 513fa603
...@@ -45,7 +45,7 @@ class UploadsController < ApplicationController ...@@ -45,7 +45,7 @@ class UploadsController < ApplicationController
when Appearance when Appearance
true true
else else
permission = "read_#{model.class.to_s.underscore}".to_sym permission = "read_#{model.class.underscore}".to_sym
can?(current_user, permission, model) can?(current_user, permission, model)
end end
......
...@@ -41,4 +41,8 @@ class ApplicationRecord < ActiveRecord::Base ...@@ -41,4 +41,8 @@ class ApplicationRecord < ActiveRecord::Base
find_or_create_by(*args) find_or_create_by(*args)
end end
end end
def self.underscore
Gitlab::SafeRequestStore.fetch("model:#{self}:underscore") { self.to_s.underscore }
end
end end
...@@ -9,6 +9,6 @@ class AttachmentUploader < GitlabUploader ...@@ -9,6 +9,6 @@ class AttachmentUploader < GitlabUploader
private private
def dynamic_segment def dynamic_segment
File.join(model.class.to_s.underscore, mounted_as.to_s, model.id.to_s) File.join(model.class.underscore, mounted_as.to_s, model.id.to_s)
end end
end end
...@@ -25,6 +25,6 @@ class AvatarUploader < GitlabUploader ...@@ -25,6 +25,6 @@ class AvatarUploader < GitlabUploader
private private
def dynamic_segment def dynamic_segment
File.join(model.class.to_s.underscore, mounted_as.to_s, model.id.to_s) File.join(model.class.underscore, mounted_as.to_s, model.id.to_s)
end end
end end
...@@ -20,7 +20,7 @@ class PersonalFileUploader < FileUploader ...@@ -20,7 +20,7 @@ class PersonalFileUploader < FileUploader
def self.model_path_segment(model) def self.model_path_segment(model)
return 'temp/' unless model return 'temp/' unless model
File.join(model.class.to_s.underscore, model.id.to_s) File.join(model.class.underscore, model.id.to_s)
end end
def object_store def object_store
......
---
title: Improve performance of users autocomplete when there are lots of results
merge_request:
author:
type: performance
# coding: utf-8
# frozen_string_literal: true # frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
...@@ -13,7 +14,7 @@ describe SendFileUpload do ...@@ -13,7 +14,7 @@ describe SendFileUpload do
# user/:id # user/:id
def dynamic_segment def dynamic_segment
File.join(model.class.to_s.underscore, model.id.to_s) File.join(model.class.underscore, model.id.to_s)
end end
end end
end end
......
...@@ -13,7 +13,7 @@ FactoryBot.define do ...@@ -13,7 +13,7 @@ FactoryBot.define do
end end
# this needs to comply with RecordsUpload::Concern#upload_path # this needs to comply with RecordsUpload::Concern#upload_path
path { File.join("uploads/-/system", model.class.to_s.underscore, mount_point.to_s, 'avatar.jpg') } path { File.join("uploads/-/system", model.class.underscore, mount_point.to_s, 'avatar.jpg') }
trait :personal_snippet_upload do trait :personal_snippet_upload do
uploader "PersonalFileUploader" uploader "PersonalFileUploader"
......
...@@ -52,4 +52,10 @@ describe ApplicationRecord do ...@@ -52,4 +52,10 @@ describe ApplicationRecord do
expect { Suggestion.find_or_create_by!(note: nil) }.to raise_error(ActiveRecord::RecordInvalid) expect { Suggestion.find_or_create_by!(note: nil) }.to raise_error(ActiveRecord::RecordInvalid)
end end
end end
describe '.underscore' do
it 'returns the underscored value of the class as a string' do
expect(MergeRequest.underscore).to eq('merge_request')
end
end
end end
...@@ -12,7 +12,7 @@ class Implementation < GitlabUploader ...@@ -12,7 +12,7 @@ class Implementation < GitlabUploader
# user/:id # user/:id
def dynamic_segment def dynamic_segment
File.join(model.class.to_s.underscore, model.id.to_s) File.join(model.class.underscore, model.id.to_s)
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment