- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我最近注意到,自从我更新到 Java 7 后,我的代码的特定部分运行速度明显变慢。这非常令人惊讶,因为 Java 7 在全局范围内比 Java 6 更快。
该程序非常大,但我成功提取了可重现的代码来演示 java 7 比 Java 6 慢的原因。
如果您使用 Java 6 和 Java 7 运行完全相同的代码,您会发现 Java 7 大约比 Java 6 慢 7-8 倍!!!
这是代码(不要费心去理解它的作用,它只是对真实代码的抽象,因此没有任何意义)。它基本上是一个解析字符串以格式化它的某些部分的代码:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
public class CPerfJava7 extends JFrame {
private static final long serialVersionUID = 1L;
// +==============================================================+
// | Attributes |
// +==============================================================+
JPanel mainPanel;
public CPseudoHtmlDocument docu;
private static long totalTime = 0;
// +==============================================================+
// | Constructors |
// +==============================================================+
public CPerfJava7() {
super("PerfJava7");
docu = new CPseudoHtmlDocument();
mainPanel = new JPanel(new BorderLayout());
JTextPane textPane = new JTextPane();
textPane.setDocument(docu);
textPane.setText("testcase one\ndo program breakfast meal\ndo program time\ndo program portion size - 1/4 of the cup\nIt was easy to set up the time and portion size as directed in the manual\n\ndo collect kibbles from the bowl and measure the breakfast portion\ncheck the portion dispensed 1/4 cup of kibbles \nActual result - it was less than 1/4 cup. The wheel that rotates and dispenses\n the kibbles might haven't rotated completely.\n\ntestcase two\ndo program lunch meal\ndo program time\ndo leave the portion size the same - 1/4 of the cup\n\ncheck the portion dispensed 1/4 cup of kibbles\n do collect kibbles from the bowl and measure the lunch portion\nActual result was 1/20 of the cup, the wheel dispenser hardly released any kibbles\n\ntestcase three\n\ndo program dinner meal\ndo program time\ndo leave the portion size the same - 1/4 of the cup\n\ncheck the portion dispensed 1/4 cup of kibbles\n do collect kibbles from the bowl and measure the dinner portion\nActual result was less than 1/4 cup\n\nWhy was the middle meal the smallest? Is lunch always the smallest?\nTo prove this hypothesis, repeat first three test cases again.\n\ntestcase four\ndo repeat test case one\nActual result - it was less 1/4 and the portion was dispensed in two increments.\n\ntestcase five\ndo repeat test case two\nActual result - 1/8 of the cup.\n\ntestcase six\ndo repeat test case three\nActual result - 1/2 cup! The wheel rotated almost twice. It looked like all\n kibbles which were not dispensed previously, got released.\n Lunch was still the smallest meal, but the dinner portion was twice of the size\n.All three tests must be repeated again.\n\ntestcase seven\ndo repeat test case one\nActual result - 1/4 of the cup. Great!\n\ntestcase eight\ndo repeat test case two\nActual result - 1/4 of the cup! It works perfectly! Why?\n\ntestcase nine\ndo repeat test case three\nActual result - 1/6, so the third meal was less than it should be. Is this size of the portion hard to dispense correctly? Let's try 1/2 of the cup\n\ntestcase ten\ndo program breakfast meal\ndo program time\ndo program 1/2 of the cup\ncheck the amount of kibbles dispensed is 1/2 of the cup\nActual result - 1/2 of the cup. Excellent. The wheel rotated twice as designed. In a minute it added 1/4 of the cup.\n\ntestcase eleven\ndo program lunch meal\ndo program time\ndo leave the portion size the same\ncheck the amount of kibbles dispensed is 1/2 of the cup\nActual result - 1/3 of the cup. Lunch is smaller again.\n\testcase twelve\ndo program dinner meal\ndo program time\ndo leave the portion size the same - 1/2 of the cup\ncheck the amount of kibbles dispensed is 1/2 of the cup\nActual result - 1/2, the portion was dispensed in 2 increments with the interval. As there is no consistency again, let test this portion size one more time.\n \ntestcase thirteen\ndo repeat test case ten\ncheck the amount of kibbles is 1/2 of the cup\nActual result - a bit less than 1/2\n\n\ntestcase fourteen\ndo repeat test case eleven\ncheck the portion size is 1/2 of the cup\nActual result - a bit more than 1/2. This portion size looks more stable. The lunch isn't the smallest anymore.\n\ntestcase fiftee\ndo repeat test case twelve\ncheck portion size is 1/2 of the cup\nActual result - is l/2, a bit less of the exact amount. All three meals were served with almost correct portion size.\n\n\n- \n\n\n");
mainPanel.add(new JScrollPane(textPane), BorderLayout.CENTER);
setContentPane(mainPanel);
}
public static void main(String[] args) {
CPerfJava7 frame;
WindowListener exitListener = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Window window = e.getWindow();
window.setVisible(false);
window.dispose();
System.exit(0);
}
};
frame = new CPerfJava7();
frame.addWindowListener(exitListener);
frame.setPreferredSize(new Dimension(600, 400));
frame.pack();
frame.setVisible(true);
try {
// run it to warm it up
frame.docu.doParse();
frame.docu.doParse();
frame.docu.doParse();
frame.docu.doParse();
frame.docu.doParse();
frame.docu.doParse();
// then do real measures
totalTime = 0;
for (int k=0; k<50; k++) {
frame.docu.doParse();
}
System.err.println(" AVERAGE = " + (totalTime/50));
} catch (Exception e) {
e.printStackTrace();
}
}
/*
+----------------------------------------------------------------------+
| Class: CPseudoHtmlDocument |
+----------------------------------------------------------------------+
*/
@SuppressWarnings("serial")
public class CPseudoHtmlDocument extends DefaultStyledDocument {
// +==============================================================+
// | Attribute(s) |
// +==============================================================+
private final SimpleAttributeSet attrNormal = new SimpleAttributeSet();
private final SimpleAttributeSet attrSpecial = new SimpleAttributeSet();
private final SimpleAttributeSet attrDefault = new SimpleAttributeSet();
private int currentPos = 0;
// +==============================================================+
// | Constructor(s) |
// +==============================================================+
public CPseudoHtmlDocument() {
StyleConstants.setForeground(attrSpecial, Color.decode("0xC71D15"));StyleConstants.setBold(attrSpecial, true);
StyleConstants.setForeground(attrDefault, new Color(150, 150, 0));
StyleConstants.setBold(attrDefault, true);
}
// +==============================================================+
// | Method(s) |
// +==============================================================+
public long getCurrentTimeMillis() {
Calendar now = Calendar.getInstance();
return now.getTimeInMillis();
}
public String getCurrentLogTime() {
Calendar now = Calendar.getInstance();
return calendarToPreciseTimeOfTheDay(now);
}
public String calendarToPreciseTimeOfTheDay (Calendar calendar) {
SimpleDateFormat localSimpleDateFormat = new SimpleDateFormat("HH:mm:ss.S");
return localSimpleDateFormat.format(calendar.getTime());
}
private void doParse() {
long before = getCurrentTimeMillis();
setCharacterAttributes(0, 3260, new SimpleAttributeSet(), true); // reset all the text to review (including the rewinded part) with normal attribute
for (int i = 0; i <= 3260; i++) {
currentPos = i;
checkForKeyword(true);
}
long after = getCurrentTimeMillis();
totalTime += (after-before);
System.err.println(" -> time to parse: " + (after-before) + " ms");
}
private void checkForKeyword(boolean insert) {
int preceedingStartTag, nextStopTag, preceedingPercentTag, nextPercentTag, preceedingSpace, nextSpace;
char currentChar = ' ';
try {
currentChar = this.getText(currentPos, 1).charAt(0);
} catch (BadLocationException e1) {
}
if (currentChar == '[') {
nextStopTag = getNextStop(currentPos+1, true);
setStyle(currentPos, nextStopTag); // check if this is a [xxx] we need to highlight
} else if (currentChar == ']') {
preceedingStartTag = getPreceedingStart(currentPos-1, true); // returns -1 if not found or another [, ], \n or space found first
setStyle(preceedingStartTag, currentPos); // check if this is a [xxx] we need to highlight
} else if (currentChar == '%') {
nextPercentTag = getNextPercent(currentPos+1, true); // returns -1 if not found or \n or space found first
if (nextPercentTag >= 0) {
// removed code
}
} else {
// [xxx]
preceedingStartTag = getPreceedingStart(currentPos-1, true); // returns -1 if not found or another ], \n or space found first
nextStopTag = getNextStop(currentPos, true); // returns -1 if not found or another [, \n or space found first
if (preceedingStartTag >=0 && nextStopTag >=0) {
setStyle(preceedingStartTag, nextStopTag);
}
// PARAMS
preceedingPercentTag = getPreceedingPercent(currentPos-1, true); // returns -1 if not found or another [, ], \n or space found first
nextPercentTag = getNextPercent(currentPos, true); // returns -1 if not found or another [, ], \n or space found first
if (preceedingPercentTag >=0 && nextPercentTag >=0) {
}
// PDNL
preceedingSpace = getPreceedingSpace(currentPos-1, true); // returns -1 if another [, ] or % found first, 0 if not found
nextSpace = getNextSpace(currentPos, true); // returns -1 if not found or another [, ] or % found first, length-1 if not found
if (preceedingSpace >=0 && nextSpace >=0) {
if (preceedingSpace == 0) preceedingSpace--; // keyword at the very beginning of the text
setStyle(preceedingSpace+1, nextSpace-1);
}
}
}
private int getPreceedingStart(int offset, boolean strict) {
while (offset >= 0) {
try {
char charAt = this.getText(offset, 1).charAt(0);
if (charAt == '[') {
return offset;
} else if (charAt == ']' || charAt == '%' || charAt == ' ' || charAt == '\n' || charAt == '\r' || charAt == '\t') {
if (strict)
return -1;
}
} catch (BadLocationException e) {
e.printStackTrace();
}
offset--;
}
if (strict)
return -1;
else
return 0;
}
private int getNextStop(int offset, boolean strict) {
while (true) {
try {
char charAt = this.getText(offset, 1).charAt(0);
if (charAt == ']') {
return offset;
} else if (charAt == '[' || charAt == '%' || charAt == ' ' || charAt == '\n' || charAt == '\r' || charAt == '\t') {
if (strict)
return -1;
}
} catch (BadLocationException e) {
if (strict)
return -1;
else
return offset-1;
}
offset++;
}
}
private int getPreceedingPercent(int offset, boolean strict) {
while (offset >= 0) {
try {
char charAt = this.getText(offset, 1).charAt(0);
if (charAt == '%') {
return offset;
} else if (charAt == ' ' || charAt == '\n' || charAt == '\r' || charAt == '\t') {
if (strict)
return -1;
}
} catch (BadLocationException e) {
e.printStackTrace();
}
offset--;
}
if (strict)
return -1;
else
return 0;
}
private int getNextPercent(int offset, boolean strict) {
while (true) {
try {
char charAt = this.getText(offset, 1).charAt(0);
if (charAt == '%') {
return offset;
} else if (charAt == ' ' || charAt == '\n' || charAt == '\r' || charAt == '\t') {
if (strict)
return -1;
}
} catch (BadLocationException e) {
if (strict)
return -1;
else
return offset;
}
offset++;
}
}
private int getPreceedingSpace(int offset, boolean strict) {
while (offset >= 0) {
try {
char charAt = this.getText(offset, 1).charAt(0);
if (charAt == ' ' || charAt == '\n' || charAt == '\r' || charAt == '\t') {
return offset;
} else if (charAt == '%' || charAt == '[' || charAt == ']') {
if (strict)
return -1;
}
} catch (BadLocationException e) {
e.printStackTrace();
}
offset--;
}
return 0;
}
private int getNextSpace(int offset, boolean strict) {
while (true) {
try {
char charAt = this.getText(offset, 1).charAt(0);
if (charAt == ' ' || charAt == '\n' || charAt == '\r' || charAt == '\t') {
return offset;
} else if (charAt == '%' || charAt == '[' || charAt == ']') {
if (strict)
return -1;
}
} catch (BadLocationException e) {
return offset-1;
}
offset++;
}
}
private void setStyle(int startTag, int stopTag) {
if (startTag >= 0 && stopTag > 0 && stopTag > startTag) {
int tagLength = stopTag-startTag+1;
try {
String tag = this.getText(startTag, tagLength);
String s = tag.trim()/*.toLowerCase()*/;
if (s.equals("testcase") || s.equals("do") || s.equals("check") || s.equals("and")) {
setCharacterAttributes(startTag, tagLength, attrSpecial, true);
} else {
setCharacterAttributes(startTag, tagLength, attrNormal, true);
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
}
}
在我的计算机上,如果我使用 Java 6 运行它,我的平均运行时间为 60 毫秒。
如果我使用 Java 7 运行它,它将花费 460 毫秒。
我是唯一注意到这一点的人吗?谢谢,
编辑:这是证明 错误方法是 Java 7 中的 DefaultStyledDocument.setCharacaterAttributes() 的新程序:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.Calendar;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
public class CPerfJava7_justSetCharacterAttributes extends JFrame {
private static final long serialVersionUID = 1L;
// +==============================================================+
// | Attributes |
// +==============================================================+
JPanel mainPanel;
public CPseudoHtmlDocument docu;
// +==============================================================+
// | Constructors |
// +==============================================================+
public CPerfJava7_justSetCharacterAttributes() {
super("PerfJava7");
docu = new CPseudoHtmlDocument();
mainPanel = new JPanel(new BorderLayout());
JTextPane textPane = new JTextPane();
textPane.setDocument(docu);
textPane.setText("testcase one\ndo program breakfast meal\ndo program time\ndo program portion size - 1/4 of the cup\nIt was easy to set up the time and portion size as directed in the manual\n\ndo collect kibbles from the bowl and measure the breakfast portion\ncheck the portion dispensed 1/4 cup of kibbles \nActual result - it was less than 1/4 cup. The wheel that rotates and dispenses\n the kibbles might haven't rotated completely.\n\ntestcase two\ndo program lunch meal\ndo program time\ndo leave the portion size the same - 1/4 of the cup\n\ncheck the portion dispensed 1/4 cup of kibbles\n do collect kibbles from the bowl and measure the lunch portion\nActual result was 1/20 of the cup, the wheel dispenser hardly released any kibbles\n\ntestcase three\n\ndo program dinner meal\ndo program time\ndo leave the portion size the same - 1/4 of the cup\n\ncheck the portion dispensed 1/4 cup of kibbles\n do collect kibbles from the bowl and measure the dinner portion\nActual result was less than 1/4 cup\n\nWhy was the middle meal the smallest? Is lunch always the smallest?\nTo prove this hypothesis, repeat first three test cases again.\n\ntestcase four\ndo repeat test case one\nActual result - it was less 1/4 and the portion was dispensed in two increments.\n\ntestcase five\ndo repeat test case two\nActual result - 1/8 of the cup.\n\ntestcase six\ndo repeat test case three\nActual result - 1/2 cup! The wheel rotated almost twice. It looked like all\n kibbles which were not dispensed previously, got released.\n Lunch was still the smallest meal, but the dinner portion was twice of the size\n.All three tests must be repeated again.\n\ntestcase seven\ndo repeat test case one\nActual result - 1/4 of the cup. Great!\n\ntestcase eight\ndo repeat test case two\nActual result - 1/4 of the cup! It works perfectly! Why?\n\ntestcase nine\ndo repeat test case three\nActual result - 1/6, so the third meal was less than it should be. Is this size of the portion hard to dispense correctly? Let's try 1/2 of the cup\n\ntestcase ten\ndo program breakfast meal\ndo program time\ndo program 1/2 of the cup\ncheck the amount of kibbles dispensed is 1/2 of the cup\nActual result - 1/2 of the cup. Excellent. The wheel rotated twice as designed. In a minute it added 1/4 of the cup.\n\ntestcase eleven\ndo program lunch meal\ndo program time\ndo leave the portion size the same\ncheck the amount of kibbles dispensed is 1/2 of the cup\nActual result - 1/3 of the cup. Lunch is smaller again.\n\testcase twelve\ndo program dinner meal\ndo program time\ndo leave the portion size the same - 1/2 of the cup\ncheck the amount of kibbles dispensed is 1/2 of the cup\nActual result - 1/2, the portion was dispensed in 2 increments with the interval. As there is no consistency again, let test this portion size one more time.\n \ntestcase thirteen\ndo repeat test case ten\ncheck the amount of kibbles is 1/2 of the cup\nActual result - a bit less than 1/2\n\n\ntestcase fourteen\ndo repeat test case eleven\ncheck the portion size is 1/2 of the cup\nActual result - a bit more than 1/2. This portion size looks more stable. The lunch isn't the smallest anymore.\n\ntestcase fiftee\ndo repeat test case twelve\ncheck portion size is 1/2 of the cup\nActual result - is l/2, a bit less of the exact amount. All three meals were served with almost correct portion size.\n\n\n- \n\n\n");
mainPanel.add(new JScrollPane(textPane), BorderLayout.CENTER);
setContentPane(mainPanel);
}
public static void main(String[] args) {
CPerfJava7_justSetCharacterAttributes frame;
WindowListener exitListener = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Window window = e.getWindow();
window.setVisible(false);
window.dispose();
System.exit(0);
}
};
frame = new CPerfJava7_justSetCharacterAttributes();
frame.addWindowListener(exitListener);
frame.setPreferredSize(new Dimension(600, 400));
frame.pack();
frame.setVisible(true);
try {
// run it to warm it up
frame.docu.doParse();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
+----------------------------------------------------------------------+
| Class: CPseudoHtmlDocument |
+----------------------------------------------------------------------+
*/
@SuppressWarnings("serial")
public class CPseudoHtmlDocument extends DefaultStyledDocument {
private final SimpleAttributeSet attrDefault = new SimpleAttributeSet();
public CPseudoHtmlDocument() {
StyleConstants.setForeground(attrDefault, new Color(150, 150, 0));
StyleConstants.setBold(attrDefault, true);
}
public long getCurrentTimeMillis() {
Calendar now = Calendar.getInstance();
return now.getTimeInMillis();
}
private void doParse() {
long before = getCurrentTimeMillis();
for (int k=0; k<5; k++) {
for (int i = 0; i <= 3260; i+=1) {
setStyle(i, i+1);
}
}
long after = getCurrentTimeMillis();
System.err.println(" -> time to parse: " + (after-before) + " ms");
}
private void setStyle(int startTag, int stopTag) {
int tagLength = stopTag-startTag+1;
setCharacterAttributes(startTag, tagLength, attrDefault, true);
}
}
}
在我的电脑上:
Java 6:~1 秒
Java 7:~4.5 秒
有什么方法可以让它在 Java 7 中像在 Java 6 中一样快?谢谢,
编辑:这是修复性能的解决方法。 Java 7 的问题(我是在 insertString() 和 remove() 上做的):
public void remove(int offset, int length) throws BadLocationException {
// start by removing normally the string using the default styled document
try {
super.remove(offset, length);
} catch (Exception e) {
e.printStackTrace();
}
int caretPosition = textPane.getCaretPosition();
textPane.setDocument(new DefaultStyledDocument());
// DO HERE THE TIME-CONSUMING TASKS THAT APPLY SOME STYLES ON THE CURRENT DOCUMENT
textPane.setDocument(this);
textPane.setCaretPosition(caretPosition);
}
最佳答案
我认为问题不在于文档,而在于 View 结构布局的差异。
尝试创建一个没有 JTextPane 的文档并应用所有样式。
在 java7 中引入了断点计算来定义可以包装 View 的位置。布局中存在错误,请参阅 Strange text wrapping with styled text in JTextPane with Java 7
猜想简单的布局也会发生同样的情况。
您可以尝试使用 ParagraphView 和 LabelView View ,看看布局的不同变化如何极大地改变性能。
关于Java 7 在一些基本的解析任务上比 Java 6 慢 8 倍,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19877641/
自己试试看: import pandas as pd s=pd.Series(xrange(5000000)) %timeit s.loc[[0]] # You need pandas 0.15.1
我最近开始使用 Delphi 中的 DataSnap 来生成 RESTful Web 服务。在遵循 Marco Cantu 本人和互联网上其他几个人的指导后,我成功地使整个“链条”正常工作。 但是有一
我一直在为操作系统类(class)编写以下代码,但结果有些奇怪。该代码创建x线程并同时运行它们,以便将两个平方矩阵相乘。每个线程将输入矩阵的Number_of_rows/Number_of_threa
我正在尝试确定何时使用 parallel包以加快运行某些分析所需的时间。我需要做的一件事是创建矩阵,比较具有不同行数的两个数据框中的变量。我在 StackOverflow 上问了一个关于有效方法的问题
我最近对我的代码进行了一些清理,并在此过程中更改了此内容(不完全是真实的代码): read = act readSTRef test1 term i var = do t v^!terms.
我正在计时查询和同一个查询的执行时间,分页。 foreach (var x in productSource.OrderBy(p => p.AdminDisplayName) .Wher
我正在开发一个项目 (WPF),我有一个 Datagrid 从数据库加载超过 5000 条记录,所以我使用 BackgroundWorker 来通知用户数据正在加载,但它太慢了,我需要等待将近 2分钟
我在查询中添加 ORDER BY 时遇到问题。没有 ORDER BY 查询大约需要 26ms,一旦我添加 ORDER BY,它大约需要 20s。 我尝试了几种不同的方法,但似乎可以减少时间。 尝试 F
我是 Android 开发新手,遇到了性能问题。当我的 GridView 有太多项目时,它会变得有点慢。有什么方法可以让它运行得更快一些吗? 这是我使用的代码: 适配器: public class C
这里的要点是: 1.设置query_cache_type = 0;重置查询缓存; 2.在 heidisql(或任何其他客户端 UI)中运行任何查询 --> 执行,例如 45 毫秒 3.使用以下代码运行
想象下表: CREATE TABLE drops( id BIGSERIAL PRIMARY KEY, loc VARCHAR(5) NOT NULL, tag INT NOT
我的表 test_table 中的示例数据: date symbol value created_time 2010-01-09 symbol1
首先,如果已经有人问过这个问题,我深表歉意,至少我找不到任何东西。 无论如何,我将每 5 分钟运行一次 cron 任务。该脚本加载 79 个外部页面,而每个页面包含大约 200 个我需要在数据库中检查
我有下面的 SQL 代码,它来自 MySQL 数据库。现在它给了我期望的结果,但是查询很慢,我想我应该在进一步之前加快这个查询的速度。 表agentstatusinformation有: PKEY(主
我需要获取一个对象在 Core Data 中数千个其他对象之间的排名。现在,这是我的代码: - (void)rankMethod { //Fetch all objects NSFet
我正在编写一个应用程序,我需要在其中读取用户的地址簿并显示他所有联系人的列表。我正在测试的 iPhone 有大约 100 个联系人,加载联系人确实需要很多时间。 ABAddressBookRef ad
我正在使用 javascript 将 160 行添加到包含 10 列的表格中。如果我这样做: var cellText = document.createTextNode(value); cell.a
我是 Swift 的新手,我已经设置了一个 tableView,它从 JSON 提要中提取数据并将其加载到表中。 表格加载正常,但是当表格中有超过 10 个单元格时,它会变得缓慢且有些滞后,特别是它到
我在 InitializeCulture 和 Page_PreInit 事件之间的 asp.net 页面中遇到性能问题。当我重写 DeterminePostBackMode() 时,我发现问题出在 b
我在 Hetzner 上有一个带有 256GB RAM 6 个 CPU(12 个线程) 的专用服务器,它位于德国。我有 CENTOS 7.5。 EA4。 我的问题是 SSL。每天大约 2 小时,我们在
我是一名优秀的程序员,十分优秀!